由于错误的行估计,MySQL Innodb无法使用索引
问题描述:
我有一个innodb表,表中的查询如下所示。由于错误的行估计,MySQL Innodb无法使用索引
SELECT *
FROM x
WHERE now() BETWEEN a AND b
我已经创建的复合指数(A,B)中,查询返回周围4K行,而行的表中的总数约为700K。
但是,当我得到EXPLAIN
的执行计划时,我发现查询没有使用预期的索引。因为估计的rows
大约是360k,比实际值大得多。
我知道就像很多帖子(如Why the rows returns by "explain" is not equal to count()?)已经解释过,EXPLAIN
只能粗略估计。但FORCE INDEX
解决方案非常棘手,未来可能会带来潜在的性能风险。
有没有什么办法可以让MySQL获得更准确的估计(目前的估计是90倍)?谢谢。
答
InnoDB只保留表的近似行数。这是SHOW TABLE STATUS
文档中解释说:
- 行
的行数。一些存储引擎(如MyISAM)存储确切的计数。对于其他存储引擎,如InnoDB,这个值是一个近似值,可能会与实际值相差40%到50%。
我不认为有什么办法可以让InnoDB保持准确的行数,但它不是如何工作。
答
这种特殊的结构是难以优化:
WHERE constant BETWEEN col1 AND col2
没有mysql指标可以设计,使其运行速度快。这些尝试包括:
INDEX(col1) -- will scan last half of table
INDEX(col2) -- will scan first half of table
INDEX(col1, col2) -- will scan last half of table
(无论它做更多的工作在B树取决于ICP,覆盖等,但在任何情况下,指数,大量的行必须被触摸)
一原因是无法改进,因为'半'中的'最后'一行可能实际上匹配。
如果(col1,col2)对不重叠,则可以通过在一行之后停止来提高性能。但MySQL不知道你是否有这种情况,所以它不能优化。 Here是非重叠的的方法有效的IP地址查找。
不,它无法使用索引,因为索引是无用的。扫描表格更有效。 –