由于错误的行估计,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倍)?谢谢。

+0

不,它无法使用索引,因为索引是无用的。扫描表格更有效。 –

InnoDB只保留表的近似行数。这是SHOW TABLE STATUS文档中解释说:

的行数。一些存储引擎(如MyISAM)存储确切的计数。对于其他存储引擎,如InnoDB,这个值是一个近似值,可能会与实际值相差40%到50%。

我不认为有什么办法可以让InnoDB保持准确的行数,但它不是如何工作。

+0

感谢您的回复。所以如果我们不把表拆分成小表,加快查询的唯一方法是'FORCE INDEX'?我担心的是,当数据分布发生变化或未来指数发生变化时,我们可能不会意识到'FORCE INDEX'的影响。手动选择索引太棘手。 – twds

+0

我还没有真正研究它,所以我不能回答这个问题。 – Barmar

+0

我的猜测是他们确定对查询优化的影响不够大,不足以要求他们解决保持精确计数的问题。 – Barmar

这种特殊的结构是难以优化:

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地址查找。