Este artículo lo lleva a comprender cómo se recopilan las estadísticas InnoDB de MySQL

prefacio

A menudo usamos algunos datos estadísticos cuando hablábamos del costo de la consulta. Por ejemplo, podemos show table statusver los datos estadísticos sobre la tabla y show indexlos datos estadísticos sobre el índice. Entonces, ¿de dónde provienen estos datos estadísticos? ¿Cómo se recogen? Este capítulo se centrará en InnoDB存储引擎las estrategias de recopilación de datos estadísticos.Después de leer este capítulo, comprenderá por qué siempre se dice que InnoDB的统计信息es una estimación inexacta.

1. Dos métodos diferentes de almacenamiento de datos estadísticos

InnoDB proporciona dos formas de almacenar datos estadísticos:

  • 永久性的统计数据: este tipo de datos estadísticos se almacenan en el disco, es decir, los datos estadísticos aún están allí después de que se reinicia el servidor

  • 非永久性的统计数据: Este tipo de datos estadísticos se almacenan en la memoria. Cuando se apaga el servidor, estos datos estadísticos se borrarán. Después de reiniciar el servidor, estos datos estadísticos se recopilarán nuevamente en algunos escenarios apropiados.

MySQL nos proporciona variables del sistema innodb_stats_persistentpara controlar de qué manera almacenar los datos estadísticos. Antes de MySQL 5.6.6, innodb_stats_persistentel valor predeterminado de es OFF, lo que significa que las estadísticas de InnoDB se almacenan en la memoria de forma predeterminada. En versiones posteriores, el innodb_stats_persistentvalor predeterminado es ON, es decir, las estadísticas se almacenan en el disco de forma predeterminada.

Sin embargo, InnoDB recopila y almacena estadísticas en unidades de tablas por defecto, es decir, podemos almacenar las estadísticas de algunas tablas (y las estadísticas de índice de la tabla) en el disco y almacenar las estadísticas de otras tablas en la memoria. ¿Cómo lo hiciste? stats_persistentPodemos especificar el atributo para indicar el método de almacenamiento de datos estadísticos de la tabla al crear y modificar la tabla :

create table 表名 (...) engine=innodb, stats_persistent = (1|0);
alter table 表名 engine=innodb, stats_persistent = (1|0);
  • En ese momentostats_persistent=1 , indicó que queríamos almacenar permanentemente los datos estadísticos de la tabla en磁盘上
  • En ese momentostats_persistent=0 , indicó que queríamos almacenar temporalmente los datos estadísticos de la tabla en内存中

Cabe señalar que si creamos un atributo al crear una tabla 未指定stats_persistent, el valor predeterminado 采用系统变量innodb_stats_persistentse utiliza como el valor del atributo

mysql> show variables like 'innodb_stats_persistent';
+-------------------------+-------+
| Variable_name           | Value |
+-------------------------+-------+
| innodb_stats_persistent | ON    |
+-------------------------+-------+
1 row in set (0.01 sec)

mysql> set persist innodb_stats_persistent =1;
Query OK, 0 rows affected (0.01 sec)

2. Estadísticas persistentes basadas en disco

Cuando elegimos almacenar los datos estadísticos de una tabla y el índice de la tabla en el disco, en realidad almacenamos estos datos estadísticos en dos tablas:

mysql> show tables from mysql like 'innodb%';
+---------------------------+
| Tables_in_mysql (innodb%) |
+---------------------------+
| innodb_index_stats        |
| innodb_table_stats        |
+---------------------------+
2 rows in set (0.03 sec)

Como puede ver, estas dos tablas se encuentran en la base de datos del sistema mysql, donde:

  • innodb_table_statsLos datos estadísticos sobre la tabla se almacenan y cada registro corresponde a los datos estadísticos de una tabla

  • innodb_index_statsLos datos estadísticos sobre el índice se almacenan y cada registro corresponde a los datos estadísticos de un elemento estadístico de un índice

