查询速度受限并且有百万条记录

6

您好,我有一个700万条记录的数据库表用于测试查询速度。

我测试了两个查询,它们是相同的查询,只是限制参数不同:

查询1 -

SELECT    * 
FROM      table 
LIMIT     20, 50;

查询2 -

SELECT    * 
FROM      table 
LIMIT     6000000, 6000030;

查询执行时间如下:

  1. 查询1 - 0.006秒
  2. 查询2 - 5.500秒

在这两个查询中,我获取的记录数量相同,但在第二种情况下需要更长的时间。有人能解释一下背后的原因吗?


我快要准备好进行新的索引测试了,让我们看看会返回什么;) 我会告诉你的。 - itsme
测试了索引键:查询1 0.08秒,查询2 4.50秒...有一点改善但情况仍然相同:P - itsme
1
哇,好发现。现在我必须真正知道是什么导致了这些问题。想法是,如果你执行 WHERE id > 600000 LIMIT 30 应该是相同的查询,对吧? - Amir Raminfar
哇,我刚刚测试了你的想法 :O 如果没有偏移量,那么:where id > n + limit(30) - 查询1 0.05秒 查询2 0.07秒 :OOOOOOOOOO 太不可思议了 :OOOO - itsme
sbaaaang,你没有获取相同数量的行……在查询2中,你获取了6000030行……跳过6000000行的正确查询应该是:SELECT * FROM table LIMIT 6000000, 30;LIMIT的第二个参数是要检索的行数,而不是上限。 - Jinxmcg
显示剩余5条评论
3个回答

8
不仔细查看的话,我认为这是因为第一个查询只需要读取前50条记录就可以返回结果,而第二个查询需要读取六百万条记录才能返回结果。基本上,第一个查询会更快地完成。
我认为这与表的构成有很大关系——字段类型和键等等。
如果一条记录由固定长度的字段组成(例如CHAR vs. VARCHAR),那么DBMS可以计算出第n条记录从哪里开始,并跳转到该位置。如果是可变长度,则必须读取记录以确定第n条记录从哪里开始。同样,我进一步认为具有适当主键的表比没有此类键的表查询速度更快。

这就是我确信的 :( 我认为没有解决办法,对吧?只有查询缓存 :( - itsme
1
@user 我暂时想不出解决方案。我唯一能想到的 - 这是一个彻底的hack - 就是添加一个日期时间字段来标记记录的创建,然后在该字段上添加索引,并在查询中按照该字段排序。我没有测试过这个方法,但你可能可以通过这个键来限制数据库,从而使查询在O(1)时间内运行,但我不会指望它。此外,它并不完全符合你上面的查询,因为默认排序顺序未经规定 - 你将模拟一个常见的约定而不是规范; 你的情况可能有所不同。 - AgentConundrum
感谢你的技巧,我会尝试一些东西。无论如何,我只是想问一下区别,以更好地了解MySQL处理数据库记录的方式 ;) - itsme

6

我认为减速是因为你正在使用带有偏移量限制的查询,并且没有其他上下文可用于索引表。可能第一个查询更快,因为它可以更快地到达偏移量。


1
一些搜索结果表明,MySQL会计算每一行直到达到偏移量..所以猜测相比于第20行,到达xxxxx偏移量需要更长的时间。 - Jake Dempsey
那是真正的索引,虽然不是速度问题,但我只是在问有什么区别 ;) - itsme

4
这是返回50行和6000030行(或者说大约100万行,因为你说总共只有700万行)的区别。
使用两个参数时,第一个参数指定要返回的第一行的偏移量,第二个参数指定要返回的最大行数。初始行的偏移量为0(不是1):
SELECT * FROM tbl LIMIT 5,10; # 检索第6-15行

http://dev.mysql.com/doc/refman/5.0/en/select.html

此外,我认为您正在寻找30行页面,因此查询应在限制子句的第二个参数中使用30。
SELECT    * 
FROM      table 
LIMIT     20, 30;

SELECT    * 
FROM      table 
LIMIT     6000000, 30;

第二个参数可能是一个影响因素,因为查询实际上返回了更多的行。我认为完全不能说这不提供答案。他的回答是返回大量行需要更长时间,这可能部分正确。 - Jake Dempsey
好的...那么在该范围内的记录是被解析还是被跳过?我认为它们会被解析,否则就没有区别了,对吧? - itsme
偏移量与行数相比非常小。我正在查找参考资料。 - dotjoe
@dotjoe 很酷,那我道歉下降票 - 我认为这个答案是相当有效的。 - Josh Darnell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接