Histogramas de MySQL proporcionan al optimizador datos reales sobre la distribución, para que pueda estimar correctamente las selectividades y generar planes de consulta más rápidos, a menudo incluso sin necesidad de un índice adicional. Te mostraré cómo configuro y compruebo los histogramas en MySQL 8+ con ANALYZE TABLE, y cómo los utilizo para tomar mejores decisiones en las uniones, los filtros y los escaneos.
Puntos centrales
Enfoque breve: Los siguientes puntos clave muestran a qué presto especial atención al utilizar histogramas.
- Selectividad En lugar de basarse en la intuición: estimaciones de cardinalidad más realistas
- Sin índice Más rápido: mejor selección de planes en caso de distribuciones asimétricas
- Tipos Comprender: cómo utilizar de forma específica «singleton» frente a «equi-height»
- Cubos gestionar: sopesar la liquidación frente a los costes de los metadatos
- Atención En resumen: actualizar, comprobar y, si es necesario, eliminar
Por qué los histogramas sin índice resultan efectivos
Utilizo Histogramas, ya que, de lo contrario, el optimizador suele partir de una distribución uniforme y, por ello, elige planes poco óptimos. Un histograma representa la Distribución de valores se aproxima a una columna y, de este modo, proporciona estimaciones realistas de selectividad para predicados como =, >, BETWEEN, IN o IS NULL. A continuación, el optimizador decide si es más conveniente realizar un escaneo de rango de índice, un escaneo de tabla o una estrategia de unión con bucles anidados. Si, por ejemplo, una condición solo afecta al 0,1 % de las filas, prefiero un acceso específico en lugar de un escaneo amplio. Por el contrario, si un filtro abarca casi todas las filas, renuncio a los costosos accesos a índices que no aportan ninguna ventaja y, de este modo, aumento la Eficacia de cada plan.
Tipos de histogramas en MySQL 8.0
Distingo dos Tipos: Singleton y Equi-Height. Los histogramas Singleton agrupan los valores únicos que aparecen con frecuencia en intervalos separados, lo que resulta ideal para columnas con pocas categorías dominantes, como „activo“, „inactivo“ o „archivado“. Los histogramas de altura equitativa dividen el rango de valores de tal manera que cada intervalo contenga un número similar de Líneas ; esto resulta adecuado para distribuciones continuas o irregulares, como precios, marcas de tiempo o rangos de identificación „con huecos“. Ambas variantes proporcionan al optimizador índices de acierto más precisos para los filtros. Yo siempre elijo el tipo en función de las características de los datos, no por preferencia personal.
Fundamentos técnicos: cómo controlar la selección de tipos en MySQL
MySQL determina la forma concreta Variante del histograma automáticamente en función de la distribución de los datos. En la práctica, esto significa que, si el número de valores distintos (NDV) es lo suficientemente pequeño en relación con el número de intervalos, se genera, en la práctica, un histograma de tipo „singleton“; en caso contrario, se genera un histograma de altura equidistante. Por lo tanto, «elijo» el tipo indirecta, seleccionando la columna adecuada y un número adecuado de intervalos. Para columnas con muy pocas categorías, pero muy dominantes, establezco deliberadamente un número reducido de buckets para obtener una precisión similar a la de un singleton para estos valores. En el caso de datos continuos y muy dispersos, aumento los buckets gradualmente hasta que EXPLAIN muestre el Selectividad refleja.
Importante: los histogramas son en una sola columna. No es posible representar directamente las dependencias entre columnas (por ejemplo, «status» y «country»). En estos casos, resulta útil aplicar un histograma a la columna más selectiva y diseñar el orden de las uniones en consecuencia.
Cómo elegir bien los cubos
MySQL utiliza 100 por defecto Cubos, aunque permite entre 1 y 1024 mediante WITH N BUCKETS. Un mayor número de buckets aumenta la resolución, pero también crecen los metadatos y el esfuerzo de análisis. Normalmente empiezo con un valor conservador, evalúo el efecto en EXPLAIN y lo voy aumentando gradualmente si el plan sigue pareciendo inadecuado. Cuando los valores están muy concentrados (por ejemplo, 90 % en un estado), a menudo bastan unos pocos buckets; en cambio, cuando los precios o las marcas de tiempo están muy dispersos, conviene utilizar más buckets. El objetivo es una resolución razonable Granularidad, lo que ha reducido notablemente los errores de valoración sin aumentar innecesariamente la carga administrativa.
Ejemplo práctico: Flujo de trabajo con ANALYZE TABLE
Sigo una línea clara Flujo de trabajo: En primer lugar, identifico las columnas que aparecen con frecuencia en condiciones WHERE o JOIN y que presentan distribuciones claramente asimétricas. A continuación, genero un histograma con ANALYZE TABLE tbl UPDATE HISTOGRAM ON col WITH N BUCKETS; y lo compruebo a través de INFORMATION_SCHEMA.COLUMN_STATISTICS. Tras los traslados de datos, vuelvo a actualizar con ANALYZE TABLE. Si una estadística no es adecuada, la elimino con ANALYZE TABLE tbl DROP HISTOGRAM ON col;. Para evaluar el impacto en el plan, consulto Interpretar EXPLAIN ANALYZE y las mismas estimaciones frente a los datos reales Líneas de.
Órdenes concretas y control
Trabajo de forma reproducible, siguiendo unos pocos pasos claros, y compruebo las estadísticas JSON generadas.
-- Crear histogramas en columnas concretas
ANALYZE TABLE orders UPDATE HISTOGRAM ON status WITH 32 BUCKETS;
ANALYZE TABLE orders UPDATE HISTOGRAM ON created_at WITH 128 BUCKETS;
-- Varias columnas en una sola ejecución con el mismo número de compartimentos
ANALYZE TABLE orders UPDATE HISTOGRAM ON status, payment_method WITH 64 BUCKETS;
-- Eliminar histogramas de forma selectiva
ANALYZE TABLE orders DROP HISTOGRAM ON status;
-- Revisión visual de las estadísticas
SELECT
SCHEMA_NAME, TABLE_NAME, COLUMN_NAME,
JSON_PRETTY(HISTOGRAM) AS histogram
FROM INFORMATION_SCHEMA.COLUMN_STATISTICS
WHERE SCHEMA_NAME = DATABASE()
AND TABLE_NAME = 'orders'
AND COLUMN_NAME IN ('status','created_at');
Evalúo el efecto directamente con EXPLAIN ANALYZE:
EXPLAIN ANALYZE
SELECT *
FROM orders
WHERE status = 'canceled'
AND created_at >= NOW() - INTERVAL 7 DAY;
¿Mejora la estimación? filas Si se nota una diferencia y el plan cambia, por ejemplo, de un escaneo completo a un escaneo de rango de índice, o si modifica el orden de las uniones, la medida habrá tenido éxito. Si la desviación sigue siendo grande, aumento o reduzco el número de buckets y vuelvo a comparar.
Ejemplo: estado de los pedidos y valores poco frecuentes
En una tabla de pedidos suele predominar el estado „completado“, mientras que „pendiente“ es bastante frecuente y „cancelado“ muy poco frecuente; esto desequilibrio Sin un histograma, esto puede dar lugar fácilmente a selectividades erróneas. Si una API consulta „canceled“, el optimizador puede optar erróneamente por un escaneo completo de la tabla, aunque bastaría con un acceso mediante un índice específico. Con un histograma singleton, MySQL detecta que „canceled“ solo representa una proporción minúscula y cambia a un escaneo de rango de índice u optimiza el orden de las uniones. De este modo, se reduce la latencia y no necesito un índice adicional para cada Variante de un filtro. En los paneles de control con SLO estrictos, esta corrección suele aportar ventajas notables en cuanto a la capacidad de respuesta.
Series temporales y marcas de tiempo
En el caso de las series temporales, hay muchos Accede a basándose en datos recientes; los intervalos de tiempo más antiguos suelen quedar inactivos. Un histograma de altura equidistante sobre «created_at» o «updated_at» distingue los intervalos de tiempo muy frecuentados de los que se utilizan con poca frecuencia. El optimizador estima entonces correctamente si es conveniente realizar un Range-Scan o si un Table-Scan permite alcanzar el objetivo más rápidamente. Especialmente en el caso de filtros temporales parciales sobre tablas grandes, observo cambios significativos en el plan de ejecución y menores costes de E/S. Considero que la Estadísticas aquí se actualiza con más frecuencia, ya que el enfoque cambia según la actividad diaria.
Particiones, tipos de datos y colaciones
En las tablas particionadas, analizo la distribución de los datos en todas las particiones. Las grandes diferencias (por ejemplo, por meses) pueden suavizar los histogramas globales. Si alguna partición es extremadamente selectiva o extremadamente amplia, compruebo además, mediante filtros de «partition pruning» en la cláusula WHERE, si la calidad del plan sigue siendo adecuada. En general, procuro formular los filtros de tal manera que MySQL seleccione las particiones lo antes posible excluir puede.
Los histogramas funcionan mejor con tipos de datos escalares y comparables (números, valores de fecha y hora, VARCHAR/CHAR con una colación adecuada). En el caso de Datos LOB/JSON yo me decanto más por Columnas generadas con valores extraídos y tipificados, y, si es necesario, los acompaña de histogramas o índices. En el caso de las cadenas de caracteres, la Colación la lógica de comparación; dependiendo de la colación, los valores pueden coincidir (por ejemplo, mayúsculas y minúsculas). Mantengo la colación coherente con las consultas para obtener selectividades realistas.
Límites y errores
Los histogramas estiman, sobre todo, columnas individuales con Constantes Bien; sin embargo, solo representan de forma limitada las dependencias entre varias columnas. En el caso de columnas muy correlacionadas o parámetros dinámicos (por ejemplo, rellenados desde la aplicación), alcanzan sus límites. Los campos booleanos o las columnas con una distribución casi uniforme rara vez se benefician de estadísticas adicionales. Por otra parte, un número excesivo de intervalos y un mantenimiento desmesurado pueden aumentar el tiempo dedicado a la gestión y al análisis. Por eso utilizo los histogramas de forma selectiva y compruebo periódicamente la Efecto en modelos reales.
Comprobación y actualización del optimizador
Compruebo el Utilice desde histogramas hasta ANALYZE TABLE y las opciones relevantes del optimizador, para que el planificador utilice las estadísticas de forma adecuada. En sistemas con mucha carga de trabajo, planifico la actualización en franjas horarias de menor actividad o por lotes tras cargas de datos de gran volumen. Antes y después, comparo los resultados de EXPLAIN y EXPLAIN ANALYZE para evaluar los cambios en el orden de las uniones, los pasos de filtrado y los modelos de costes. Si se producen efectos negativos, reacciono de inmediato y revierto una estadística. Para un control más exhaustivo de la Opciones del optimizador Me aseguro de que las dependencias con otras estadísticas no generen errores que pasen desapercibidos Supuestos generar.
Supervisión, protección contra la regresión y guía de actuación
Me estoy construyendo un Manual de estrategias Para el entorno de producción:
- Establecer una referencia: antes de realizar cambios, ejecutar EXPLAIN ANALYZE y registrar el tiempo de ejecución, el número de „filas examinadas“ y el contador del controlador.
- Crear/modificar un histograma: centrado en las columnas de filtro, con intervalos conservadores.
- Medir inmediatamente después: plan, líneas estimadas frente a líneas reales; una desviación con un factor >10 es para mí una señal de alarma.
- Ajuste fino: subir/bajar los «buckets»; si es necesario, modificar el orden de los filtros en la consulta.
- Tener preparada una reversión: DROP HISTOGRAM, en caso de que aumenten las latencias.
- Automatización: ejecutar ANALYZE en ventanas de mantenimiento tras cargas ETL o oleadas importantes de DML.
Para analizar las causas, utilizo Rastros del optimizador y EXPLAIN ANALYZE, para comprobar si el planificador, basándose en los histogramas, selecciona la tabla correcta „en primer lugar“. Para las pruebas A/B, fijo de forma experimental el orden de las uniones (STRAIGHT_JOIN) o fuerzo/desactivo índices concretos para evaluar de forma aislada el efecto de las estadísticas.
Desde el punto de vista organizativo, lo que mejor funciona es un breve Registro de cambios Por tabla: columna, número de intervalos, momento, valores medidos antes y después. Esto facilita las correcciones posteriores y evita interacciones poco claras.
Aspectos operativos: restricciones, costes, portabilidad
ANALYZE TABLE realiza una Bloqueo de metadatos en la tabla, pero no bloquea de forma permanente las operaciones habituales de lectura y escritura. En tablas muy grandes, preveo tiempo suficiente; la generación del histograma funciona con muestras y está limitada por la memoria (palabra clave: memoria interna para el cálculo). El espacio que ocupa la propia estadística sigue siendo moderado: entre unas pocas docenas y unos pocos cientos de kilobytes por columna con 100-256 compartimentos es una estimación realista. No obstante, hago un cálculo total, ya que muchas columnas multiplicadas por muchas tablas dan como resultado metadatos visibles.
En Volcados lógicos (mysqldump) los histogramas no se transfieren junto con los datos; tras una restauración, los vuelvo a crear de forma específica. En una actualización in situ, se conservan. Por el lado de los permisos, necesito privilegios suficientes para ejecutar ANALYZE TABLE en los objetos correspondientes; en entornos estrictamente regulados, integro el mantenimiento en procesos de mantenimiento automatizados.
Cuándo los histogramas no sirven de nada
Me ahorro Histogramas en columnas que contienen muy pocos valores y que, de todos modos, se pueden estimar con bastante precisión. Incluso en aquellos casos en los que un buen índice ya cubre conjuntos de resultados mínimos, un histograma rara vez aporta un beneficio adicional. Las distribuciones uniformes no requieren un nivel de detalle excesivo. En sistemas muy dinámicos y con un uso intensivo de la escritura, el mantenimiento puede generar una carga innecesaria si lo inicio con demasiada frecuencia. En tales situaciones, utilizo la Energía más bien en estrategias de índices, diseño de consultas y almacenamiento en caché.
Guía rápida en forma de tabla
Yo utilizo el siguiente Visión general Para tomar decisiones rápidas: qué tipo de histograma es el adecuado, cómo configurar los intervalos y qué costes conlleva. La tabla sirve como guía de referencia durante las revisiones de consultas problemáticas. La actualizo en función de lo aprendido con EXPLAIN ANALYZE y las métricas de producción. Al hacerlo, tengo en cuenta que las distribuciones de datos cambian y que las hipótesis históricas quedan obsoletas. Lo fundamental sigue siendo la Calidad del plan confirmarlo con mediciones reales.
| Aspecto | Recomendación | Beneficio | compensación | Ejemplo |
|---|---|---|---|---|
| Tipo | Singleton con pocos valores dominantes | Porcentajes exactos de aciertos para las categorías más frecuentes | Poco útil en zonas continuas | estado_del_pedido |
| Tipo | Equi-Height con datos continuos distorsionados | Mejor estimación a lo largo del rango de valores | Más metadatos cuando hay muchos buckets | created_at, price |
| Cubos | Empieza por 100 y luego ajústalo | Resolución equilibrada | Mayor carga de análisis y almacenamiento entre 512 y 1024 | CON 100 CUBIERNAS |
| Atención | Después de realizar cambios importantes en los datos, ejecuta ANALYZE | Selectividades actuales | Planificar la ventana de mantenimiento | ANALYZE TABLE … UPDATE HISTOGRAM |
| Controlar | Comprobar mediante COLUMN_STATISTICS | Transparencia y auditoría | Se requiere interpretación de JSON | INFORMATION_SCHEMA.COLUMN_STATISTICS |
Integración en el panorama general del tuning
Trato Histogramas como elemento fundamental, junto con los índices, el diseño de consultas, el almacenamiento en caché y los parámetros de hardware. A menudo, un buen histograma cambia el orden de las uniones, reduce las operaciones de E/S y garantiza tiempos de respuesta constantes. No obstante, no sustituye a unas estrategias de indexación bien diseñadas ni a un esquema eficiente. Quien analice en profundidad las decisiones de planificación se beneficiará de Entender los planes de ejecución y compara modelos de costes con plazos reales. Compruebo periódicamente si los Cargas de trabajo si siguen ajustándose a las estadísticas o si es necesario realizar ajustes.
Escenarios avanzados de unión de tablas
Los histogramas resultan especialmente útiles cuando hay varias tablas con filtros. Ejemplo:
SELECT o.id, o.amount
FROM users u
JOIN orders o ON o.user_id = u.id
WHERE u.country = 'DE'
AND o.status = 'canceled'
AND o.created_at >= NOW() - INTERVAL 30 DAY;
Sin histogramas, es posible que el optimizador subestime la selectividad de o.status=’canceled‘ o sobreestime la proporción de usuarios alemanes. Con un histograma en y país y sin estado (en su caso, también en o.created_at) el planificador suele darse cuenta de que la combinación es extremadamente selectiva. En la práctica, observo que MySQL determina primero el subconjunto más pequeño (por ejemplo, mediante un índice en users(country) u orders(status, created_at)) y solo después ejecuta la unión, en lugar de escanear la tabla grande. Esto ahorra operaciones de E/S, memoria intermedia y CPU, y estabiliza la latencia incluso bajo carga.
Porque los histogramas solo en una sola columna las estrategias de índice siguen siendo importantes: un índice compuesto en (status, created_at) puede acelerar aún más el Range Scan. El histograma se encarga aquí, sobre todo, de que el optimizador utilice este Estrategia considera que es barato en general.
Resumen para la práctica
He puesto MySQL-Utilizo histogramas cuando el optimizador se equivoca al basarse en estadísticas predeterminadas y las distribuciones asimétricas generan planes erróneos. Con ANALYZE TABLE, creo, actualizo y elimino de forma selectiva estadísticas en las columnas que predominan en los filtros y las uniones. Elijo entre «Singleton» y «Equi-Height» en función de los datos, y calibro el número de compartimentos mediante mediciones. Con EXPLAIN ANALYZE compruebo si el orden de las uniones, las posiciones de los filtros y los escaneos cambian según lo deseado. De este modo, consigo con poco Sobrecarga Consultas notablemente más rápidas, a menudo sin necesidad de índices adicionales.