Lo que vamos a hacer a continuación es echar un vistazo a lo que hay en estas dos tablas y cómo se generan los datos en las tablas.

2.1 innodb_table_stats

Aquí hay una mirada directa a innodb_table_statslo que hace cada columna en la tabla:

nombre del campo describir
nombre de la base de datos Nombre de la base de datos
nombre de la tabla Nombre de la tabla
última actualización Este registro fue actualizado por última vez
n_filas el número de registros en la tabla
tamaño_índice_agrupado Número de páginas ocupadas por el índice agrupado de la tabla
suma_de_otros_tamaños_de_índice El número de páginas ocupadas por los otros índices de la tabla.

Tenga en cuenta que la clave principal de esta tabla es (database_name,table_name), es decir innodb_table_stats表的每条记录代表着一个表的统计信息. Veamos directamente el contenido de esta tabla:

mysql> select * from mysql.innodb_table_stats where database_name= 'testdb' limit 2;
+---------------+---------------+---------------------+--------+----------------------+--------------------------+
| database_name | table_name    | last_update         | n_rows | clustered_index_size | sum_of_other_index_sizes |
+---------------+---------------+---------------------+--------+----------------------+--------------------------+
| testdb        | demo1         | 2023-05-06 18:20:56 |      1 |                    1 |                        0 |
| testdb        | demo8         | 2023-05-16 16:38:16 |  18758 |                   97 |                      170 |
+---------------+---------------+---------------------+--------+----------------------+--------------------------+
2 rows in set (0.01 sec)

Puede ver que la información estadística de las tablas que conocemos demo8corresponde mysql.innodb_table_statsal segundo registro. Los valores de varios elementos estadísticos importantes son los siguientes:

  • n_rowsEl valor es 18758, lo que indica que demo8hay alrededor de 187581 registros en la tabla, tenga en cuenta que este dato es un valor estimado
  • clustered_index_sizeEl valor de es 97, que indica demo8que el índice agrupado de la tabla ocupa 97páginas, y este valor también es un valor estimado
  • sum_of_other_index_sizesEl valor de es 170, indicando que demo8los demás índices de la tabla ocupan 170un total de páginas, y este valor también es un valor estimado

2.1.1 Recopilación de estadísticas de n_rows

¿Por qué se ha enfatizado que n_rowsel valor de este elemento estadístico es un valor estimado? Ahora a revelar la respuesta. InnoDB cuenta cuántos registros hay en una tabla como esta:

  • Seleccione cada página de hoja de nodo propio de acuerdo con un cierto algoritmo (no puramente aleatorio), calcule el número de registros de valor de clave principal en cada página y luego calcule el número promedio de registros de valor de clave principal en una página multiplicado por el número de todos leaf self-nodes es el valor de n_rows de la tabla

    小提示:
    El proceso de cálculo real es un poco más complicado que esto, pero esto es más o menos lo que significa

Se puede ver que n_rowsla precisión de este valor depende de la cantidad de páginas muestreadas durante las estadísticas MySQL ha preparado una innodb_stats_persistent_sample_pagesvariable de sistema con nombre para que controlemos la cantidad de páginas muestreadas cuando calculamos estadísticas cuando usamos estadísticas permanentes.

  • Cuanto mayor sea el valor establecido, más preciso será el valor estadístico n_rows, pero las estadísticas tardan más
  • Cuanto menor sea el valor establecido, más inexacto será el valor estadístico n_rows, pero las estadísticas llevarán menos tiempo.

Por lo tanto, en el uso real, debemos sopesar los pros y los contras. El valor predeterminado de esta variable del sistema es 20.

mysql> show variables like 'innodb_stats_persistent_sample_pages';
+--------------------------------------+-------+
| Variable_name                        | Value |
+--------------------------------------+-------+
| innodb_stats_persistent_sample_pages | 20    |
+--------------------------------------+-------+
1 row in set (0.01 sec)

mysql> set persist innodb_stats_persistent_sample_pages =20;
Query OK, 0 rows affected (0.02 sec)

