prefácio
Muitas vezes usamos alguns dados estatísticos quando falamos sobre o custo da consulta. Por exemplo, podemos show table status
ver os dados estatísticos sobre a tabela e show index
os 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.
Índice
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_persistent
para controlar de que maneira armazenar dados estatísticos. Antes do MySQL 5.6.6, innodb_stats_persistent
o 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_persistent
valor 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_persistent
Podemos 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 momento
stats_persistent=1
, indicava que queríamos armazenar permanentemente os dados estatísticos da tabela em磁盘上
- Naquele momento
stats_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_stats
Os dados estatísticos sobre a tabela são armazenados e cada registro corresponde aos dados estatísticos de uma tabela -
innodb_index_stats
Os 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_stats
que 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 demo8
correspondem mysql.innodb_table_stats
ao segundo registro. Os valores de vários itens estatísticos importantes são os seguintes:
n_rows
O valor é18758
, indicando quedemo8
há cerca de18758
1 registro na tabela, observe que este dado é um valor estimadoclustered_index_size
O valor de é97
, indicandodemo8
que o índice clusterizado da tabela ocupa97
páginas, e esse valor também é um valor estimadosum_of_other_index_sizes
O valor de é170
, indicando quedemo8
os demais índices da tabela ocupam170
um 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_rows
o 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_rows
a precisão deste valor depende do número de páginas amostradas durante as estatísticas. O MySQL preparou uma innodb_stats_persistent_sample_pages
variá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_pages
Se não especificarmos um atributo na instrução que cria a tabela , innodb_stats_persistent_sample_pages
o 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 InnoDB
o 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_indexes
tabela )
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 Heade
Na seção r da página raiz de cada índice, existem dois campos:
Page_btr_seg_leaf:
Segment Header
Indica a informação do segmento folha da árvore B+Page_btr_seg_top
Segment 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 Header
A estrutura é a seguinte:
A partir da estrutura correspondente , INODE Entry
pode-se descobrir que este segmento corresponde a todos os endereços de página dispersos e free
aos nós de base da lista encadeada.not_full
full
INODE Entry
A estrutura é a seguinte:
Conte diretamente o número de páginas espalhadas e, em seguida, List Length
leia 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:
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_size
de 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_size
e 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_stats
que 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_name
se refere ao nome do item estatístico, ou seja, innodb_index_stats
cada 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 demo8
estatí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_name
a coluna que indica as informações estatísticas de qual índice o registro pertence. Pelos resultados, podemos ver quePRIMARY
o índice (ou seja, a chave primária) ocupa 3 registros eidx_key_part
o índice ocupa 6 registros. -
Para
index_name
registros com a mesma coluna,stat_name
indica o nome do item estatístico para o índice estat_value
mostra o valor do índice no item estatístico,stat_description
que é 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_pfx01
Significa contarkey_part1
o número de valores únicos nesta única colunan_diff_pfx02
Indicakey_part1
quantos valores exclusivos são combinados nas duas colunas de estatísticas e key_part2n_diff_pfx03
Indica o número de valores exclusivos na combinação de estatísticaskey_part1
,key_part2
e essas três colunaskey_part3
n_diff_pfx04
Indica quantos valores únicos são combinados nas quatro colunas de estatísticaskey_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
size
coluna 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_stats
devem ser alterados de acordo? innodb_index_stats
Claro, 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:
-
ligar
innodb_stats_auto_recalc
A variável de sistema
innodb_stats_auto_recalc
determina 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 servidor10%
O o cálculo dos dados estatísticos será realizado novamente e a tabela de somas seráinnodb_table_stats
atualizadainnodb_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 exceda10%
, 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_recalc
especificar 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=0
Nesse 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_recalc
o valor da variável do sistema será usado como o valor do atributo por padrão.
-
Invoque
analyze table
instruções manualmente para atualizar estatísticasSe
innodb_stats_auto_recalc
o valor da variável do sistema for OFF, também podemos chamar manualmenteanalyze table
a instrução para recalcular os dados estatísticos. Por exemplo, podemos atualizardemo8
os dados estatísticos sobre a tabela assim:
mysql> analyze table demo8;
Deve-se observar que analyze table
a 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_stats
a 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 demo8
alterar 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_stats
os 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 status
o 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_persistent
definimos 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_persistent
do 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_pages
controlado 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 dive
acessar 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 NULL
valor é único, ou seja, ao contar o número de valores únicos na coluna do índice, o NULL
valor deve ser considerado como um valor independente, então o número de valores únicos na coluna col é : 4 ( 1、2、NULL、NULL
respectivamente 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_method
variá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_method
o 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_persistent
Controla se deve usar estatísticas persistentes ou não persistentes; -
innodb_stats_persistent_sample_pages
controla o número de páginas amostradas para estatísticas permanentes
; -
innodb_stats_transient_sample_pages
Controla o número de páginas amostradas para estatísticas não persistentes; -
innodb_stats_auto_recalc
Controla 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_method
Determina 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