Curso de MySQL

EXPLAIN en MySQL: analizar por qué una consulta va lenta

Por Víctor Peña · Publicado el

EXPLAIN en MySQL

Hola, ¿cómo están? Continuando con el curso de MySQL, hoy veremos EXPLAIN: la herramienta que te dice qué está haciendo MySQL con tu consulta en lugar de que lo adivines.

Es lo que convierte la optimización en un trabajo de diagnóstico y no de intuición.

¡Empecemos!

Cómo se usa

Antepón EXPLAIN a cualquier consulta:

EXPLAIN SELECT * FROM citas WHERE estado = 'programada';

No ejecuta la consulta: te muestra el plan de ejecución, es decir, cómo piensa MySQL resolverla.

El resultado es una tabla con varias columnas. Vamos a las que importan.

La columna type: la más importante

Indica cómo accede MySQL a las filas. Ordenada de mejor a peor:

Valor Significa Veredicto
const Una sola fila por clave primaria Óptimo
eq_ref Una fila por cada fila de la otra tabla Excelente
ref Varias filas con un índice no único Muy bien
range Rango sobre un índice Bien
index Recorre el índice completo Regular
ALL Escanea toda la tabla Problema

Si ves ALL en una tabla grande, ahí está tu problema. Significa que MySQL está leyendo fila por fila porque no encontró ningún índice útil.

En tablas pequeñas ALL es normal y hasta preferible: leer 50 filas es más rápido que consultar un índice.

La columna key

Muestra qué índice está usando realmente.

EXPLAIN SELECT * FROM citas WHERE estado = 'programada';

Si key aparece como NULL, no está usando ninguno. Contrástalo con la columna possible_keys, que lista los que podría haber usado:

  • possible_keys con valores y key en NULL → MySQL descartó el índice, normalmente porque devolvería demasiadas filas.
  • possible_keys en NULL → no existe ningún índice aplicable. Ahí toca crear uno.

La columna rows

Estimación de cuántas filas va a examinar MySQL.

Es una estimación, no un número exacto, pero sirve para comparar: si tu tabla tiene 500.000 filas y rows dice 480.000, la consulta está leyendo prácticamente todo.

Lo que quieres ver es un número bajo en relación al tamaño de la tabla.

La columna Extra

Contiene avisos que conviene reconocer:

Valor Qué significa
Using index Excelente. Responde solo con el índice, sin tocar la tabla
Using where Filtra después de leer. Normal
Using filesort Ordena en memoria o disco. El ORDER BY no usa índice
Using temporary Crea una tabla temporal. Costoso
Using index condition Filtra usando el índice. Bien

Los dos que hay que vigilar son Using filesort y Using temporary. Aparecen sobre todo con ORDER BY y GROUP BY sin índice de apoyo, y en tablas grandes son la causa de que una consulta tarde segundos.

Y Using index es la mejor noticia posible: significa que el índice contiene todo lo que la consulta pide y MySQL no necesita leer la tabla. Se llama índice cubriente.

Un caso completo

Vamos a ver el antes y el después.

Antes, sin índice:

EXPLAIN SELECT fecha, costo FROM citas WHERE estado = 'programada';
type: ALL
possible_keys: NULL
key: NULL
rows: 500000
Extra: Using where

Traducción: lee las 500.000 filas y descarta las que no cumplen.

Creamos el índice:

CREATE INDEX idx_citas_estado ON citas(estado);

Después:

type: ref
possible_keys: idx_citas_estado
key: idx_citas_estado
rows: 1200
Extra: Using where

De 500.000 filas examinadas a 1.200. Eso es lo que buscas.

EXPLAIN ANALYZE: datos reales

Desde MySQL 8.0.18 existe una versión que sí ejecuta la consulta y reporta tiempos medidos:

EXPLAIN ANALYZE
SELECT c.fecha, p.nombre
FROM citas c
JOIN pacientes p ON c.paciente_id = p.id
WHERE c.estado = 'programada';

Devuelve el tiempo real de cada paso y cuántas filas se procesaron de verdad, no estimadas.

Es más fiable que EXPLAIN normal, porque las estimaciones pueden estar desactualizadas. Ojo con una cosa: al ejecutar realmente la consulta, no lo uses con UPDATE o DELETE en producción.

EXPLAIN con formato legible