Como dijimos antes, pero yo , también podemos establecer individualmente el número de páginas de muestreo de una tabla determinada. El método de configuración es especificar el método de almacenamiento de datos estadísticos de la tabla nnoDB默认是以表为单位来收集和存储统计数据的especificando el atributo al crear o modificar la tabla:stats_sample_pages

create table 表名 (...) engine=innodb, stats_sample_pages = 具体的采样页面数量;
alter table 表名 engine=innodb, stats_sample_pages = 具体的采样页面数量;

stats_sample_pagesSi no especificamos un atributo en la declaración que crea la tabla , innodb_stats_persistent_sample_pagesel valor de la variable del sistema se utilizará como valor del atributo por defecto.

2.1.2 Colección de elementos estadísticos clustered_index_size y sum_of_other_index_sizes

Contar estos dos datos requiere mucho InnoDB表空间conocimiento que hemos aprendido antes. Si no ha leído ese capítulo en absoluto, entonces no debe leer el proceso de cálculo a continuación (no puede entenderlo); si lo ha leído, entonces Todos encontrará que InnoDBel conocimiento de los espacios de tabla es realmente útil.

Este artículo lo lleva a comprender el espacio de tabla InnoDB de MySQL [ a través del tren ]

El proceso de recogida de estos dos elementos estadísticos es el siguiente:

Paso 1: encuentre la ubicación de la página raíz correspondiente a cada índice de la tabla del diccionario de datos (la información de la página raíz correspondiente a cada índice se almacena en la sys_indexestabla )

Paso 2:Header busque el segmento de nodo de hoja y el segmento de nodo que no es de hoja correspondientes en la página de la página raíz Segment Header. Page HeadeEn la sección r de la página raíz de cada índice hay dos campos:

  • Page_btr_seg_leaf:Segment HeaderIndica la información del segmento hoja del árbol B+
  • Page_btr_seg_topSegment Header: Indica la información del segmento no hoja del árbol B+

Paso 3:Segment Header Encuentre la estructura correspondiente a los dos segmentos del segmento de nodo hoja y el segmento de nodo no hoja INODE Entry.

Segment HeaderLa estructura es la siguiente:

inserte la descripción de la imagen aquí
De la estructura correspondiente , INODE Entryse puede encontrar que este segmento corresponde a todas las direcciones de página dispersas y freelos nodos base de la lista enlazada.not_fullfull

INODE EntryLa estructura es la siguiente:

inserte la descripción de la imagen aquí
Cuente directamente el número de páginas dispersas y luego List Lengthlea el tamaño del área ocupada por el segmento de los campos de las tres listas vinculadas. Cada área ocupa 64 páginas, por lo que se pueden contar las páginas ocupadas por el segmento completo.

Este es un diagrama esquemático del nodo base de la lista enlazada:

inserte la descripción de la imagen aquí
Paso 4: Calcule la cantidad de páginas ocupadas por el segmento de nodo hoja y el segmento de nodo no hoja del índice agrupado respectivamente, y su suma es el valor de , y calcule la cantidad clustered_index_sizede páginas ocupadas por los otros índices de acuerdo con la misma rutina y sumarlos a sum_of_other_index_sizes el valor de

Aquí hay una pregunta a la que todos deben prestar atención, decimos que cuando hay muchos datos en un segmento (más de 32 páginas), el espacio se solicitará en unidades de distritos, el problema aquí es que algunas páginas en No se puede utilizar el espacio de la aplicación en unidades de distritos, pero se cuentan en las estadísticas clustered_index_sizey el tiempo, por lo que el número de páginas ocupadas por el índice agrupado y otros índices puede ser mayor que estos dos valores.sum_of_other_index_sizes

2.2 innodb_index_stats

Eche un vistazo directamente a innodb_index_statslo que hace cada columna en esta tabla:

