我正在解决查询性能问题。这是解释中的预期查询计划:
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'语法不会更改查询计划。
提前感谢您的帮助,我非常乐意提供更多信息/回答问题。
答案 0 :(得分:3)
500万个索引探测器可能比读取所有3.5亿行(顺序磁盘读取)更昂贵(大量随机磁盘读取,可能更复杂的同步)。
这种情况可能是一个例外,因为大概时间戳的顺序大致与插入表中的顺序相匹配。但是,除非tdcol
上的索引是“聚簇”索引(意味着数据库确保基础表中的顺序与tdcol中的顺序匹配),否则优化程序不太可能知道这一点。
如果没有订单关联信息,那么假设您想要的500万行大致均匀地分布在3.5亿行中是正确的,因此索引方法将涉及读取大部分或几乎全部的无论如何,在底层行中的页面(在这种情况下,扫描将比索引方法便宜得多,完全更少读取和顺序而不是随机读取)。
答案 1 :(得分:0)
MySQL的查询生成器在确定如何使用索引时有一个截止点。正如您已经正确识别的那样,MySQL已经确定表扫描将比使用索引更快,并且不会被它的决定所阻止。具有讽刺意味的是,当关键范围匹配超过表的三分之一时,它可能是正确的。那么为什么在这种情况下?
我没有答案,但我怀疑MySQL没有足够的内存来探索索引。我会查看服务器内存设置,特别是Innodb内存池和一些其他密钥存储池。
答案 2 :(得分:0)
您的数据分布情况如何?尝试在其上运行min(),avg(),max()以查看它的位置。 1分钟可能会对该范围中包含的信息量产生影响。
它也可以只是InnoDB的背景设置有几个因素,如页面大小,和像staticsan说的内存。您可能希望明确定义B + Tree索引。
答案 3 :(得分:0)
“所以我很难相信桌面扫描更好。”
真。 你很难相信它。但优化器似乎没有。
我不会说你的“正确”而你的优化者是“正确的”。但优化者会像他们那样做,总而言之,他们的“智力”能力仍然被认为是相当有限的。
那就是说,您的数据库统计信息是否显示MAX值(对于此列)恰好等于“多一秒”值?
如果是这样,那么优化器可能已经断定所有行都满足上限,并且可能已经决定采用不同的方式,与必须得出结论的情况相比,“哦,肯定有一些行赢了” t也满足上限,所以我将使用索引来保证安全“。