MySQL 查询优化器从哪里读取索引统计信息?

ivo*_*ron 16 mysql index-statistics

我正在尝试确定 MySQL 优化器在估计(准备)查询的成本时从何处获取可用于表的索引列表。

Rol*_*DBA 8

对此的直接答案是

information_schema.statistics

mysql> desc information_schema.statistics;
+---------------+---------------+------+-----+---------+-------+
| Field         | Type          | Null | Key | Default | Extra |
+---------------+---------------+------+-----+---------+-------+
| TABLE_CATALOG | varchar(512)  | NO   |     |         |       |
| TABLE_SCHEMA  | varchar(64)   | NO   |     |         |       |
| TABLE_NAME    | varchar(64)   | NO   |     |         |       |
| NON_UNIQUE    | bigint(1)     | NO   |     | 0       |       |
| INDEX_SCHEMA  | varchar(64)   | NO   |     |         |       |
| INDEX_NAME    | varchar(64)   | NO   |     |         |       |
| SEQ_IN_INDEX  | bigint(2)     | NO   |     | 0       |       |
| COLUMN_NAME   | varchar(64)   | NO   |     |         |       |
| COLLATION     | varchar(1)    | YES  |     | NULL    |       |
| CARDINALITY   | bigint(21)    | YES  |     | NULL    |       |
| SUB_PART      | bigint(3)     | YES  |     | NULL    |       |
| PACKED        | varchar(10)   | YES  |     | NULL    |       |
| NULLABLE      | varchar(3)    | NO   |     |         |       |
| INDEX_TYPE    | varchar(16)   | NO   |     |         |       |
| COMMENT       | varchar(16)   | YES  |     | NULL    |       |
| INDEX_COMMENT | varchar(1024) | NO   |     |         |       |
+---------------+---------------+------+-----+---------+-------+
16 rows in set (0.01 sec)
Run Code Online (Sandbox Code Playgroud)

你可以从那个表中选择

SELECT * FROM information_schema.statistics
WHERE table_schema='mydb' AND table_name='mytable';
Run Code Online (Sandbox Code Playgroud)

或通过执行查看统计数据

显示来自 mydb.mytable 的索引;

请记住,此表在写入繁重的环境中并不总是准确的。您必须定期对所有频繁更新的 MyISAM 表运行ANALYZE TABLE。否则,依赖于 information_schema.statistics 的 MySQL 查询优化器有时会在为查询制定 EXPLAIN 计划时做出错误的选择。索引统计信息必须尽可能是最新的。

ANALYZE TABLE 对 InnoDB 表绝对没有影响。InnoDB 的所有索引统计信息都是通过深入 BTREE 页面按需计算的。因此,当您对 InnoDB 表运行 SHOW INDEXES FROM 时,显示的基数始终是近似值。

更新 2011-06-21 12:17 EDT

为了澄清分析表,让我改写一下。在 InnoDB 表上运行 ANALYZE TABLE 完全没用。即使您在 InnoDB 表上运行 ANALYZE TABLE,InnoDB 存储引擎也会一遍又一遍地深入索引以获取基数近似值,从而破坏您刚刚编译的统计信息。事实上,Percona 对 ANALYZE TABLE 进行了一些测试并得出了这个结论。


小智 6

Re:ANALYZE TABLE 对 InnoDB 表绝对没有影响。

我不确定这个说法是否属实。我们有大量的 innodb 表读写,当 mysql 优化器做出错误的选择时,查询的解释输出显示错误的策略。以及来自 Innodb 表的 SHOW INDEXES 显示它们的基数值有很大的差异。但是在这些 innodb 表上运行 ANALYZE 命令修复了解释计划并消除了基数的差异行为。我不知道 Innodb 表上的 ANALYZE table 命令是否一直有帮助,但在我们的例子中,它在大约 99% 的情况下确实有帮助。

通过在查询中包含“STRAIGHT_JOIN”,我们完全消除了 mysql 优化器的错误选择。这迫使 mysql 优化器不要做出错误的选择或任何选择,而只是遵循我们在查询中定义的 JOIN 条件。