nombre del campo describir
nombre de la base de datos Nombre de la base de datos
nombre de la tabla Nombre de la tabla
nombre_índice nombre de índice
última actualización Este registro fue actualizado por última vez
stat_name El nombre del elemento estadístico.
valor_estadístico El valor del ítem estadístico correspondiente
tamaño de la muestra El número de páginas muestreadas para la generación de estadísticas.
stat_description Descripción del ítem estadístico correspondiente

Nótese que la clave principal de esta tabla es (database_name,table_name,index_name,stat_name), donde stat_namese refiere al nombre del ítem estadístico, es decir, innodb_index_statscada registro de la tabla representa un ítem estadístico de un índice. Tal vez esto lo confunda un poco acerca de a qué se refiere este elemento estadístico. No se preocupe, echemos un vistazo a las demo8estadísticas del índice sobre la tabla:

mysql> select * from mysql.innodb_index_stats where table_name='demo8';
+---------------+------------+--------------+---------------------+--------------+------------+-------------+-----------------------------------+
| database_name | table_name | index_name   | last_update         | stat_name    | stat_value | sample_size | stat_description                  |
+---------------+------------+--------------+---------------------+--------------+------------+-------------+-----------------------------------+
| testdb        | demo8      | PRIMARY      | 2023-05-16 16:38:16 | n_diff_pfx01 |      18750 |          20 | id                                |
| testdb        | demo8      | PRIMARY      | 2023-05-16 16:38:16 | n_leaf_pages |         75 |        NULL | Number of leaf pages in the index |
| testdb        | demo8      | PRIMARY      | 2023-05-16 16:38:16 | size         |         97 |        NULL | Number of pages in the index      |
| testdb        | demo8      | idx_key1     | 2023-05-16 16:38:16 | n_diff_pfx01 |        256 |          22 | key1                              |
| testdb        | demo8      | idx_key1     | 2023-05-16 16:38:16 | n_diff_pfx02 |      18567 |          22 | key1,id                           |
| testdb        | demo8      | idx_key1     | 2023-05-16 16:38:16 | n_leaf_pages |         22 |        NULL | Number of leaf pages in the index |
| testdb        | demo8      | idx_key1     | 2023-05-16 16:38:16 | size         |         23 |        NULL | Number of pages in the index      |
| testdb        | demo8      | idx_key2     | 2023-05-16 16:38:16 | n_diff_pfx01 |      18565 |          18 | key2                              |
| testdb        | demo8      | idx_key2     | 2023-05-16 16:38:16 | n_leaf_pages |         18 |        NULL | Number of leaf pages in the index |
| testdb        | demo8      | idx_key2     | 2023-05-16 16:38:16 | size         |         19 |        NULL | Number of pages in the index      |
| testdb        | demo8      | idx_key3     | 2023-05-16 16:38:16 | n_diff_pfx01 |       4053 |          30 | key3                              |
| testdb        | demo8      | idx_key3     | 2023-05-16 16:38:16 | n_diff_pfx02 |      18568 |          30 | key3,id                           |
| testdb        | demo8      | idx_key3     | 2023-05-16 16:38:16 | n_leaf_pages |         30 |        NULL | Number of leaf pages in the index |
| testdb        | demo8      | idx_key3     | 2023-05-16 16:38:16 | size         |         31 |        NULL | Number of pages in the index      |
| testdb        | demo8      | idx_key_part | 2023-05-16 16:38:16 | n_diff_pfx01 |      16122 |          50 | key_part1                         |
| testdb        | demo8      | idx_key_part | 2023-05-16 16:38:16 | n_diff_pfx02 |      18570 |          50 | key_part1,key_part2               |
| testdb        | demo8      | idx_key_part | 2023-05-16 16:38:16 | n_diff_pfx03 |      18570 |          50 | key_part1,key_part2,key_part3     |
| testdb        | demo8      | idx_key_part | 2023-05-16 16:38:16 | n_diff_pfx04 |      18570 |          50 | key_part1,key_part2,key_part3,id  |
| testdb        | demo8      | idx_key_part | 2023-05-16 16:38:16 | n_leaf_pages |         50 |        NULL | Number of leaf pages in the index |
| testdb        | demo8      | idx_key_part | 2023-05-16 16:38:16 | size         |         97 |        NULL | Number of pages in the index      |
+---------------+------------+--------------+---------------------+--------------+------------+-------------+-----------------------------------+
20 rows in set (0.03 sec)

