2010-08-24 76 views
6

在一个站点上显示一个包含约70K条记录的表格,每页显示50条记录。 在查询上使用limit offset,50完成分页,并且记录可以在不同的列上排序。选择最新记录时选择速度要慢很多

浏览最新的页面(因此偏移约60,000)使得查询慢得多浏览前几页(约10倍)

这是使用limit命令的一个问题,当比? 是否有其他方法可以获得相同的结果?

+0

好问题,我不熟悉MySQL在这方面的工作原理。 – RedFilter 2010-08-24 14:26:05

+0

感谢你的回复,稍后会测试它,希望能获得一些速度。 – Omiod 2010-08-24 16:07:28

回答

7

随着较大的偏移量,MySQL需要浏览更多的记录。

即使计划使用filesort(这意味着所有的记录应该浏览),MySQL优化,这样只有$offset + $limit最高记录进行排序,这使得它更加高效为$offset较低值。

典型的解决方案是索引您订购的列,记录列的最后一个值,并在随后的查询重用,像这样:

SELECT * 
FROM mytable 
ORDER BY 
     value, id 
LIMIT 0, 10 

,输出:

value id 

1  234 
3  57 
4  186 
5  457 
6  367 
8  681 
10  366 
13  26 
15  765 
17  345 -- this is the last one 

要进入下一个页面,你可以使用:

SELECT * 
FROM mytable 
WHERE (value, id) > (17, 345) 
ORDER BY 
     value, id 
LIMIT 0, 10 

,它采用了在请登录(value, id)查询。

当然这不会对任意访问页面有所帮助,但有助于顺序浏览。

另外,MySQL在后期查询中存在一些问题。如果列索引,它可能是值得尝试重写查询是这样的:

SELECT * 
FROM (
     SELECT id 
     FROM mytable 
     ORDER BY 
       value, id 
     LIMIT $offset, $limit 
     ) q 
JOIN mytable m 
ON  m.id = q.id 

请参阅这篇文章更详细的解释:

+0

MySQL支持元组式样的语法('(val1,val2)>(1,2)')?我以前从来没有见过。什么是组合器(和,我假设)?我想你每天都会学到新的东西...... – ircmaxell 2010-08-24 14:40:41

+0

@ircmaxell:是的。它是字典顺序,与val1> 1 OR(val1 = 1 AND val2> 2)相同' – Quassnoi 2010-08-24 14:42:19

+0

好的答案。这里是一个演示,我认为有一些很好的信息是沿着相同的路线:http://www.slideshare.net/Eweaver/efficient-pagination-using-mysql – nathan 2010-08-24 18:42:01

2

这是MySQL如何处理限制。如果它可以对索引进行排序(并且查询足够简单),则可以在找到第一个offset + limit行后停止搜索。所以LIMIT 0,10意味着如果查询很简单,它可能只需要扫描10行。但LIMIT 1000,10意味着至少需要扫描1010行。当然,需要扫描的实际行数取决于许多其他因素。但重点在于,limit + offset越低,需要扫描的行数越低...

至于变通方法,我会优化您的查询,以便查询本身没有LIMIT子句尽可能高效。 EXPLAIN是你在这种情况下的朋友...