EXPLAIN FORMAT=TREE
SELECT c.fecha, p.nombre
FROM citas c
JOIN pacientes p ON c.paciente_id = p.id;

Muestra el plan como un árbol, con el orden en que se ejecutan las operaciones. Es bastante más comprensible que la tabla de columnas cuando hay varios JOIN.

Los problemas más frecuentes que revela

1. Índice inutilizado por una función

EXPLAIN SELECT * FROM citas WHERE YEAR(fecha) = 2026;
-- type: ALL
EXPLAIN SELECT * FROM citas
WHERE fecha >= '2026-01-01' AND fecha < '2027-01-01';
-- type: range

Misma consulta lógica, plan completamente distinto.

2. Orden equivocado en un índice compuesto

Con el índice (doctor_id, fecha):

EXPLAIN SELECT * FROM citas WHERE fecha > '2026-04-01';
-- type: ALL  ← no puede usarlo

Es la regla del extremo izquierdo que vimos en la lección de índices. EXPLAIN te lo confirma.

3. Ordenación sin índice

EXPLAIN SELECT * FROM citas ORDER BY costo DESC LIMIT 20;
-- Extra: Using filesort

Un índice sobre costo elimina el filesort.

4. JOIN sin índice en la clave foránea

EXPLAIN SELECT c.fecha, p.nombre
FROM citas c
JOIN pacientes p ON c.paciente_id = p.id;

Si la columna paciente_id no está indexada, verás ALL en esa tabla. Es la razón por la que declarar las claves foráneas ayuda: crean el índice automáticamente.

Un método de diagnóstico

Cuando una consulta va lenta:

  1. Ejecuta EXPLAIN.
  2. Busca ALL en la columna type.
  3. Mira si key es NULL.
  4. Compara rows con el tamaño real de la tabla.
  5. Revisa Extra buscando filesort o temporary.
  6. Crea el índice que falte, o reescribe la consulta.
  7. Vuelve a ejecutar EXPLAIN y comprueba que cambió.

Ese último paso es el que cierra el círculo. Sin volver a medir, no sabes si tu cambio sirvió.

EXPLAIN en Workbench

Workbench tiene una vista gráfica: ejecuta la consulta y pulsa el icono de Explain junto al resultado. Muestra el plan como un diagrama con colores —verde para bien, rojo para escaneo completo— y el costo estimado de cada paso.

Es mucho más digerible que la tabla de texto cuando estás empezando.

Lo que EXPLAIN no te dice

Para tener expectativas realistas:

  • No mide el tiempo real salvo que uses EXPLAIN ANALYZE.
  • Las estimaciones pueden estar desactualizadas. Ejecuta ANALYZE TABLE para refrescarlas.
  • No detecta problemas de la aplicación, como el N+1: cada consulta suelta puede verse perfecta y aun así estar ejecutándose 500 veces.

Ejercicios

Con tu base de la clínica:

  1. Ejecuta EXPLAIN sobre una consulta filtrando por estado sin índice y anota el type.
  2. Crea el índice y repite. Compara.
  3. Prueba WHERE YEAR(fecha) = 2026 frente al rango equivalente.
  4. Analiza una consulta con tres JOIN y revisa qué índice usa cada tabla.

Errores comunes

  • Optimizar sin usar EXPLAIN, a base de prueba y error.
  • Ignorar Using filesort y Using temporary.
  • Confiar en rows como número exacto.
  • Analizar con datos de prueba. Con 50 filas todo parece rápido; el plan cambia con volumen real.
  • No repetir el EXPLAIN después de crear el índice.

Para cerrar

EXPLAIN convierte «esta consulta va lenta» en «esta consulta escanea 480.000 filas porque no hay índice en la columna del WHERE». Es la diferencia entre diagnosticar y adivinar.

Lo esencial: busca ALL en type, NULL en key, y filesort o temporary en Extra. Con esos tres indicadores resuelves la mayoría de los casos.

En la siguiente lección veremos la búsqueda de texto completo.

Saludos y éxitos.

Norvic Software

Desarrollamos el software que tu empresa necesita

Somos una fábrica de software en Bolivia. Construimos sistemas a medida y aplicaciones móviles, y llevamos Inteligencia Artificial a las empresas que ya tienen un sistema funcionando.

Solicitar cotizaciónVer todos los servicios

Cotización sin costo · Respuesta directa por WhatsApp