Para arreglar una consulta lenta de MySQL, identifica primero la consulta y mide su tiempo. Después ejecuta EXPLAIN o EXPLAIN ANALYZE, busca lecturas excesivas, escaneos completos y archivos temporales, y corrige el índice o la consulta que lo provoca. Repite la medición con los mismos datos y detén los cambios si alteran el resultado o bloquean el servicio.
Detecta qué consulta es realmente lenta
MySQL permite localizar las consultas que consumen más tiempo mediante el registro de consultas lentas o las herramientas de observabilidad del servidor. No optimices una consulta elegida por intuición: confirma que se repite, cuánto tarda y cuántas filas examina.
En un servidor administrado, activa el registro desde el panel o pide al responsable de la base de datos que lo habilite. En una instalación propia, revisa las variables relacionadas con `slow_query_log`, `long_query_time` y `log_queries_not_using_indexes`. El manual de referencia de MySQL documenta estas opciones y advierte que registrar demasiadas consultas puede aumentar el uso de disco.
Prioriza una consulta frecuente que tenga mucho tiempo total acumulado. Una consulta individual de 2 segundos puede ser menos urgente que otra de 200 milisegundos ejecutada miles de veces. Comprueba también si la lentitud aparece siempre, solo con rangos grandes o cuando coinciden varias operaciones.
Comprueba el plan con EXPLAIN
`EXPLAIN` muestra cómo MySQL prevé ejecutar una consulta: el orden de las tablas, los índices considerados y el número estimado de filas. Ejecútalo sin modificar datos:
EXPLAIN SELECT columna1, columna2
FROM pedidos
WHERE cliente_id = 42
AND estado = 'pendiente'
ORDER BY creado_en DESC
LIMIT 50;
Busca señales observables: `type` con valores como `ALL` puede indicar un escaneo completo; un valor alto en `rows` señala muchas filas examinadas; `key` como `NULL` significa que no se ha elegido un índice; y `Extra` con `Using filesort` o `Using temporary` merece revisión, aunque no siempre implica un error. Son indicios, no diagnósticos aislados.
En versiones que lo admitan, `EXPLAIN ANALYZE` ejecuta la consulta y añade tiempos y filas reales. Úsalo con una consulta de lectura y en pruebas controladas, porque no es una simple estimación. La documentación oficial de MySQL distingue entre el plan estimado de `EXPLAIN` y las mediciones obtenidas durante la ejecución.
EXPLAIN ANALYZE
SELECT columna1, columna2
FROM pedidos
WHERE cliente_id = 42
AND estado = 'pendiente';
Corrige el índice según los filtros y el orden
Un índice de MySQL debe corresponder a las columnas que filtran, relacionan u ordenan la consulta, en el orden adecuado. Antes de crearlo, revisa los índices existentes con `SHOW INDEX FROM pedidos;` y evita duplicar uno que ya cubra el mismo prefijo.
Para el ejemplo anterior, un índice compuesto puede ser una opción razonable si la consulta filtra habitualmente por `cliente_id` y `estado`, y después ordena por `creado_en`:
CREATE INDEX idx_pedidos_cliente_estado_fecha
ON pedidos (cliente_id, estado, creado_en);
La elección depende de la distribución de los datos y de otras consultas. Un índice adicional ocupa espacio y puede ralentizar inserciones, actualizaciones y borrados. Por eso, crea el cambio en pruebas, vuelve a ejecutar `EXPLAIN` y confirma que `key` cambia de forma útil y que la estimación de `rows` baja.
No añadas un índice a cada columna de una tabla. Si una condición devuelve gran parte de la tabla, el optimizador puede preferir leerla completa; eso no demuestra por sí solo que MySQL esté fallando.
Reescribe la consulta cuando el índice no basta
Una consulta de MySQL puede seguir siendo lenta aunque tenga índices si transforma la columna filtrada, devuelve demasiados datos o aplica una operación costosa antes de limitar el resultado.
Revisa estos patrones concretos:
- Evita `SELECT *` y solicita solo las columnas que necesita la aplicación.
- Evita aplicar funciones sobre una columna indexada en el filtro, como `WHERE YEAR(creado_en) = 2026`; usa un rango de fechas cuando conserve el mismo significado.
- Verifica que los tipos de las columnas comparadas coincidan, especialmente en uniones y filtros numéricos.
- Para páginas grandes, considera paginación basada en una columna indexada en lugar de saltos muy altos con `OFFSET`.
- Comprueba las uniones con `EXPLAIN`: las columnas relacionadas deben tener tipos compatibles y, normalmente, índices útiles.
Haz un solo cambio cada vez. Si una reescritura devuelve filas distintas, cambia el orden, elimina duplicados o modifica el tratamiento de valores `NULL`, vuelve atrás y valida primero la lógica funcional.
Verifica la mejora con la misma carga
La solución de una consulta lenta de MySQL solo está confirmada cuando mejora el tiempo sin cambiar el resultado ni perjudicar al resto del sistema.
- Ejecuta la consulta con los mismos parámetros o con una muestra equivalente. Descarta la primera ejecución si solo refleja la carga inicial de páginas, pero conserva varias mediciones posteriores.
- Compara tiempo, filas devueltas, filas examinadas, lecturas de disco y uso de CPU cuando esas métricas estén disponibles.
- Repite `EXPLAIN` y guarda el nuevo plan. Una mejora esperable es examinar menos filas o evitar una operación costosa, pero el optimizador puede escoger otro plan según las estadísticas.
- Observa otras consultas que usan la tabla. Un índice nuevo puede acelerar una lectura y aumentar el coste de escritura o el espacio utilizado.
- Después del despliegue, vigila el registro de consultas lentas y los bloqueos durante un periodo representativo.
Si el plan sigue igual, actualiza las estadísticas solo con un procedimiento aprobado para tu entorno y vuelve a medir. Si el tiempo empeora, revierte el cambio documentado y conserva el plan anterior para comparar.
Qué revisar si no aparece una mejora
Si MySQL continúa lento tras revisar la consulta y sus índices, el problema puede estar fuera del SQL concreto: bloqueo entre transacciones, falta de memoria, almacenamiento saturado, conexiones agotadas, estadísticas poco representativas o una consulta que espera a otro recurso.
Comprueba si el tiempo se consume ejecutando la consulta o esperando. Revisa procesos y bloqueos con las herramientas permitidas por tu versión y proveedor, y compara el momento del problema con CPU, memoria, disco y conexiones. En réplicas, confirma que estás midiendo el servidor que atiende realmente la petición.
Como alternativa segura, prueba la consulta en una copia con un conjunto de datos similar y registra el plan antes de modificar producción. Si afecta a datos críticos, provoca bloqueos o no puedes explicar el cambio en el plan, detente y pásalo a un administrador de bases de datos. No borres datos ni desactives controles de seguridad para perseguir una mejora de rendimiento.
Preguntas frecuentes
¿Qué significa que EXPLAIN muestre `type: ALL` en MySQL?
Significa que el plan prevé leer todas las filas de esa tabla. Puede ser adecuado si la tabla es pequeña o el filtro devuelve casi todo, pero en tablas grandes conviene revisar el filtro, los tipos comparados y los índices disponibles. Confirma el diagnóstico con `rows`, `key` y una medición real; `ALL` por sí solo no justifica crear un índice.
¿Crear un índice siempre acelera una consulta lenta de MySQL?
No. Un índice puede acelerar lecturas selectivas, pero añade espacio y trabajo a las operaciones de escritura. Si el filtro devuelve muchas filas, MySQL puede preferir un escaneo completo. Revisa los índices existentes, crea uno en pruebas y compara el plan, el tiempo y el impacto en otras consultas antes de aplicarlo.
¿Puedo usar EXPLAIN ANALYZE en cualquier versión de MySQL?
No. Su disponibilidad y comportamiento dependen de la versión y del tipo de sentencia. Comprueba primero `SELECT VERSION();` y la documentación correspondiente. Si no está disponible, usa `EXPLAIN` para el plan estimado y mide la consulta mediante el registro o la herramienta de observabilidad de tu entorno.
¿Por qué una consulta de MySQL es rápida unas veces y lenta otras?
Las diferencias pueden deberse a parámetros que devuelven cantidades distintas de filas, cachés, bloqueos, estadísticas, concurrencia o recursos saturados. Compara varias ejecuciones con los mismos parámetros y observa si el tiempo es de ejecución o de espera. Si hay bloqueos o presión del servidor, resolver esa causa debe preceder a cambiar el SQL.
Fuentes y verificación
- Solución de problemas de consultas lentas en MySQL: una guía ... | https://devops.aibit.im/es/article/mysql-slow-query-troubleshooting-guide