我正在对查询性能问题进行故障排除.这是来自explain的预期查询计划:
mysql> explain select * from table1 where tdcol between '2010-04-13 00:00' and '2010-04-14 03:16';
+----+-------------+--------------------+-------+---------------+--------------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------------+-------+---------------+--------------+---------+------+---------+-------------+
| 1 | SIMPLE | table1 | range | tdcol | tdcol | 8 | NULL | 5437848 | Using where |
+----+-------------+--------------------+-------+---------------+--------------+---------+------+---------+-------------+
1 row in set (0.00 sec)
这是有道理的,因为使用了名为tdcol(KEY tdcol(tdcol))的索引,因此应从该查询中选择大约5M行.
但是,如果我仅查询一分钟的数据,我们将得到以下查询计划:
mysql> explain select * from table1 where tdcol between '2010-04-13 00:00' and '2010-04-14 03:17';
+----+-------------+--------------------+------+---------------+------+---------+------+-----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------------+------+---------------+------+---------+------+-----------+-------------+
| 1 | SIMPLE | table1 | ALL | tdcol | NULL | NULL | NULL | 381601300 | Using where |
+----+-------------+--------------------+------+---------------+------+---------+------+-----------+-------------+
1 row in set (0.00 sec)
优化器认为扫描会更好,但是要检查的行数却多了70倍,因此我很难相信表扫描会更好.
同样,“ USE KEY tdcol”语法不会更改查询计划.
在此先感谢您的帮助,我们非常乐意提供更多信息/答案问题.
解决方法:
500万个索引探针可能比读取所有3.5亿行(顺序磁盘读取)更昂贵(大量随机磁盘读取,可能更复杂的同步).
这种情况可能是一个例外,因为时间戳的顺序大概与表中插入的顺序大致匹配.但是,除非tdcol上的索引是“聚集的”索引(意味着数据库确保基础表中的顺序与tdcol中的顺序匹配),否则优化程序不太可能知道这一点.
在没有该顺序相关信息的情况下,正确地假设您想要的500万行大致均匀地分布在3.5亿行中,因此索引方法将涉及读取页面中的大部分或几乎所有页面.无论如何,底层行(在这种情况下,扫描将比索引方法便宜得多,直接读取和顺序读取的次数要少于随机读取的次数).