Este resultado es demasiado, la forma correcta de ver este resultado es esta:

  • Primero mire index_namela columna, que indica la información estadística de a qué índice pertenece el registro. De los resultados, podemos ver que PRIMARYel índice (es decir, la clave principal) ocupa 3 registros y idx_key_partel índice ocupa 6 registros.

  • Para index_nameregistros con la misma columna, stat_nameindica el nombre del elemento estadístico para el índice y stat_valuemuestra el valor del índice en el elemento estadístico, stat_descriptionque se utiliza para describir el significado del elemento estadístico. Echemos un vistazo a las estadísticas de un índice:

    • n_leaf_pages: Indica cuántas páginas están ocupadas por los nodos hoja del índice

    • size: Indica cuántas páginas ocupa el índice en total

    • n_diff_pfxNN: Indica cuántos valores únicos tiene la columna de índice correspondiente. El NN en él se ve un poco raro, ¿qué quieres decir? De hecho, NN se puede reemplazar con números como 01, 02, 03…. Por ejemplo, para idx_key_part:

      • n_diff_pfx01Significa contar key_part1el número de valores únicos en esta única columna.
      • n_diff_pfx02Indica key_part1cuantos valores únicos se combinan en las dos columnas de estadísticas y key_part2
      • n_diff_pfx03Indica el número de valores únicos en la combinación de estadísticas key_part1, key_part2y estas tres columnaskey_part3
      • n_diff_pfx04Indica cuántos valores únicos se combinan en las cuatro columnas de estadísticas key_part1, key_part2, key_part3,id

小提示:
Cabe señalar aquí que para los índices secundarios ordinarios, no se garantiza que los valores de la columna de índice sean únicos. Por ejemplo, para idx_key1, la columna key1 puede tener muchos registros con valores duplicados. En este momento, solo agregando el valor de la clave principal a la columna de índice se pueden distinguir los registros de índice secundario con el mismo valor de las dos columnas de índice. No existe tal problema para la clave principal y el índice secundario único.Pueden garantizar que los valores de la columna de índice no se repitan, por lo que no es necesario contar la cantidad de valores únicos agregados al valor de clave principal después de la columna de índice. Por ejemplo, idx_key1 anterior tiene dos elementos estadísticos, n_diff_pfx01 y n_diff_pfx02, mientras que idx_key2 solo tiene un elemento estadístico, n_diff_pfx01.

  • Al calcular cuántos valores únicos están contenidos en algunas columnas de índice, estas páginas de nodos de hoja deben muestrearse, y la sizecolumna indica la cantidad de páginas muestreadas

小提示:
Para un índice conjunto con múltiples columnas, el número de páginas muestreadas es: innodb_stats_persistent_sample_pages × 索引列的个数. Cuando la cantidad de páginas que se van a muestrear es mayor que la cantidad de nodos de hoja en el índice, se utiliza directamente una exploración completa de la tabla para contar la cantidad de valores únicos en la columna del índice. Entonces puede ver en los resultados de la consulta que los valores de la columna de tamaño correspondientes a diferentes índices pueden ser diferentes.

2.3 Actualizar periódicamente las estadísticas

