【问题标题】:Order by / limit execution in SQL在 SQL 中排序/限制执行
【发布时间】:2018-12-08 20:58:07
【问题描述】:

网上已经有很多帖子了,只是想了解一些让我感到困惑的细微差别!

引用doc reference

如果将 LIMIT row_count 与 ORDER BY 结合使用,MySQL 将停止排序为 一旦找到排序结果的前 row_count 行, 而不是对整个结果进行排序。如果订购是通过使用 索引,这非常快。

SO thread

它将首先订购,然后获取前 20 个。数据库也将 在 ORDER BY 之前处理 WHERE 子句中的任何内容。

从问题中获取相同的查询:

SELECT article
FROM table1
ORDER BY publish_date
LIMIT 20

假设表有 2000 行,其中 query 预计将返回 20 行,现在,看着 mysql ref ....stops sorting as soon as it has found the first row_count rows.... 让我感到困惑,因为我觉得它有点模棱两可!!

为什么是stops sortinglimit 子句不是应用于通过order by 子句返回的已排序数据(假设它是non-indexed)还是我的理解错误,SQL 是limiting first然后排序!!??

【问题讨论】:

    标签: mysql sql-order-by limit


    【解决方案1】:

    文档中提到的优化通常仅在publish_date 列上有索引时才有效。这些值按顺序存储在索引中,因此引擎只需遍历列的索引,获取关联的行,直到获取 20 行。

    如果列没有被索引,引擎通常需要获取所有行,对它们进行排序,然后返回其中的前 20 行。

    了解它如何与WHERE 条件相互作用也很有用。假设查询是:

    SELECT article
    FROM table1
    WHERE last_read_date > '2018-11-01'
    ORDER BY publish_date
    LIMIT 20
    

    如果publish_date被索引而last_read_date没有被索引,它将依次扫描publish_date索引,根据条件测试关联的last_read_date,如果测试成功则将article添加到结果集中.当结果集中有 20 行时,它将停止并返回它。

    如果last_read_date 被索引而publish_date 没有被索引,它将使用last_read_date 索引来查找所有满足条件的行的子集。然后它将使用 publish_date 列对这些行进行排序,并从中返回前 20 行。

    如果两列都没有被索引,它将进行全表扫描以测试last_read_date,对所有符合条件的行进行排序,并返回前 20 行。

    【讨论】:

    • 嗨,Barmar,感谢您的解释。几个疑问:1。根据indexed 列,mysql 实际上可能最终会在您概述的所有 3 种情况下返回不同的行集? 2If publish_date is indexed and last_read_date is not -> 因为默认order byASC 中,所以这个查询实际上不会返回最旧的article,因为过滤条件在order by 而不是where 子句上? (表示最旧的publish datelast read 在这种情况下返回!!!)
    • 如果您有多行具有相同的发布日期,这样 20 行截止点以一组具有相同发布日期的行结束,您的查询可能会得到不同的结果。例如,假设您每天发布 6 个并且它们都被阅读。从前 3 天起,您总是会得到相同的 18 个,但从第四天起您只会得到 2 个,而您得到的 2 个可能会有所不同,具体取决于您使用的查询变体。如果每一行都有不同的 publish_date,那么无论有哪个索引,您总是会得到相同的 20。索引改变了mysql获取数据的方式,而不是你得到的。
    • @NoobEditor 除非有重复的publish_date 值,否则您应该得到相同的结果。这些只是性能优化,不会改变查询的含义。
    • 如果有重复,并且超过20行符合条件,则无法预测会选择哪20行,不同的优化可能会导致选择不同的一次。
    【解决方案2】:

    MySQL 在找到排序结果的前 row_count 行后立即停止排序,而不是对整个结果进行排序

    这实际上是mysql内部非常明智的优化。如果您使用 limit 返回 20 行并且 mysql 知道它已经找到它们,那么 mysql(或您)为什么会关心其余记录的排序方式?没关系,因此 mysql 停止对其余行进行排序。

    如果 order by 是在索引列上完成的,那么 mysql 可以很快判断它是否找到了前 n 条记录。

    【讨论】:

      猜你喜欢
      • 2013-01-06
      • 2010-10-28
      • 1970-01-01
      • 1970-01-01
      • 2015-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多