ANALYZE TABLE

El optimizador de consultas de MySQL toma decisiones cruciales cada vez que ejecutas una consulta: qué índice usar, en qué orden unir las tablas, si hacer un escaneo completo o usar un rango de índice. Todas estas decisiones dependen de las estadísticas sobre la distribución de datos en los índices. Cuando esas estadísticas están desactualizadas, el optimizador puede tomar decisiones subóptimas y tus consultas se vuelven lentas sin razón aparente. La sentencia ANALYZE TABLE resuelve este problema actualizando dichas estadísticas.

Sintaxis

ANALYZE TABLE nombre_tabla [, nombre_tabla2, ...];

La sintaxis es simple. Especificas una o más tablas separadas por comas y MySQL recalcula las estadísticas de distribución de claves para cada una de ellas.

Por qué importan las estadísticas

Cuando creas un índice en una columna, MySQL almacena información sobre cómo están distribuidos los valores en ese índice. Esta información incluye la cardinalidad, es decir, el número aproximado de valores distintos que contiene el índice. El optimizador usa la cardinalidad para estimar cuántas filas devolverá una condición y decidir si vale la pena usar un índice o es más eficiente escanear la tabla completa.

Imagina una tabla clientes con 100,000 filas y un índice en la columna ciudad. Si MySQL cree que hay solo 5 ciudades distintas, estimará que cualquier búsqueda por ciudad devolverá unas 20,000 filas y podría optar por un escaneo completo. Pero si realmente hay 500 ciudades distintas, cada búsqueda devolvería unas 200 filas y el índice sería mucho más eficiente. Estadísticas incorrectas llevan a planes de ejecución incorrectos.

Cuándo ejecutar ANALYZE TABLE

Las estadísticas se vuelven imprecisas cuando la tabla sufre cambios significativos en sus datos. Los escenarios más comunes son:

Después de cargar una gran cantidad de datos, por ejemplo al importar un archivo CSV con millones de registros o al migrar datos de otro sistema. También después de eliminar una proporción significativa de las filas, ya que la distribución de valores cambia. Igualmente, si notas que una consulta que antes era rápida se ha vuelto inexplicablemente lenta, las estadísticas desactualizadas pueden ser la causa.

-- Después de una carga masiva de datos
LOAD DATA INFILE '/tmp/clientes_nuevos.csv'
INTO TABLE clientes
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n';
 
-- Actualizar estadísticas
ANALYZE TABLE clientes;

Ejemplo práctico

Veamos cómo ejecutar ANALYZE TABLE y leer su resultado:

ANALYZE TABLE productos;
TableOpMsg_typeMsg_text
tienda_mysql.productosanalyzestatusOK

El resultado contiene cuatro columnas. Table muestra el nombre completo de la tabla incluyendo la base de datos. Op confirma la operación realizada. Msg_type indica el tipo de mensaje, que normalmente es status. Msg_text muestra OK si todo fue bien, o un mensaje de error si ocurrió algún problema.

Analizar múltiples tablas

Puedes analizar varias tablas en una sola sentencia:

ANALYZE TABLE productos, clientes, pedidos, detalle_pedidos;
TableOpMsg_typeMsg_text
tienda_mysql.productosanalyzestatusOK
tienda_mysql.clientesanalyzestatusOK
tienda_mysql.pedidosanalyzestatusOK
tienda_mysql.detalle_pedidosanalyzestatusOK

MySQL analiza cada tabla secuencialmente y muestra el resultado individual.

Verificar el efecto en las estadísticas

Puedes comprobar las estadísticas de los índices antes y después de ANALYZE TABLE usando SHOW INDEX:

SHOW INDEX FROM productos;
TableKey_nameColumn_nameCardinality
productosPRIMARYid150
productosidx_categoriacategoria_id12
productosidx_precioprecio145

La columna Cardinality muestra el número estimado de valores distintos en cada índice. Después de ANALYZE TABLE, estos valores reflejan con mayor precisión la distribución real de los datos.

Impacto en los planes de ejecución

Para ver cómo las estadísticas afectan las decisiones del optimizador, usa EXPLAIN antes y después de analizar:

-- Antes de ANALYZE TABLE (estadísticas antiguas)
EXPLAIN SELECT * FROM productos WHERE categoria_id = 6;
idselect_typetabletypekeyrows
1SIMPLEproductosALLNULL150