A medida que agregamos, eliminamos y modificamos la tabla, los datos de la tabla también cambian. ¿ innodb_table_statsDeberían innodb_index_statscambiarse los datos estadísticos de la tabla en consecuencia? Por supuesto, cambiará.Si permanece sin cambios, el costo calculado por el optimizador de consultas MySQL se quedará muy atrás. MySQL proporciona las siguientes dos formas de actualizar las estadísticas:

  • encenderinnodb_stats_auto_recalc

    La variable del sistema innodb_stats_auto_recalcdetermina si el servidor recalcula automáticamente las estadísticas, su valor por defecto es ON, es decir, la función está habilitada por defecto. Cada tabla mantiene una variable, que registra la cantidad de registros que se agregaron, eliminaron o modificaron.Si la cantidad de registros modificados excede el tamaño de la tabla y la función de recalcular automáticamente los datos estadísticos está activada, el 10%servidor se volverá a realizar el cálculo de los datos estadísticos y se innodb_table_statsactualizará la tabla de suma innodb_index_stats. Sin embargo, el proceso de recalcular automáticamente los datos estadísticos se produce de forma asíncrona, es decir, incluso si la cantidad de registros modificados en la tabla supera 10%, el recalculo automático de los datos estadísticos no se realizará de inmediato y el cálculo puede retrasarse unos segundos. .

mysql> show variables like 'innodb_stats_auto_recalc';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| innodb_stats_auto_recalc | ON    |
+--------------------------+-------+
1 row in set (0.00 sec)

mysql> set persist innodb_stats_auto_recalc =1;
Query OK, 0 rows affected (0.00 sec)

Una vez más, InnoDB recopila y almacena datos estadísticos en unidades de tablas de forma predeterminada. También podemos establecer el atributo de recalcular automáticamente las estadísticas para una tabla por separado. El método de configuración es especificar el atributo al crear o modificar la tabla. para stats_auto_recalcespecificar cómo se almacenan las estadísticas de la tabla:

create table 表名 (...) engine=innodb, stats_auto_recalc = (1|0);
alter table 表名 engine=innodb, stats_auto_recalc = (1|0);

En ese momentostats_auto_recalc=1 , indicando que queremos que la tabla recalcule automáticamente las estadísticas stats_persistent=0En ese momento , indicando que no queremos que la tabla recalcule automáticamente las estadísticas

Si no especificamos un atributo al crear una tabla stats_auto_recalc, innodb_stats_auto_recalcel valor de la variable del sistema se usa como el valor del atributo por defecto.

  • Invocar analyze tabledeclaraciones manualmente para actualizar estadísticas

    Si innodb_stats_auto_recalcel valor de la variable del sistema es OFF, también podemos llamar manualmente analyze tablela declaración para recalcular los datos estadísticos.Por ejemplo, podemos actualizar demo8los datos estadísticos sobre la tabla de esta manera:

mysql> analyze table demo8;

Cabe señalar que analyze tablela declaración recalculará inmediatamente los datos estadísticos, es decir, el proceso es síncrono. Este proceso puede ser particularmente lento cuando hay muchos índices en la tabla o hay demasiadas páginas de muestra. No ejecute la declaración. solo por nada analyze tableSe ejecuta de nuevo cuando no está muy ocupado.

2.4 Actualizar manualmente las tablas innodb_table_stats e innodb_index_stats

De hecho innodb_table_stats, innodb_index_statsla tabla es equivalente a una tabla ordinaria, y podemos agregarlas, eliminarlas, modificarlas y consultarlas. Esto también significa que podemos actualizar manualmente las estadísticas de una tabla o índice. Por ejemplo, si queremos demo8cambiar las estadísticas de la tabla sobre el número de filas, podemos hacer esto:

Paso 1: actualice la tabla demo8

update innodb_table_stats set n_rows = 1 where table_name = 'demo8';

Paso 2: Deje que el optimizador de consultas de MySQL vuelva a cargar nuestros datos modificados

Después de la actualización, innodb_table_statslos datos de una tabla simplemente se modifican y el optimizador de consultas de MySQL necesita volver a cargar los datos modificados, simplemente ejecute el siguiente comando:

flush table demo8;

Más tarde, cuando usamos show table statusla declaración para ver los datos estadísticos de la tabla, podemos ver que la línea Filas ha cambiado a 1.

