很多线程已经在网上,只是想了解一些令我困惑的细微差别!
Quoting the doc reference
如果将LIMIT row_count与ORDER BY结合使用,MySQL会在找到排序结果的第一行row_count行后立即停止排序,而不是对整个结果进行排序 . 如果使用索引完成排序,则速度非常快 .
and a 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 sorting
?不是 limit
子句应用于通过 order by
子句返回的已经排序的数据(假设它是 non-indexed
列)或者我的理解是错误的,SQL首先是 limit
然后排序!! ??
2 回答
这实际上是mysql中非常明智的优化 . 如果你使用limit来返回20行并且mysql知道它已经找到了它们,那么为什么mysql(或你)会关心其余记录的排序方式呢?没关系,因此mysql停止对其余行进行排序 .
如果order by是在索引列上完成的,那么mysql可以很快地告诉它是否找到了前n个记录 .
文档中提到的优化通常只有在
publish_date
列上有索引时才有效 . 这些值按顺序存储在索引中,因此引擎只需迭代列的索引,获取相关的行,直到它获取了20行 .如果列未编入索引,则引擎通常需要获取所有行,对它们进行排序,然后返回其中的前20行 .
了解它如何与
WHERE
条件相互作用也很有用 . 假设查询是:如果
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行 .