Este artigo leva você a entender como as estatísticas InnoDB do MySQL são coletadas

prefácio

Muitas vezes usamos alguns dados estatísticos quando falamos sobre o custo da consulta. Por exemplo, podemos show table statusver os dados estatísticos sobre a tabela e show indexos dados estatísticos sobre o índice. Então, como esses dados estatísticos vêm? Como são coletados? Este capítulo se concentrará nas InnoDB存储引擎estratégias de coleta de dados estatísticos.Após a leitura deste capítulo, você entenderá porque sempre se diz que InnoDB的统计信息é uma estimativa imprecisa.

1. Dois métodos diferentes de armazenamento de dados estatísticos

O InnoDB fornece duas maneiras de armazenar dados estatísticos:

  • 永久性的统计数据: Este tipo de dados estatísticos é armazenado no disco, ou seja, os dados estatísticos ainda estão lá depois que o servidor é reiniciado

  • 非永久性的统计数据: Este tipo de dados estatísticos é armazenado na memória. Quando o servidor for desligado, esses dados estatísticos serão apagados. Depois que o servidor for reiniciado, esses dados estatísticos serão coletados novamente em alguns cenários apropriados.

O MySQL nos fornece variáveis ​​de sistema innodb_stats_persistentpara controlar de que maneira armazenar dados estatísticos. Antes do MySQL 5.6.6, innodb_stats_persistento valor padrão de é OFF, o que significa que as estatísticas do InnoDB são armazenadas na memória por padrão. Em versões posteriores, o innodb_stats_persistentvalor padrão é ON, ou seja, as estatísticas são armazenadas em disco por padrão.

No entanto, o InnoDB coleta e armazena estatísticas em unidades de tabelas por padrão, ou seja, podemos armazenar as estatísticas de algumas tabelas (e as estatísticas de índice da tabela) em disco e armazenar as estatísticas de outras tabelas na memória. Como você fez isso? stats_persistentPodemos especificar o atributo para indicar o método de armazenamento de dados estatísticos da tabela ao criar e modificar a tabela :

create table 表名 (...) engine=innodb, stats_persistent = (1|0);
alter table 表名 engine=innodb, stats_persistent = (1|0);
  • Naquele momentostats_persistent=1 , indicava que queríamos armazenar permanentemente os dados estatísticos da tabela em磁盘上
  • Naquele momentostats_persistent=0 , indicava que queríamos armazenar temporariamente os dados estatísticos da tabela em内存中

Deve-se notar que se criarmos um atributo ao criar uma tabela 未指定stats_persistent, o valor padrão 采用系统变量innodb_stats_persistenté usado como o valor do 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. Estatísticas persistentes baseadas em disco

Quando optamos por armazenar os dados estatísticos de uma tabela e o índice da tabela no disco, na verdade armazenamos esses dados estatísticos em duas tabelas:

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 você pode ver, essas duas tabelas estão localizadas no banco de dados do sistema mysql, onde:

  • innodb_table_statsOs dados estatísticos sobre a tabela são armazenados e cada registro corresponde aos dados estatísticos de uma tabela

  • innodb_index_statsOs dados estatísticos sobre o índice são armazenados e cada registro corresponde aos dados estatísticos de um item estatístico de um índice

O que vamos fazer a seguir é dar uma olhada no que há nessas duas tabelas e como os dados nas tabelas são gerados

2.1 innodb_table_stats

Aqui está uma visão direta do innodb_table_statsque cada coluna na tabela faz:

nome do campo descrever
nome do banco de dados Nome do banco de dados
Nome da tabela Nome da tabela
última atualização Este registro foi atualizado pela última vez
n_rows o número de registros na tabela
clustered_index_size Número de páginas ocupadas pelo índice clusterizado da tabela
sum_of_other_index_sizes O número de páginas ocupadas pelos outros índices da tabela