3. Estadísticas no persistentes basadas en memoria

Cuando innodb_stats_persistentestablecemos el valor de la variable del sistema en OFF, los datos estadísticos de la tabla creada posteriormente no son permanentes por defecto, o establecemos directamente el valor stats_persistentdel atributo en 0 al crear o modificar la tabla, entonces los datos estadísticos de los datos de la tabla son impermanentes.

A diferencia de las estadísticas persistentes, el número de páginas muestreadas por las estadísticas no persistentes está innodb_stats_transient_sample_pagescontrolado por el valor predeterminado de 8 para esta variable del sistema. Además, dado que los datos estadísticos no permanentes se actualizan con frecuencia, el optimizador de consultas de MySQL se basa en datos estadísticos que cambian con frecuencia al calcular los costos de las consultas y genera planes de ejecución que cambian con frecuencia, lo que puede confundir a todos. Sin embargo, las versiones recientes de MySQL no usan este tipo de estadísticas no permanentes basadas en memoria, por lo que no sabemos mucho al respecto.

mysql> show variables like 'innodb_stats_transient_sample_pages';
+-------------------------------------+-------+
| Variable_name                       | Value |
+-------------------------------------+-------+
| innodb_stats_transient_sample_pages | 8     |
+-------------------------------------+-------+
1 row in set (0.01 sec)

mysql> set persist innodb_stats_transient_sample_pages =1;
Query OK, 0 rows affected (0.00 sec)

Cuarto, el uso de innodb_stats_method

Sabemos que las estadísticas de la cantidad de valores únicos en la columna de índice son muy importantes para el optimizador de consultas de MySQL, ya que se puede usar para calcular cuántas filas se repiten en un valor promedio en la columna de índice. Tiene dos principales escenarios de aplicación:

  • Hay demasiados intervalos de un solo punto en la consulta de una sola tabla, por ejemplo: cuando hay demasiados parámetros en IN, el index diverendimiento es demasiado intensivo para acceder directamente al índice de árbol B+ para contar la cantidad de registros correspondientes a cada uno. intervalo de punto, así que confíe directamente en cuántas filas se repiten para obtener un valor promedio en los datos estadísticos para calcular el número de registros correspondientes al intervalo de un solo punto.
    select * from tbl_name where key in ('xx1', 'xx2', ..., 'xxn');

  • Al conectar consultas, si hay una condición de combinación de coincidencia de equivalencia que involucra dos tablas, y la columna en la tabla controlada correspondiente a la condición de combinación tiene un índice, puede usar el método de acceso para consultar la tabla controlada, por ejemplo ref:

    select * from t1 join t2 on t1.column = t2.key where ...;

    Antes de ejecutar realmente la consulta en la tabla t2, el valor de t1.comumn es incierto, por lo que no podemos index diveacceder directamente al índice del árbol B+ para contar la cantidad de registros correspondientes a cada intervalo de un solo punto, por lo que solo podemos confiar en Cuántos veces es el valor promedio en los datos estadísticos repetidos para calcular el número de registros correspondientes al intervalo de un solo punto.

Al contar la cantidad de valores únicos en una columna de índice, existe un problema problemático que es cómo tratar los valores NULL en la columna de índice. Por ejemplo, el contenido de una columna de índice es el siguiente:

+------+
| col  |
+------+
|    1 |
|    2 |
| NULL |
| NULL |
+------+

En este momento, calcular la cantidad de valores únicos en la columna col tiene las siguientes diferencias:

  • Algunas personas piensan que el valor NULL representa un valor indeterminado, por lo que MySQL piensa que cualquier expresión que se compare con el valor NULL se evalúa como NULL, eso es todo:
mysql> select 1 = null;
+----------+
| 1 = null |
+----------+
|     null |
+----------+
1 row inset (0.00 sec)
mysql> select 1 != null;
+-----------+
| 1 != null |
+-----------+
|      null |
+-----------+
1 row inset (0.00 sec)
mysql> select null = null;
+-------------+
| null = null |
+-------------+
|        null |
+-------------+
1 row inset (0.00 sec)
mysql> select null != null;
+--------------+
| null != null |
+--------------+
|         null |
+--------------+
1 row inset (0.00 sec)

