【问题标题】:Select is much slower when selecting latest records选择最新记录时选择要慢得多
【发布时间】:2010-08-24 14:23:52
【问题描述】:

一个包含大约 70K 记录的表格显示在网站上,每页显示 50 条记录。 查询时使用limit offset,50进行分页,记录可以按不同的列排序。

浏览最新页面(因此偏移量约为 60,000)使查询比浏览第一页时慢得多(大约 10 倍)

这是使用limit 命令的问题吗? 还有其他方法可以获得相同的结果吗?

【问题讨论】:

  • 好问题,我不熟悉 MySQL 在这方面的工作原理。
  • 感谢您的回复,稍后将测试它以希望获得一些速度。

标签: php sql mysql limit


【解决方案1】:

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

即使计划使用filesort(这意味着应该浏览所有记录),MySQL 也会对其进行优化,以便仅对$offset + $limit 顶部的记录进行排序,这对于较低的@987654327 值更有效@。

典型的解决方案是索引您正在排序的列,记录列的最后一个值并在后续查询中重用它,如下所示:

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

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

【讨论】:

  • MySQL 是否支持元组样式语法 ((val1, val2) > (1, 2))?我以前从未见过。什么是组合器(并且,我假设)?我猜你每天都会学到一些新东西……
  • @ircmaxell:是的。是字典顺序,和val1 > 1 OR (val1 = 1 AND val2 > 2)一样
  • 好答案。这是一个我认为有一些很好的信息的演示文稿:slideshare.net/Eweaver/efficient-pagination-using-mysql
  • 我比较了新旧查询,加入的查询要快两到三倍。谢谢!作为一个副作用,我注意到在某些情况下,我可以减少 order by 上的列数,而不会产生显着差异,并且还可以提高速度。
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-27
    • 2012-03-19
    • 1970-01-01
    • 2021-05-16
    • 1970-01-01
    • 1970-01-01
    • 2014-02-06
    • 1970-01-01
    相关资源
    最近更新 更多