EXPLAIN VS EXPLAIN ANALYZE EN MYSQL: DIFERENCIAS Y CÓMO INTERPRETAR UN PLAN DE EJECUCIÓN

Cuando una consulta tarda más de lo esperado, el primer paso suele ser examinar el plan de ejecución. En MySQL existen dos herramientas principales para esto: EXPLAIN y EXPLAIN ANALYZE. No son intercambiables y conviene saber exactamente qué aporta cada una.

Qué hace EXPLAIN

EXPLAIN muestra el plan que el optimizador ha elegido basándose en las estadísticas disponibles. No ejecuta la consulta, solo estima.

Ejemplo básico

EXPLAIN SELECT * FROM pedidos WHERE cliente_id = 123 AND fecha > '2025-01-01';
La salida tradicional incluye columnas como:
  • type: método de acceso a la tabla. Los más eficientes suelen ser "const", "eq_ref" o "ref. range" es aceptable. "index" y especialmente "ALL", escaneo completo de tabla, suelen indicar problemas en tablas grandes.
  • key: índice que realmente se usa. Si aparece "NULL", no se está utilizando ninguno.
  • rows: estimación del número de filas que se examinarán.
  • Extra: información adicional. Valores como "Using filesort" o "Using temporary" en tablas voluminosas suelen señalar puntos de mejora.
  • Using index indica un índice de cobertura (se obtienen todos los datos del índice sin tocar la tabla).
También se pueden pedir formatos más legibles:

EXPLAIN FORMAT=TREE SELECT ...
EXPLAIN FORMAT=JSON SELECT ...
EXPLAIN es seguro: se puede ejecutar en cualquier entorno sin riesgo de modificar datos ni de consumir recursos de ejecución reales.

Qué hace EXPLAIN ANALYZE

A partir de MySQL 8.0.18 aparece EXPLAIN ANALYZE. Esta variante sí ejecuta la consulta y muestra, además de las estimaciones del optimizador, las mediciones reales de cada paso::

EXPLAIN ANALYZE SELECT * FROM pedidos WHERE cliente_id = 123 AND fecha > '2025-01-01';
La salida siempre utiliza el formato árbol. Cada nodo incluye algo similar a:

(cost=... rows=...) (actual time=0.012..4.567 rows=850 loops=1)
  • cost y rows: estimaciones del optimizador, igual que en EXPLAIN.
  • actual time=inicio..fin: tiempo real en milisegundos. El primer valor es el tiempo hasta devolver la primera fila; el segundo, el tiempo total de ese iterator, incluyendo los hijos.
  • rows: número real de filas producidas.
  • loops: número de veces que se ha ejecutado ese paso. Valores altos en joins anidados suelen indicar cuellos de botella.

Diferencias clave

Aspecto EXPLAIN EXPLAIN ANALYZE
Ejecuta la consulta No
Datos Estimaciones basadas en estadísticas Estimaciones + tiempos y filas reales
Formato por defecto TRADITIONAL (tabular) TREE
Riesgo Ninguno Ejecuta la sentencia (cuidado con UPDATE/DELETE)
Uso principal Ver el plan elegido y detectar problemas evidentes Medir dónde se gasta realmente el tiempo y validar estimaciones


La gran ventaja de EXPLAIN ANALYZE es que permite detectar cuando las estadísticas están desactualizadas: si el optimizador estima 1.000 filas y realmente se procesan 150.000, el plan elegido probablemente no sea el óptimo.

Cómo interpretar un plan de ejecución

  • Empezar por el tipo de acceso: Buscar ALL o index en tablas grandes. Si aparece, suele merecer la pena revisar los índices o la forma de escribir la condición WHERE/JOIN.
  • Comparar filas estimadas frente a reales, solo con ANALYZE; Diferencias de un orden de magnitud o más indican estadísticas obsoletas. Ejecutar ANALYZE TABLE sobre las tablas implicadas y vuelve a probar.
  • Fíjarse en los tiempos reales: El iterator que acumula más tiempo, el valor final de actual time, es el candidato principal a optimización. A veces un filtro aparentemente barato resulta caro porque se ejecuta muchas veces.
  • Observar operaciones costosas en Extra
    • Using temporary + Using filesort: suele ser caro en volúmenes altos.
    • Using where solo: el filtro se aplica después de leer las filas.
    • Using index condition: el motor puede filtrar parcialmente con el índice (bueno).
  • Orden de los joins: En el formato TREE se ve claramente la anidación. El optimizador elige un orden según las estimaciones; si las estadísticas fallan, ese orden puede ser suboptimal.

Recomendaciones de uso

  • Usar EXPLAIN, o "EXPLAIN FORMAT=TREE", de forma rutinaria durante el desarrollo. Es rápido y seguro.
  • Reservar EXPLAIN ANALYZE para cuando necesites datos reales de rendimiento. En sentencias de modificación ,como UPDATE, DELETE, es mejor ponerlo en una transacción y hacer ROLLBACK si no se quiere que los cambios persistan.
  • Después de cambios importantes en índices o datos, volver a ejecutar "ANALYZE TABLE" para actualizar las estadísticas.
  • Si la diferencia entre estimación y realidad es grande y persiste, revisar la cardinalidad de los índices y la distribución de los datos.
Con estas dos herramientas puedes pasar de “la consulta va lenta” a localizar el paso concreto que consume tiempo y decidir si hace falta un índice nuevo, reescribir la consulta o actualizar estadísticas.