Translate

martes, 26 de mayo de 2026

Cómo detectar cuando MySQL elige un mal plan de ejecución?


El optimizador de MySQL es muy bueno… pero no es perfecto.


A veces elige un plan que:

❌ No usa índices

❌ Hace scans innecesarios

❌ Escala mal con más datos


El problema es que la query funciona… pero lento.


Primero: qué es un “mal plan”. Un mal plan no significa que falle.

Significa que:

  • Hace más trabajo del necesario
  • No usa la mejor estrategia disponible


Señales claras de un mal plan

❌ 1. Gran diferencia entre estimado y real

rows=1000 (estimated)

actual rows=10


Esto es una alarma 🚨

MySQL toma decisiones basadas en estimaciones.


Si están mal:

  • Puede elegir un índice incorrecto
  • O directamente no usar índice

❌ 2. Full Table Scan inesperado

Table scan on libros


Si tenés índice y aun así escanea todo:

🚨 Algo está mal


Posibles causas

  • Falta de índice
  • Índice no selectivo
  • Uso de funciones en columnas
  • LIKE '%texto%'


❌ 3. Índice ignorado

Tenés índice:

CREATE INDEX idx_nombre ON autores(nombre);


Pero el plan dice:

Table scan on autores


❌ No lo está usando


Causas típicas

  • Baja selectividad
  • Estadísticas desactualizadas
  • El optimizador cree que el scan es más barato


❌ 4. Nested loops con muchas filas

Nested loop (loops=10000)


Esto escala MUY mal


Problema

Por cada fila de A:

  • Busca en B


Complejidad tipo: O(n * m)


❌ 5. Filtros aplicados tarde


👉 Si aparece después de un scan:

❌ Primero lee todo

❌ Después filtra


❌ 6. Uso excesivo de “Using temporary” o “Sort”

Using temporary

Sort: ...


Señales de:

  • Falta de índices
  • Ordenamientos costosos


Ejemplo real:

SELECT *

FROM libros

WHERE titulo LIKE '%Java%';


Plan:

Table scan on libros


Aunque tengas índice en titulo:

No se usa por el `%` inicial


Caso interesante: estimaciones incorrectas

rows=1.25 actual rows=1

Esto es normal.


Pero:

rows=10000 actual rows=1

Problema serio


Consecuencia


MySQL puede pensar:

“Esto devuelve muchas filas → mejor full scan”

Pero en realidad devuelve pocas


Cómo confirmar que el plan es malo


1. Usar EXPLAIN ANALYZE

EXPLAIN ANALYZE SELECT ...


Comparar:

  • estimado vs real
  • tiempos


2. Medir tiempo real

A veces el plan “feo” igual es rápido.


3. Probar alternativas

  • Reescribir query
  • Forzar índice:

SELECT * FROM libros FORCE INDEX (idx_titulo)

WHERE titulo LIKE 'Java%';


Cómo corregir un mal plan

1. Actualizar estadísticas

ANALYZE TABLE libros;

Muchas veces esto solo ya arregla todo


2. Crear índices correctos

Pensar en:

  • WHERE
  • JOIN
  • ORDER BY


3. Cambiar la query


Ejemplo:

LIKE '%Java%' ❌

LIKE 'Java%'  ✔️


4. Reducir datos

Menos filas = mejores decisiones


5. Forzar plan (último recurso)

USE INDEX / FORCE INDEX

Solo si estás seguro


Error común

“Si EXPLAIN dice que usa índice, está todo bien”

❌ No necesariamente

👉 Puede usarlo… pero mal


Regla de oro

Siempre mirar:

  • rows vs actual rows
  • loops
  • tipo de acceso


El optimizador de MySQL:

✔️ Es bueno

❌ Pero depende de estadísticas


Y cuando se equivoca:

  • No falla
  • Solo se vuelve lento 

No hay comentarios.:

Publicar un comentario