¿De dónde lee MySQL Query Optimizer las estadísticas del índice?

14

Estoy tratando de determinar de dónde el optimizador MySQL obtiene la lista de índices que están disponibles para una tabla cuando estima el costo de (prepara) una consulta.

ivotron
fuente
Haga clic en +1 para esta buena pregunta porque los desarrolladores y los DBA deben hacer una pausa y pensar en cómo se compilan y almacenan las estadísticas de índice.
RolandoMySQLDBA
Como referencia, desde el sitio web de documentación de mysql: < dev.mysql.com/doc/refman/5.0/en/innodb-restrictions.html >> ANALYZE TABLEdetermina la cardinalidad de índice (como se muestra en la columna de Cardinalidad de SHOW INDEXsalida) haciendo ocho inmersiones aleatorias a cada de los árboles de índice y actualizar las estimaciones de cardinalidad de índice en consecuencia. Debido a que estas son solo estimaciones, las ejecuciones repetidas de ANALYZE TABLE pueden producir números diferentes. Esto ANALYZE TABLEacelera en las tablas de InnoDB pero no es 100% preciso porque no tiene en cuenta todas las filas.
Chen Xie

Respuestas:

6

La respuesta directa para esto sería

information_schema.statistics

mysql> desc information_schema.statistics;
+---------------+---------------+------+-----+---------+-------+
| Field         | Type          | Null | Key | Default | Extra |
+---------------+---------------+------+-----+---------+-------+
| TABLE_CATALOG | varchar(512)  | NO   |     |         |       |
| TABLE_SCHEMA  | varchar(64)   | NO   |     |         |       |
| TABLE_NAME    | varchar(64)   | NO   |     |         |       |
| NON_UNIQUE    | bigint(1)     | NO   |     | 0       |       |
| INDEX_SCHEMA  | varchar(64)   | NO   |     |         |       |
| INDEX_NAME    | varchar(64)   | NO   |     |         |       |
| SEQ_IN_INDEX  | bigint(2)     | NO   |     | 0       |       |
| COLUMN_NAME   | varchar(64)   | NO   |     |         |       |
| COLLATION     | varchar(1)    | YES  |     | NULL    |       |
| CARDINALITY   | bigint(21)    | YES  |     | NULL    |       |
| SUB_PART      | bigint(3)     | YES  |     | NULL    |       |
| PACKED        | varchar(10)   | YES  |     | NULL    |       |
| NULLABLE      | varchar(3)    | NO   |     |         |       |
| INDEX_TYPE    | varchar(16)   | NO   |     |         |       |
| COMMENT       | varchar(16)   | YES  |     | NULL    |       |
| INDEX_COMMENT | varchar(1024) | NO   |     |         |       |
+---------------+---------------+------+-----+---------+-------+
16 rows in set (0.01 sec)

Puedes SELECCIONAR de esa tabla con

SELECT * FROM information_schema.statistics
WHERE table_schema='mydb' AND table_name='mytable';

o ver las estadísticas haciendo

MOSTRAR ÍNDICES DE mydb.mytable;

Tenga en cuenta que esta tabla no siempre es precisa en un entorno de escritura intensa. Periódicamente, deberá ejecutar ANALYZE TABLE en todas las tablas MyISAM que se actualizan con frecuencia. De lo contrario, MySQL Query Optimizer, que se basa en information_schema.statistics, a veces puede tomar malas decisiones al desarrollar planes EXPLAIN para consultas. Las estadísticas de índice deben estar lo más actualizadas posible.

ANALYZE TABLE no tiene ABSOLUTAMENTE EFECTO contra las tablas InnoDB. Todas las estadísticas de índice para InnoDB se calculan a pedido mediante inmersiones en las páginas BTREE. Por lo tanto, cuando ejecuta SHOW INDEXES FROM contra una tabla InnoDB, las cardinalidades que se muestran son siempre aproximaciones.

ACTUALIZACIÓN 2011-06-21 12:17 EDT

Para aclarar la TABLA DE ANÁLISIS, permítanme reformular. Ejecutar ANALYZE TABLE en tablas InnoDB es completamente inútil. Incluso si ejecutó ANALYZE TABLE en una tabla de InnoDB, el motor de almacenamiento de InnoDB realiza inmersiones en el índice para aproximaciones de cardinalidad una y otra vez, destruyendo las estadísticas que acaba de compilar . De hecho, Percona realizó algunas pruebas en la TABLA DE ANÁLISIS y también llegó a esa conclusión.

RolandoMySQLDBA
fuente
5

Re: ANALYZE TABLE no tiene ABSOLUTAMENTE EFECTO contra las tablas InnoDB.

No estoy seguro de si esta afirmación es cierta. Tenemos muchas tablas de lectura y escritura innodb y cuando mysql optimizer toma la mala decisión, la salida de explicación de la consulta muestra una mala estrategia. y también SHOW INDEXES de una tabla Innodb muestra tanta variación en sus valores de cardinalidad. Pero ejecutar un comando ANALIZAR en esas tablas innodb corrige el plan de explicación y también elimina el comportamiento de varianza de la cardinalidad. No sé si el comando ANALIZAR tabla en las tablas Innodb ayuda todo el tiempo o no, pero en nuestro caso, ayudó el 99% del tiempo.

Hemos eliminado por completo la mala elección del optimizador mysql al incluir "STRAIGHT_JOIN" en nuestras consultas. Esto obligó al optimizador mysql a no tomar malas decisiones o cualquier elección, sino simplemente seguir la condición JOIN de lo que definimos en la consulta tal como está.

Revathi
fuente
Actualicé mi respuesta para resaltar la inutilidad de ANALYZE TABLE en las tablas de InnoDB.
RolandoMySQLDBA
Estoy de acuerdo con su respuesta cuando mencionó la variación en la cardinalidad. Eso es exactamente lo que estaba diciendo cuando dije aproximaciones de cardinalidad.
RolandoMySQLDBA
También necesitaba mencionar que usar sugerencias en las consultas no siempre es lo mejor que se puede hacer cuando MySQL Query Optimizer tiende a eliminarlas a veces. Aquí hay un enlace a lo que sucede internamente con las consultas que realmente pueden hacer que los datos desaparezcan en partes de los planes de consulta: dba.stackexchange.com/questions/1371/…
RolandoMySQLDBA
2

ANALYZE TABLE for MyISAM escanea toda la tabla y reconstruye las estadísticas, que se guardan (creo) en el archivo .MYI. Rara vez se necesita.

TABLA DE ANÁLISIS para InnoDB hace algo: hace la inmersión mencionada. El problema es que puede ayudar, empeorar las cosas o (lo más probable) no hará ninguna diferencia visible (excepto en cardinalidades).

Las versiones más nuevas prometen permitir cambiar las 8 sondas no tan aleatorias a (1) más aleatorias, (2) permitiéndole cambiar el "8" (¡hay ventajas y desventajas de esto!), Y (3) guardar entre reinicios.

En pocas palabras: InnoDB todavía no lo ha entendido bien. ANALICE cuando lo desee, pero no contenga la respiración.

Actualizar

Reformular ... ANALYZE TABLEtiene un efecto temporal (posiblemente beneficioso, posiblemente no) en las optimizaciones de las tablas de InnoDB.

"Versión más reciente": a partir de 5.6.6 (2012) y MariaDB 10.1 (2014), las estadísticas se manejan mucho mejor y ANALYZEahora (1) se necesita con menos frecuencia y (2) es más permanente.

Rick James
fuente