Description:
Index cardinality has the same value for all indexes on a table when innodb_stats_persistent = ON no matter how many times you run ANALYZE TABLE. In my case I ran it twenty times. This seems to be a wrong behaviour as the index cardinality should be more accurate. Its causing serious performance issues when the wrong index is selected. The index cardinality is correct when innodb_stats_persistent = OFF.
How to repeat:
mysql> SHOW GLOBAL VARIABLES LIKE '%innodb_stats%';
+--------------------------------------+---------------+
| Variable_name | Value |
+--------------------------------------+---------------+
| innodb_stats_auto_recalc | ON |
| innodb_stats_method | nulls_ignored |
| innodb_stats_on_metadata | OFF |
| innodb_stats_persistent | ON |
| innodb_stats_persistent_sample_pages | 20 |
| innodb_stats_sample_pages | 32 |
| innodb_stats_transient_sample_pages | 32 |
+--------------------------------------+---------------+
7 rows in set (0.00 sec)
mysql> ANALYZE TABLE TestTbl;
+----------------------------+---------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+----------------------------+---------+----------+----------+
| testdb.TestTbl | analyze | status | OK |
+----------------------------+---------+----------+----------+
1 row in set (0.04 sec)
mysql> EXPLAIN SELECT name, id FROM TestTbl WHERE nameid = 130478989 AND name = 'LinksTbl2' AND id IN ('1538540', '1538306');
+----+-------------+---------------+------+--------------------+------------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------+------+--------------------+------------+---------+-------+------+--------------------------+
| 1 | SIMPLE | TestTbl | ref | PRIMARY,name | name | 102 | const | 2 | Using where; Using index |
+----+-------------+---------------+------+--------------------+------------+---------+-------+------+--------------------------+
1 row in set (0.00 sec)
mysql> SHOW INDEX FROM TestTbl;
+---------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| TestTbl | 0 | PRIMARY | 1 | nameid | A | 1585550 | NULL | NULL | | BTREE | | |
| TestTbl | 0 | PRIMARY | 2 | name | A | 1585550 | NULL | NULL | | BTREE | | |
| TestTbl | 0 | PRIMARY | 3 | id | A | 1585550 | NULL | NULL | | BTREE | | |
| TestTbl | 0 | PRIMARY | 4 | shopid | A | 1585550 | NULL | NULL | | BTREE | | |
| TestTbl | 1 | TestTbl_IX1 | 1 | shopid | A | 1585550 | NULL | NULL | | BTREE | | |
| TestTbl | 1 | TestTbl_IX1 | 2 | name | A | 1585550 | NULL | NULL | | BTREE | | |
| TestTbl | 1 | TestTbl_IX1 | 3 | id | A | 1585550 | NULL | NULL | | BTREE | | |
| TestTbl | 1 | TestTbl_IX1 | 4 | nameid | A | 1585550 | NULL | NULL | | BTREE | | |
| TestTbl | 1 | name | 1 | name | A | 1585550 | NULL | NULL | | BTREE | | |
| TestTbl | 1 | name | 2 | id | A | 1585550 | NULL | NULL | | BTREE | | |
+---------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
10 rows in set (0.01 sec)
mysql> ANALYZE TABLE TestTbl; +----------------------------+---------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+----------------------------+---------+----------+----------+
| testdb.TestTbl | analyze | status | OK |
+----------------------------+---------+----------+----------+
1 row in set (0.04 sec)
mysql> SHOW INDEX FROM TestTbl;
+---------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| TestTbl | 0 | PRIMARY | 1 | nameid | A | 1541903 | NULL | NULL | | BTREE | | |
| TestTbl | 0 | PRIMARY | 2 | name | A | 1541903 | NULL | NULL | | BTREE | | |
| TestTbl | 0 | PRIMARY | 3 | id | A | 1541903 | NULL | NULL | | BTREE | | |
| TestTbl | 0 | PRIMARY | 4 | shopid | A | 1541903 | NULL | NULL | | BTREE | | |
| TestTbl | 1 | TestTbl_IX1 | 1 | shopid | A | 1541903 | NULL | NULL | | BTREE | | |
| TestTbl | 1 | TestTbl_IX1 | 2 | name | A | 1541903 | NULL | NULL | | BTREE | | |
| TestTbl | 1 | TestTbl_IX1 | 3 | id | A | 1541903 | NULL | NULL | | BTREE | | |
| TestTbl | 1 | TestTbl_IX1 | 4 | nameid | A | 1541903 | NULL | NULL | | BTREE | | |
| TestTbl | 1 | name | 1 | name | A | 1541903 | NULL | NULL | | BTREE | | |
| TestTbl | 1 | name | 2 | id | A | 1541903 | NULL | NULL | | BTREE | | |
+---------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
10 rows in set (0.00 sec)
mysql> EXPLAIN SELECT name, id FROM TestTbl WHERE nameid = 130478989 AND name = 'John' AND id IN ('2323232', '143132');
+----+-------------+---------------+------+--------------------+------------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------+------+--------------------+------------+---------+-------+------+--------------------------+
| 1 | SIMPLE | TestTbl | ref | PRIMARY,name | name | 102 | const | 2 | Using where; Using index |
+----+-------------+---------------+------+--------------------+------------+---------+-------+------+--------------------------+
1 row in set (0.00 sec)
*******************************************************************
mysql> SET GLOBAL innodb_stats_persistent = OFF;
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW GLOBAL VARIABLES LIKE '%innodb_stats%';
+--------------------------------------+---------------+
| Variable_name | Value |
+--------------------------------------+---------------+
| innodb_stats_auto_recalc | ON |
| innodb_stats_method | nulls_ignored |
| innodb_stats_on_metadata | OFF |
| innodb_stats_persistent | OFF |
| innodb_stats_persistent_sample_pages | 20 |
| innodb_stats_sample_pages | 32 |
| innodb_stats_transient_sample_pages | 32 |
+--------------------------------------+---------------+
7 rows in set (0.00 sec)
mysql> ANALYZE TABLE TestTbl;
+----------------------------+---------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+----------------------------+---------+----------+----------+
| testdb.TestTbl | analyze | status | OK |
+----------------------------+---------+----------+----------+
1 row in set (0.04 sec)
mysql> EXPLAIN SELECT name, id FROM TestTbl WHERE nameid = 3434343 AND name = 'John' AND id IN ('2323232', '143132');
+----+-------------+---------------+-------+--------------------+---------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------+-------+--------------------+---------+---------+------+------+--------------------------+
| 1 | SIMPLE | TestTbl | range | PRIMARY,name | PRIMARY | 110 | NULL | 2 | Using where; Using index |
+----+-------------+---------------+-------+--------------------+---------+---------+------+------+--------------------------+
1 row in set (0.00 sec)
mysql> SHOW INDEX FROM TestTbl;
+---------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| TestTbl | 0 | PRIMARY | 1 | nameid | A | 3267 | NULL | NULL | | BTREE | | |
| TestTbl | 0 | PRIMARY | 2 | name | A | 11892 | NULL | NULL | | BTREE | | |
| TestTbl | 0 | PRIMARY | 3 | id | A | 1581673 | NULL | NULL | | BTREE | | |
| TestTbl | 0 | PRIMARY | 4 | shopid | A | 1581673 | NULL | NULL | | BTREE | | |
| TestTbl | 1 | TestTbl_IX1 | 1 | shopid | A | 1581673 | NULL | NULL | | BTREE | | |
| TestTbl | 1 | TestTbl_IX1 | 2 | name | A | 1581673 | NULL | NULL | | BTREE | | |
| TestTbl | 1 | TestTbl_IX1 | 3 | id | A | 790836 | NULL | NULL | | BTREE | | |
| TestTbl | 1 | TestTbl_IX1 | 4 | nameid | A | 1581673 | NULL | NULL | | BTREE | | |
| TestTbl | 1 | name | 1 | name | A | 18 | NULL | NULL | | BTREE | | |
| TestTbl | 1 | name | 2 | id | A | 1581673 | NULL | NULL | | BTREE | | |
+---------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
10 rows in set (0.00 sec)
Suggested fix:
Index cardinality should be more or less similar to when innodb_stats_persistent = ON.