网站上显示一个大约70K记录的表,每页显示50条记录。
在查询中使用limit offset,50
进行分页,并且可以在不同的列上对记录进行排序。
浏览最新页面(因此偏移量大约为60,000)会使查询比浏览第一页(约10倍)时慢得多
这是使用limit
命令的问题吗?
还有其他方法可以获得相同的结果吗?
答案 0 :(得分: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
有关更详细的说明,请参阅此文章:
答案 1 :(得分:2)
这是MySQL处理限制的方式。如果它可以对索引进行排序(并且查询足够简单),它可以在找到第一个offset + limit
行后停止搜索。所以LIMIT 0,10
意味着如果查询足够简单,它可能只需要扫描10行。但LIMIT 1000,10
表示至少需要扫描1010行。当然,需要扫描的实际行数取决于许多其他因素。但这里的要点是limit + offset
越低,需要扫描的行数下限就越低......
至于变通方法,我会优化您的查询,以便不带LIMIT
子句的查询本身尽可能高效。 EXPLAIN
在这种情况下你是朋友......