Observe que a chave primária desta tabela é (database_name,table_name), ou seja innodb_table_stats表的每条记录代表着一个表的统计信息. Vejamos diretamente o conteúdo desta tabela:

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)

Você pode ver que as informações estatísticas das tabelas que conhecemos demo8correspondem mysql.innodb_table_statsao segundo registro. Os valores de vários itens estatísticos importantes são os seguintes:

  • n_rowsO valor é 18758, indicando que demo8há cerca de 187581 registro na tabela, observe que este dado é um valor estimado
  • clustered_index_sizeO valor de é 97, indicando demo8que o índice clusterizado da tabela ocupa 97páginas, e esse valor também é um valor estimado
  • sum_of_other_index_sizesO valor de é 170, indicando que demo8os demais índices da tabela ocupam 170um total de páginas, sendo esse valor também um valor estimado

2.1.1 Coleta de estatísticas n_rows

Por que foi enfatizado que n_rowso valor desse item estatístico é um valor estimado? Agora, para revelar a resposta. O InnoDB conta quantos registros existem em uma tabela como esta:

  • Selecione cada página de autonó folha de acordo com um determinado algoritmo (não puramente aleatório), calcule o número de registros de valor de chave primária em cada página e, em seguida, calcule o número médio de registros de valor de chave primária em uma página multiplicado pelo número de todos auto-nós de folha é o valor n_rows da tabela

    小提示:
    O processo de cálculo real é um pouco mais complicado do que isso, mas é mais ou menos isso que significa

Pode-se ver que n_rowsa precisão deste valor depende do número de páginas amostradas durante as estatísticas. O MySQL preparou uma innodb_stats_persistent_sample_pagesvariável de sistema nomeada para controlarmos o número de páginas amostradas ao calcular estatísticas ao usar estatísticas permanentes.

  • Quanto maior o valor definido, mais preciso é o valor estatístico n_rows, mas as estatísticas levam mais tempo
  • Quanto menor for o valor definido, mais impreciso será o valor estatístico n_rows, mas as estatísticas levarão menos tempo.

Portanto, no uso real, precisamos pesar os prós e os contras. O valor padrão dessa variável de sistema é 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 dissemos antes, mas eu também podemos definir individualmente o número de páginas de amostragem de uma determinada tabela. O método de configuração é especificar o método de armazenamento de dados estatísticos da tabela nnoDB默认是以表为单位来收集和存储统计数据的, especificando o atributo ao criar ou modificar a tabela:stats_sample_pages

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

stats_sample_pagesSe não especificarmos um atributo na instrução que cria a tabela , innodb_stats_persistent_sample_pageso valor da variável do sistema será usado como o valor do atributo por padrão.

2.1.2 Coleção de itens estatísticos clustered_index_size e sum_of_other_index_sizes

Contar esses dois dados requer muito InnoDB表空间conhecimento que aprendemos antes. Se você não leu esse capítulo, não deve ler o processo de cálculo abaixo (você não pode entendê-lo); se você leu, então Todos descobrirá que InnoDBo conhecimento dos espaços de tabela é realmente útil.

Este artigo leva você a entender o espaço de tabela InnoDB do MySQL [ through train ]

O processo de coleta desses dois itens estatísticos é o seguinte:

Etapa 1: encontre o local da página raiz correspondente a cada índice da tabela no dicionário de dados (as informações da página raiz correspondentes a cada índice são armazenadas na sys_indexestabela )

Etapa 2:Header encontre o segmento de nó folha correspondente e o segmento de nó não folha na página da página raiz Segment Header. Page HeadeNa seção r da página raiz de cada índice, existem dois campos:

  • Page_btr_seg_leaf:Segment HeaderIndica a informação do segmento folha da árvore B+
  • Page_btr_seg_topSegment Header: Indica a informação do segmento não folha da árvore B+

Etapa 3:Segment Header encontre a estrutura correspondente aos dois segmentos do segmento do nó folha e do segmento do nó não folha INODE Entry.

Segment HeaderA estrutura é a seguinte:

