MySQL QueryOptimizer 似乎随机使用索引(或不使用)
Posted
技术标签:
【中文标题】MySQL QueryOptimizer 似乎随机使用索引(或不使用)【英文标题】:MySQL QueryOptimizer seems to randomly use index (or not) 【发布时间】:2012-01-12 11:10:51 【问题描述】:我刚刚发现 mysql 使用 InnoDB 引擎的以下行为。有没有办法解释执行时间的显着差异?
第一个查询:
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。行,主键是时间戳。我还有一个关于(询问,时间戳)的索引和一个询问(这是多余的,仅用于测试目的)。为什么 MySQL 只在第二个查询中使用索引?
【问题讨论】:
您能否为每个查询添加解释,请使用SQL_NO_CACHE
为您的sql 查询计时:SELECT SQL_NO_CACHE ask FROM history_time WHERE ask> 1.5790 AND timestamp > 1207000800290
谢谢,我刚刚添加了解释 - 时间是在不使用缓存的情况下完成的
【参考方案1】:
你的答案在于:The Range Access Method for Multiple-Part Indexes
编辑:而且你最好检查一下:mysql range index。优化器有可能认为使用全扫描然后索引会更快。
【讨论】:
感谢您的帮助!有没有办法优化这个? 这取决于“询问”列的基数。如果您要查询特定时间并且您的定时数据小于询问基数,我建议您使用时间戳索引;如果不是,那将是对资源和空间的浪费。【参考方案2】:您的查询特别以时间戳作为主键,但也是通过您的评论(询问,时间戳)提出的索引。交换它...您希望在第一个位置具有较小的粒度...(时间戳,询问)...除非您要求非常具体的询问值或询问值范围。这样想吧。
如果您有 8300 万行并且您要查询在 X 和 Y 的时间范围内发生的事情,那么时间戳就是您的基础......为什么要考虑低于或高于相关范围的任何事情。现在,您添加“ask > someValue”,优化器可能会感到困惑。猜猜.. 是否有小于要价的值,或者基于提供的时间戳范围的值更少。如果您在 (timestamp,ask) 上有一个索引,它将能够更好地利用它。在提供的范围内,只给 ask > SomeValue。
如果优化器使用当前的 Ask 索引,它基本上会遍历所有大于提供的值的条目......然后在每个条目中,跳转到时间戳范围内的条目。
现在,交换您的标准。如果您正在寻找特定的“询问”值或范围,那么您当前的索引将非常好。它只会关注那个范围。
【讨论】:
(timestamp, ask)
索引有什么帮助?该查询在两列上都使用范围条件。
@ypercube,我想我是在看第一个带有中间值的条目,但是广泛的“失败”标准,不知道“询问”范围值的更多统计信息或它们是什么尝试实际获得结果是困难的。虽然使用时间戳的第一个位置,以及一个介于两者之间的,如果能够首先优化特定范围,那么只获取那些大于“询问”值的条目而不是所有可能的“询问”值从岁到现在。否则很难打电话。以上是关于MySQL QueryOptimizer 似乎随机使用索引(或不使用)的主要内容,如果未能解决你的问题,请参考以下文章
大爆料!Github上100%好评的Java多线程池面试题,确实牛!