Entonces, cada NULLvalor es único, es decir, al contar la cantidad de valores únicos en la columna de índice, el NULLvalor debe considerarse como un valor independiente, por lo que la cantidad de valores únicos en la columna col es : 4 ( 1、2、NULL、NULLrespectivamente cuatro valores).

  • Algunas personas piensan que el valor NULL en realidad no significa nada en los negocios, y todos los valores NULL representan el mismo significado, por lo que el número de valores únicos en la columna col es: 3 (respectivamente 1, 2, NULL estos tres valores) .

  • Algunas personas piensan que NULL no tiene ningún sentido, por lo que no se pueden contar al contar la cantidad de valores únicos en la columna de índice, por lo que la cantidad de valores únicos en la columna col es: 2 (respectivamente 1 , 2 valor).

MySQL proporciona una innodb_stats_methodvariable de sistema con nombre, que es equivalente a cómo tratar los valores NULL al calcular el número de valores únicos de una columna de índice. El bote se lanza al usuario. Esta variable de sistema tiene tres valores candidatos:

  • nulls_equal: Considera que todos los valores NULL son iguales. Este valor también es el predeterminado para innodb_stats_method.

    Si hay demasiados valores NULL en cierta columna de índice, este método estadístico hará que el optimizador piense que el número promedio de repeticiones de un valor en cierta columna es demasiado alto, por lo que tiende a no usar el índice para acceder .

  • nulls_unequal: Considera que todos los valores NULL son desiguales.

    Si hay demasiados valores NULL en cierta columna de índice, este método estadístico hará que el optimizador piense que el número promedio de repeticiones de un valor en cierta columna es muy pequeño, por lo que tiende a usar el índice para acceder.

  • nulls_ignored: ignorar directamente el valor NULL.

De todos modos, esta culpa es del usuario. Después de seleccionar innodb_stats_methodel valor, incluso si el optimizador elige un plan de ejecución no óptimo, no tiene nada que ver con MySQL ~ Por supuesto, para nosotros como usuarios, es mejor no usar la columna de índice Almacenar valores NULL en es la solución correcta.

Resumir

InnoDB以表为单位来收集统计数据, estas estadísticas pueden ser 基于磁盘的永久性统计数据, o pueden ser 基于内存的非永久性统计数据.

  • innodb_stats_persistentControla si usar estadísticas persistentes o estadísticas no persistentes;

  • innodb_stats_persistent_sample_pagescontrola el número de páginas muestreadas para estadísticas permanentes
    ;

  • innodb_stats_transient_sample_pagesControla el número de páginas muestreadas para estadísticas no persistentes;

  • innodb_stats_auto_recalcControla si las estadísticas se recalculan automáticamente.

  • Para una tabla específica , podemos controlar los atributos de datos estadísticos relacionados especificando los valores de stats_persistent, al crear y modificar la tabla .stats_auto_recalcstats_sample_pages

  • innodb_stats_methodDetermina cómo tratar los valores NULL al contar la cantidad de valores únicos en una columna de índice

Hasta ahora, el estudio de hoy ha terminado, espero que te conviertas en un yo indestructible
~~~

No puedes conectar los puntos mirando hacia adelante; solo puedes conectarlos mirando hacia atrás. Así que tienes que confiar en que los puntos se conectarán de alguna manera en tu futuro. Tienes que confiar en algo: tu instinto, destino, vida, karma, lo que sea. Este enfoque nunca me ha defraudado y ha marcado una gran diferencia en mi vida.

Si mi contenido te es útil, por favor 点赞, 评论,, 收藏la creación no es fácil, el apoyo de todos es la motivación para que yo persevere

inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/liang921119/article/details/130806064
Recomendado
Clasificación