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


14

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


这个好问题+1,因为开发人员和DBA应该暂停并考虑如何编译和存储索引统计信息。
RolandoMySQLDBA 2011年

作为参考,请从mysql文档网站上:< dev.mysql.com/doc/refman/5.0/en/innodb-restrictions.html >> 通过对每个值进行八次随机潜水来ANALYZE TABLE确定索引基数(如SHOW INDEX输出的“基数”列中所示)索引树并相应地更新索引基数估计。由于这些只是估计,因此重复运行ANALYZE TABLE可能会产生不同的数字。这使得ANALYZE TABLE在InnoDB表上速度很快,但由于没有考虑所有行,因此不能100%准确。

Answers:


6

直接的答案是

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)

您可以使用以下命令从该表中进行选择

SELECT * FROM information_schema.statistics
WHERE table_schema='mydb' AND table_name='mytable';

或通过查看统计信息

从mydb.mytable显示索引;

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

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上进行了一些测试,并得出了同样的结论。


5

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

我不确定这个说法是否正确。我们已经大量读写innodb表,并且当mysql优化器做出错误选择时,查询的解释输出显示出错误的策略。Innodb表中的SHOW INDEXES也显示​​出它们的基数值变化很大。但是,在那些innodb表上运行ANALYZE命令可以修复解释计划,还可以消除基数的方差行为。我不知道Innodb表上的ANALYZE table命令是否一直有帮助,但是在我们的例子中,它确实有99%的时间有帮助。

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


我更新了答案,以突出显示InnoDB表上ANALYZE TABLE的无用性。
RolandoMySQLDBA 2011年

当您提到基数差异时,我同意您的回答。这就是我说基数近似值时所说的。
RolandoMySQLDBA 2011年

我还需要提及的是,当MySQL Query Optimizer有时会消除提示时,在查询中使用提示并非总是最好的选择。这是指向内部查询的链接,这些查询实际上会使数据在查询计划的某些
6

2

MyISAM的ANALYZE TABLE扫描整个表并重建统计信息,该统计信息保存在(我认为).MYI文件中。很少需要它。

InnoDB的ANALYZE TABLE 做一些事情-它会进行上述提到的潜水。问题在于它可能会有所帮助,可能会使情况变得更糟,或者(很可能)不会产生任何明显的改变(除了基数外)。

较新的版本承诺允许将8种非随机探测器更改为(1)更多随机性,(2)让您更改“ 8”(这有其优点和缺点!),以及(3)在重新启动时保存。

底线:InnoDB仍然没有做到“正确”。在需要时进行分析,但不要屏住呼吸。

更新资料

重新措辞... ANALYZE TABLE有一个临时的对InnoDB表的优化影响(可能有益,可能没有效果)。

“较新版本”:从5.6.6(2012)和MariaDB 10.1(2014)开始,统计数据得到了更好的处理,ANALYZE现在(1)不需要的频率越来越多,(2)更具永久性。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.