SQL如何执行limit和offset?

3

我想知道limit和offset是在选定行之后执行的吗:

SELECT * FROM users WHERE id > 4 LIMIT 0,90 ORDER BY datetime DESC;

这个查询是先选择所有用户的行再应用 LIMIT,还是先应用 LIMIT 再选择用户的行?


2
在没有使用ORDER BY的情况下使用LIMIT意味着您将无法获得可预测的结果。如果您正在使用LIMIT,确实应该定义您希望以什么顺序返回结果。否则,MySQL不能保证您实际上会收到哪些行。 - Gavin Towey
4个回答

4

FROM子句是查询中首先执行的,然后是WHERE子句。之后应用LIMIT子句。

因此,以下是您发布的查询的逻辑查询处理步骤:

  • FROM子句返回所有用户。
  • 应用WHERE子句。只有id > 4的用户才能通过下一个步骤。
  • 然后是LIMIT

2
所以你提出的问题在这里并不太合适。
你真正应该问的是:“MySQL是否必须找到与查询中WHERE子句匹配的所有行,还是可以应用LIMIT,并且只需要读取最多N行?”
这里有两种可能情况,还有一件额外需要考虑的事情,以及你原始查询中存在的一个问题。
1. 如果你使用了LIMIT,应该使用ORDER BY。MySQL没有“自然”顺序,这意味着实际从查询中获取的行不是确定性的。这是不好的。
现在你正在使用ORDER BY,有两种可能性。
1. MySQL可以使用索引来满足ORDER BY子句。在这种情况下,它可以按索引顺序扫描表,查找匹配项,直到满足LIMIT为止,然后停止读取。这是有效的。
2. MySQL无法使用索引。然后它将不得不找到所有可能的匹配项,并在应用LIMIT之前对整个结果集进行排序。如果有很多行,这通常会非常慢。
需要考虑的另一个问题是,当你在limit中使用偏移量时,mysql必须读取所有到达起始位置之前的行才能返回结果。当偏移值非常大时,这会变得非常慢。
这篇关于MySQL高效分页的幻灯片解释了很多问题: http://www.scribd.com/doc/14683263/Efficient-Pagination-Using-MySQL

你可以使用SQL:2011的特性来获得确定性的LIMIT等效功能。搜索WITH TIES - Janus Troelsen

1

选择查询

SELECT * FROM users WHERE id > 4 LIMIT 0,90;

1

来自http://dev.mysql.com/doc/refman/5.0/en/limit-optimization.html

如果您在ORDER BY中使用LIMIT row_count,MySQL会在找到排序结果的前row_count行后立即结束排序,而不是对整个结果进行排序。如果使用索引进行排序,则速度非常快。如果必须进行文件排序,则必须选择与没有LIMIT子句的查询匹配的所有行,并且必须对其中大部分或全部进行排序,然后才能确定已找到前row_count行。在任何情况下,在找到初始行之后,没有必要对结果集的任何其余部分进行排序,MySQL也不会这样做。

主参考链接


MySQL永远不会进行部分文件排序。如果它无法使用索引进行排序,它将始终在应用LIMIT子句之前对整个结果集进行排序。 - Gavin Towey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接