Eu tenho a seguinte tabela:
mysql> select count(*) from employees;
+----------+
| count(*) |
+----------+
| 10000 |
+----------+
1 row in set (0.03 sec)
Eu faço um EXPLAIN
: mysql> explique selecione last_name da ordem dos funcionários por last_name;
+----+-------------+-----------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+------+----------------+
| 1 | SIMPLE | employees | ALL | NULL | NULL | NULL | NULL | 9894 | Using filesort |
+----+-------------+-----------+------+---------------+------+---------+------+------+----------------+
1 row in set (0.00 sec)
As linhas são 9894. Eu esperava 10000.
Eu faço:
mysql> analyze table employees;
+-------------------------------------+---------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+-------------------------------------+---------+----------+----------+
| sql_dummy.employees | analyze | status | OK |
+-------------------------------------+---------+----------+----------+
1 row in set (0.04 sec)
e execute novamente EXPLAIN
:
mysql> explique selecionar last_name da ordem dos funcionários por last_name;
+----+-------------+-----------+------+---------------+------+---------+------+-------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+-------+----------------+
| 1 | SIMPLE | employees | ALL | NULL | NULL | NULL | NULL | 10031 | Using filesort |
+----+-------------+-----------+------+---------------+------+---------+------+-------+----------------+
1 row in set (0.01 sec)
As linhas agora são 10031.
Alguém sabe por que as linhas nunca são 10000? Também notei isso em outros casos.
Você pode achar isso surpreendente, mas esse é o comportamento do InnoDB.
O mecanismo de armazenamento InnoDB faz a aproximação de cardinalidade percorrendo alguns níveis abaixo dos nós BTREE não folha e faz uma estimativa fundamentada.
Escrevi sobre isso há muito tempo com base em mysqlperformanceblog.com
Jun 21, 2011
: De onde o MySQL Query Optimizer lê as estatísticas do índice?Aug 03, 2011
: Quando devo reconstruir índices?Feb 23, 2013
: Como o mysql lida com consultas que tocam nas tabelas myisam e innodb?Talvez você possa tentar desabilitar esse comportamento executando isto:
Definir innodb_stats_on_metadata deve estabilizar a cardinalidade aproximada e você deve obter a mesma cardinalidade repetidas vezes.