insira a descrição da imagem aqui
A partir da estrutura correspondente , INODE Entrypode-se descobrir que este segmento corresponde a todos os endereços de página dispersos e freeaos nós de base da lista encadeada.not_fullfull

INODE EntryA estrutura é a seguinte:

insira a descrição da imagem aqui
Conte diretamente o número de páginas espalhadas e, em seguida, List Lengthleia o tamanho da área ocupada pelo segmento nos campos das três listas vinculadas. Cada área ocupa 64 páginas, portanto, as páginas ocupadas pelo segmento inteiro podem ser contadas.

Este é um diagrama esquemático do nó base da lista encadeada:

insira a descrição da imagem aqui
Passo 4: Calcule o número de páginas ocupadas pelo segmento de nó folha e segmento de nó não folha do índice clusterizado, respectivamente, e sua soma é o valor de , e calcule o número clustered_index_sizede páginas ocupadas pelos outros índices de acordo com a mesma rotina , e adicione-os até sum_of_other_index_sizes o valor de

Aqui está uma questão para a qual todos devem estar atentos. Dizemos que quando houver muitos dados em um segmento (mais de 32 páginas), o espaço será aplicado em unidades de distritos. O problema aqui é que algumas páginas em o espaço de aplicação em unidades de distritos não pode ser usado, mas são contabilizados nas estatísticas clustered_index_sizee no tempo, portanto, o número de páginas ocupadas pelo índice agrupado e outros índices pode ser maior que esses dois valores.sum_of_other_index_sizes

2.2 innodb_index_stats

Dê uma olhada diretamente no innodb_index_statsque cada coluna nesta tabela faz:

nome do campo descrever
nome do banco de dados Nome do banco de dados
Nome da tabela Nome da tabela
index_name nome do índice
última atualização Este registro foi atualizado pela última vez
stat_name O nome do item estatístico
valor_estatístico O valor do item estatístico correspondente
sample_size O número de páginas amostradas para geração de estatísticas
stat_description Descrição do item estatístico correspondente

Observe que a chave primária desta tabela é (database_name,table_name,index_name,stat_name), onde stat_namese refere ao nome do item estatístico, ou seja, innodb_index_statscada registro da tabela representa um item estatístico de um índice. Talvez isso o deixe um pouco confuso sobre a que se refere esse item estatístico. Não se preocupe, vamos dar uma olhada nas demo8estatísticas do índice sobre a tabela:

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 é um pouco demais, a maneira correta de visualizar este resultado é esta:

  • Primeiro, observe index_namea coluna que indica as informações estatísticas de qual índice o registro pertence. Pelos resultados, podemos ver que PRIMARYo índice (ou seja, a chave primária) ocupa 3 registros e idx_key_parto índice ocupa 6 registros.

  • Para index_nameregistros com a mesma coluna, stat_nameindica o nome do item estatístico para o índice e stat_valuemostra o valor do índice no item estatístico, stat_descriptionque é usado para descrever o significado do item estatístico. Vamos dar uma olhada nas estatísticas de um índice:

    • n_leaf_pages: Indica quantas páginas estão ocupadas pelos nós folha do índice

    • size: Indica quantas páginas o índice ocupa no total

    • n_diff_pfxNN: Indica quantos valores únicos a coluna de índice correspondente possui. O NN parece um pouco estranho, o que você quer dizer? Na verdade, NN pode ser substituído por números como 01, 02, 03…. Por exemplo, para idx_key_part:

      • n_diff_pfx01Significa contar key_part1o número de valores únicos nesta única coluna
      • n_diff_pfx02Indica key_part1quantos valores exclusivos são combinados nas duas colunas de estatísticas e key_part2
      • n_diff_pfx03Indica o número de valores exclusivos na combinação de estatísticas key_part1, key_part2e essas três colunaskey_part3
      • n_diff_pfx04Indica quantos valores únicos são combinados nas quatro colunas de estatísticas key_part1, key_part2, key_part3,id