En este ejemplo ficticio, el optimizador decidió hacer un escaneo completo (ALL) porque las estadísticas antiguas indicaban una cardinalidad baja para el índice de categoría.

-- Actualizar estadísticas
ANALYZE TABLE productos;
 
-- Después de ANALYZE TABLE
EXPLAIN SELECT * FROM productos WHERE categoria_id = 6;
idselect_typetabletypekeyrows
1SIMPLEproductosrefidx_categoria12

Ahora el optimizador usa el índice idx_categoria y estima que solo necesita leer 12 filas. La consulta será significativamente más rápida.

Comportamiento en InnoDB

En tablas InnoDB, ANALYZE TABLE realiza un muestreo aleatorio de las páginas del índice para estimar la cardinalidad. No lee todas las filas, lo que hace la operación bastante rápida incluso en tablas grandes.

InnoDB también actualiza las estadísticas automáticamente cuando detecta que la tabla ha cambiado significativamente. La variable innodb_stats_auto_recalc controla este comportamiento y está activada por defecto. Sin embargo, la actualización automática no siempre ocurre en el momento ideal, por lo que ejecutar ANALYZE TABLE manualmente después de operaciones masivas sigue siendo una buena práctica.

La variable innodb_stats_persistent determina si las estadísticas se almacenan en disco. Cuando está activada (valor por defecto), las estadísticas sobreviven a reinicios del servidor, lo que significa que no necesitas ejecutar ANALYZE TABLE después de cada reinicio.

-- Verificar la configuración actual
SHOW VARIABLES LIKE 'innodb_stats%';
Variable_nameValue
innodb_stats_auto_recalcON
innodb_stats_persistentON
innodb_stats_persistent_sample_pages20

La variable innodb_stats_persistent_sample_pages controla cuántas páginas se muestrean. Un valor mayor produce estadísticas más precisas pero ANALYZE TABLE tardará más.

Comportamiento en MyISAM

En tablas MyISAM, ANALYZE TABLE lee todas las filas para calcular la distribución exacta de claves. La tabla se bloquea con un bloqueo de lectura durante la operación, lo que significa que otras sesiones pueden leer la tabla pero no pueden escribir en ella hasta que termine.

Bloqueo y rendimiento

ANALYZE TABLE adquiere un bloqueo de lectura en la tabla. Las consultas SELECT pueden continuar ejecutándose normalmente, pero las operaciones de escritura (INSERT, UPDATE, DELETE) quedarán en espera hasta que la operación termine.

Para tablas InnoDB, la operación suele ser rápida porque se basa en muestreo. Para tablas MyISAM grandes, puede tomar más tiempo. En cualquier caso, es recomendable ejecutar ANALYZE TABLE durante ventanas de bajo tráfico.

Automatización con eventos

Puedes programar ANALYZE TABLE para que se ejecute periódicamente usando el scheduler de eventos de MySQL:

CREATE EVENT analizar_tablas_principales
ON SCHEDULE EVERY 1 WEEK
STARTS '2026-02-15 03:00:00'
DO
BEGIN
    ANALYZE TABLE productos;
    ANALYZE TABLE pedidos;
    ANALYZE TABLE clientes;
    ANALYZE TABLE detalle_pedidos;
END;

Este evento analiza las tablas principales cada semana a las 3 de la madrugada, cuando el tráfico suele ser mínimo.

Cuándo NO es necesario

No necesitas ejecutar ANALYZE TABLE constantemente. Si la tabla no ha experimentado cambios significativos en el volumen o distribución de datos, las estadísticas existentes siguen siendo válidas. Ejecutarlo innecesariamente no causa daño, pero consume recursos sin beneficio.

Tampoco resolverá problemas de rendimiento causados por consultas mal escritas, falta de índices adecuados, o un diseño de esquema ineficiente. Si una consulta es lenta, verifica primero con EXPLAIN que el problema realmente sea de estadísticas antes de ejecutar ANALYZE TABLE.

La sentencia ANALYZE TABLE es una operación de mantenimiento ligera que conviene ejecutar después de cambios significativos en los datos. En el siguiente artículo veremos OPTIMIZE TABLE, que va un paso más allá y reorganiza físicamente los datos para recuperar espacio desperdiciado.

Escrito por Eduardo Lázaro