MySQL QueryOptimizer似乎随机使用索引(或不)

时间:2012-01-12 11:10:52

标签: mysql indexing innodb

我刚刚使用InnoDB引擎发现了MySQL的以下行为。有没有办法解释执行时间的显着差异?

第一次查询:

   SELECT ask FROM history_time  WHERE ask> 1.5790 AND timestamp BETWEEN 1207000800290 AND        1207690900290 

执行时间:0.715秒

   EXPLAIN: '1', 'SIMPLE', 'history_time', 'range', 'PRIMARY,timestamp,ask,ask_2', 'PRIMARY', '8', NULL, '3278190','Using where'

第二次查询:

SELECT ask FROM history_time  WHERE ask> 1.5790 AND timestamp > 1207000800290

执行时间:0.002秒

EXPLAIN: '1', 'SIMPLE', 'history_time', 'range', 'PRIMARY,timestamp,ask,ask_2', 'ask', '4', NULL, '5850604', 'Using where; Using index'

第三次质询:

SELECT ask FROM history_time  WHERE ask> 1.5790 AND timestamp < 1207690900290

执行时间:0.651秒

EXPLAIN: '1', 'SIMPLE', 'history_time', 'range', 'PRIMARY,timestamp,ask,ask_2', 'PRIMARY', '8', NULL, '3278190', 'Using where'

EXPLAIN告诉我,只有第二个查询使用索引。我的桌子包含83 Mio.行,主键是时间戳。我还有一个索引(ask,timestamp)和一个关于ask(这是多余的,仅用于测试目的)。为什么MySQL只在第二个查询中使用索引?

2 个答案:

答案 0 :(得分:1)

你的答案在于:The Range Access Method for Multiple-Part Indexes

编辑:你还最好检查一下:mysql range index。优化器有可能决定使用全扫描然后索引会更快。

答案 1 :(得分:0)

您的查询专门按时间戳作为主键,但也可以通过您的评论(ask,timestamp)查询。交换它...你想要在第一个位置使用较小的粒度...(时间戳,询问)......除非你要求一个非常具体的询问值或询问值范围。可以这样想。

如果你有8300万行并且你要求在X和Y的时间范围内发生的事情,时间戳是你的基础......为什么要考虑任何低于或大于有问题的范围。现在,您添加“ask&gt; someValue”,优化器可能会感到困惑。猜猜..是否有更少的值大于ask值,或者更少的值基于提供的时间戳范围。如果你有一个索引(时间戳,问),它将能够更好地利用它。在提供的范围内,只提出问题&gt; someValue中。

如果优化器使用当前的Ask索引,它基本上会遍历所有大于提供值的条目......然后在每个条目中跳转到时间戳范围内的那些条目。

现在,交换您的标准。如果您正在寻找特定的“询问”值或范围,那么您当前的指数将非常好。它只关注那个范围。