小提示:
Deve-se observar aqui que, para índices secundários comuns, não há garantia de que os valores da coluna do índice sejam exclusivos. Por exemplo, para idx_key1, a coluna key1 pode ter muitos registros com valores duplicados. Neste momento, apenas adicionando o valor da chave primária à coluna do índice, os registros do índice secundário com o mesmo valor das duas colunas do índice podem ser distinguidos. Não existe esse problema para a chave primária e o índice secundário exclusivo. Eles podem garantir que os valores da coluna do índice não sejam repetidos, portanto, não há necessidade de contar o número de valores exclusivos adicionados ao valor da chave primária após a coluna do índice. Por exemplo, idx_key1 acima possui dois itens estatísticos, n_diff_pfx01 e n_diff_pfx02, enquanto idx_key2 possui apenas um item estatístico, n_diff_pfx01.

  • Ao calcular quantos valores exclusivos estão contidos em algumas colunas de índice, essas páginas do nó folha precisam ser amostradas e a sizecoluna indica o número de páginas amostradas

小提示:
Para um índice conjunto com várias colunas, o número de páginas amostradas é: innodb_stats_persistent_sample_pages × 索引列的个数. Quando o número de páginas a serem amostradas é maior que o número de nós folha no índice, uma varredura completa da tabela é usada diretamente para contar o número de valores exclusivos na coluna do índice. Assim, você pode ver nos resultados da consulta que os valores da coluna de tamanho correspondentes a diferentes índices podem ser diferentes.

2.3 Estatísticas atualizadas regularmente

À medida que continuamos a adicionar, excluir e modificar a tabela, os dados da tabela também mudam. Os dados estatísticos da tabela innodb_table_statsdevem ser alterados de acordo? innodb_index_statsClaro, isso vai mudar.Se permanecer inalterado, o custo calculado pelo otimizador de consulta do MySQL ficará muito para trás. O MySQL fornece as duas maneiras a seguir para atualizar as estatísticas:

  • ligarinnodb_stats_auto_recalc

    A variável de sistema innodb_stats_auto_recalcdetermina se o servidor recalcula as estatísticas automaticamente, seu valor padrão é ON, ou seja, a função está habilitada por padrão. Cada tabela mantém uma variável, que registra o número de registros adicionados, excluídos ou modificados. Se o número de registros alterados exceder o tamanho da tabela e a função de recalcular automaticamente os dados estatísticos estiver ativada, o servidor 10%O o cálculo dos dados estatísticos será realizado novamente e a tabela de somas será innodb_table_statsatualizada innodb_index_stats. No entanto, o processo de recalcular automaticamente os dados estatísticos ocorre de forma assíncrona, ou seja, mesmo que o número de registros alterados na tabela exceda 10%, o recalculo automático dos dados estatísticos não acontecerá imediatamente, podendo o cálculo demorar alguns 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)

Mais uma vez, o InnoDB coleta e armazena dados estatísticos em unidades de tabelas por padrão. Também podemos definir o atributo de recalcular estatísticas automaticamente para uma tabela separadamente. O método de configuração é especificar o atributo ao criar ou modificar a tabela . para stats_auto_recalcespecificar como as estatísticas da tabela são armazenadas:

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

Nesse momentostats_auto_recalc=1 , indicando que queremos que a tabela recalcule automaticamente as estatísticas stats_persistent=0Nesse momento , indicando que não queremos que a tabela recalcule automaticamente as estatísticas

Se não especificarmos um atributo ao criar uma tabela stats_auto_recalc, innodb_stats_auto_recalco valor da variável do sistema será usado como o valor do atributo por padrão.

  • Invoque analyze tableinstruções manualmente para atualizar estatísticas

    Se innodb_stats_auto_recalco valor da variável do sistema for OFF, também podemos chamar manualmente analyze tablea instrução para recalcular os dados estatísticos. Por exemplo, podemos atualizar demo8os dados estatísticos sobre a tabela assim:

mysql> analyze table demo8;

Deve-se observar que analyze tablea instrução recalculará imediatamente os dados estatísticos, ou seja, o processo é síncrono. Este processo pode ser particularmente lento quando houver muitos índices na tabela ou houver muitas páginas de amostra. Por favor, não execute a instrução apenas por nada analyze table. Executa novamente quando não está muito ocupado.

2.4 Atualize manualmente as tabelas innodb_table_stats e innodb_index_stats

Na verdade innodb_table_stats, innodb_index_statsa tabela é equivalente a uma tabela comum, e podemos adicionar, excluir, modificar e consultá-los. Isso também significa que podemos atualizar manualmente as estatísticas de uma tabela ou índice. Por exemplo, se quisermos demo8alterar as estatísticas da tabela sobre o número de linhas, podemos fazer isso:

Etapa 1: atualizar a tabela demo8

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

Etapa 2: deixe o otimizador de consulta do MySQL recarregar nossos dados alterados

Após a atualização, innodb_table_statsos dados de uma tabela são simplesmente modificados, e o otimizador de consultas do MySQL precisa recarregar os dados alterados, basta executar o seguinte comando:

flush table demo8;

Posteriormente, quando utilizamos show table statuso comando para visualizar os dados estatísticos da tabela, podemos observar que a linha Rows mudou para 1.

3. Estatísticas não persistentes baseadas na memória

Quando innodb_stats_persistentdefinimos o valor da variável de sistema como OFF, os dados estatísticos da tabela criada posteriormente são não permanentes por padrão, ou definimos diretamente o valor stats_persistentdo atributo como 0 ao criar ou modificar a tabela, então os dados estatísticos de os dados da tabela são impermanentes.

Ao contrário das estatísticas persistentes, o número de páginas amostradas por estatísticas não persistentes é innodb_stats_transient_sample_pagescontrolado pelo valor padrão de 8 para esta variável de sistema. Além disso, como os dados estatísticos não permanentes são atualizados com frequência, o otimizador de consulta do MySQL depende de dados estatísticos que mudam frequentemente ao calcular os custos da consulta e gera planos de execução que mudam com frequência, o que pode deixar todos um pouco confusos. No entanto, as versões recentes do MySQL não usam esse tipo de estatística não permanente baseada em memória, então não sabemos muito sobre isso.

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)

Em quarto lugar, o uso de innodb_stats_method

Sabemos que a estatística do número de valores únicos na coluna do índice é muito importante para o otimizador de consultas do MySQL, pois pode ser usado para calcular quantas linhas se repetem em um valor médio na coluna do índice. principais cenários de aplicação:

  • Existem muitos intervalos de ponto único na consulta de tabela única, por exemplo: Quando há muitos parâmetros em IN, index diveé muito intensivo em desempenho acessar diretamente o índice da árvore B+ para contar o número de registros correspondentes a cada um intervalo de ponto, portanto, confie diretamente em quantas linhas são repetidas para um valor médio nos dados estatísticos para calcular o número de registros correspondentes ao intervalo de ponto único.
    select * from tbl_name where key in ('xx1', 'xx2', ..., 'xxn');

  • Ao conectar consultas, se houver uma condição de junção de correspondência de equivalência envolvendo duas tabelas e a coluna na tabela acionada correspondente à condição de junção tiver um índice, você poderá usar o método de acesso para consultar a tabela acionada, por exemplo ref:

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

    Antes de realmente executar a consulta na tabela t2, o valor de t1.comumn é incerto, portanto não podemos index diveacessar diretamente o índice da árvore B+ para contar o número de registros correspondentes a cada intervalo de ponto único, portanto, podemos confiar apenas em Quantos vezes é o valor médio nos dados estatísticos repetidos para calcular o número de registros correspondentes ao intervalo de ponto único.

