我正在排除查询性能问题。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)
)的索引,应该从该查询中选择大约500行。但是,如果我只查询一分钟的数据,我们将得到以下查询计划:
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亿行中是正确的,因此索引方法将涉及读取基本行中的大部分或几乎所有页面(在其中如果扫描要比索引方法便宜得多,那么直接和连续的读取要比随机读取少得多。
关于mysql - 为什么带有InnoDB的MySQL在 key 存在时进行表扫描并选择检查70多行?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2642108/