Ao contar o número de valores únicos em uma coluna de índice, existe um problema incômodo que é como lidar com valores NULL na coluna de índice. Por exemplo, o conteúdo de uma coluna de índice é o seguinte:

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

Neste momento, calcular o número de valores únicos na coluna col tem as seguintes diferenças:

  • Algumas pessoas acham que o valor NULL representa um valor indeterminado, então o MySQL acha que qualquer expressão que compare com o valor NULL resulta em NULL, é isso:
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)

Então cada NULLvalor é único, ou seja, ao contar o número de valores únicos na coluna do índice, o NULLvalor deve ser considerado como um valor independente, então o número de valores únicos na coluna col é : 4 ( 1、2、NULL、NULLrespectivamente quatro valores).

  • Algumas pessoas pensam que o valor NULL na verdade não significa nada nos negócios, e todos os valores NULL representam o mesmo significado, então o número de valores únicos na coluna col é: 3 (respectivamente 1, 2, NULL esses três valores) .

  • Algumas pessoas pensam que NULL é completamente sem sentido, então eles não podem ser contados ao contar o número de valores únicos na coluna do índice, então o número de valores únicos na coluna col é: 2 (respectivamente 1 , 2 valor).

O MySQL fornece uma innodb_stats_methodvariável de sistema nomeada, que é equivalente a como tratar valores NULL ao calcular o número de valores únicos de uma coluna de índice. O pote é lançado para o usuário. Essa variável de sistema possui três valores candidatos:

  • nulls_equal: Considera todos os valores NULL iguais. Esse valor também é o padrão para innodb_stats_method.

    Se houver muitos valores NULL em uma determinada coluna de índice, esse método estatístico fará com que o otimizador pense que o número médio de repetições de um valor em determinada coluna é muito alto, portanto, ele tende a não usar o índice para acesso .

  • nulls_unequal: Considera todos os valores NULL desiguais.

    Se houver muitos valores NULL em uma determinada coluna de índice, esse método estatístico fará com que o otimizador pense que o número médio de repetições de um valor em determinada coluna é muito pequeno, então ele tende a usar o índice para acesso.

  • nulls_ignored: ignore diretamente o valor NULL.

De qualquer forma, a culpa é do usuário. Depois de selecionar innodb_stats_methodo valor, mesmo que o otimizador escolha um plano de execução não ideal, não tem nada a ver com o MySQL~ Claro, para nós usuários, é melhor não usar a coluna de índice Armazenar valores NULL é a solução correta.

Resumir

InnoDB以表为单位来收集统计数据, essas estatísticas podem ser 基于磁盘的永久性统计数据, ou podem ser 基于内存的非永久性统计数据.

  • innodb_stats_persistentControla se deve usar estatísticas persistentes ou não persistentes;

  • innodb_stats_persistent_sample_pagescontrola o número de páginas amostradas para estatísticas permanentes
    ;

  • innodb_stats_transient_sample_pagesControla o número de páginas amostradas para estatísticas não persistentes;

  • innodb_stats_auto_recalcControla se as estatísticas são recalculadas automaticamente.

  • Para uma tabela específica, podemos controlar os atributos de dados estatísticos relacionados especificando os valores de stats_persistent, stats_auto_recalc, ao criar e modificar a tabela .stats_sample_pages

  • innodb_stats_methodDetermina como tratar valores NULL ao contar o número de valores únicos em uma coluna de índice

Até agora, o estudo de hoje acabou, espero que você se torne um eu indestrutível
~~~

Você não pode ligar os pontos olhando para frente; você só pode conectá-los olhando para trás. Portanto, você precisa confiar que os pontos de alguma forma se conectarão em seu futuro. Você precisa confiar em algo - seu instinto, destino, vida, karma, seja o que for. Essa abordagem nunca me decepcionou e fez toda a diferença na minha vida

Se meu conteúdo for útil para você, por favor 点赞, criar não é fácil, o apoio de todos é a 评论motivação 收藏para eu perseverar

insira a descrição da imagem aqui

Acho que você gosta

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