On this page
8.2.1.17 LIMIT 查询优化
如果从结果集中只需要指定数量的行,请在查询中使用LIMIT
子句,而不要获取整个结果集并丢弃多余的数据。
MySQL 有时会优化具有LIMIT row_count
子句而没有HAVING
子句的查询:
如果您只选择
LIMIT
的几行,则在某些情况下,MySQL 通常会选择使用全 table 扫描,而 MySQL 通常会使用索引。如果将
LIMIT row_count
和ORDER BY
结合使用,MySQL 会在找到排序结果的前*row_count
行后立即停止排序,而不是对整个结果进行排序。如果通过使用索引进行排序,这将非常快。如果必须执行文件排序,则在找到第一个row_count
*之前,将选择与查询匹配的所有行,但不带有LIMIT
子句,并对其中的大多数或全部进行排序。找到初始行后,MySQL 不会对结果集的其余部分进行排序。
此行为的一种体现是,具有和不具有LIMIT
的ORDER BY
查询可能以不同的 Sequences 返回行,如本节稍后所述。
如果将
LIMIT row_count
和DISTINCT
结合使用,MySQL 将在找到*row_count
*唯一行后立即停止。在某些情况下,可以通过按 Sequences 读取索引(或对索引进行排序),然后计算汇总直到索引值更改来解决
GROUP BY
。在这种情况下,LIMIT row_count
不会计算任何不必要的GROUP BY
值。MySQL 一旦向 Client 端发送了所需的行数,它将立即中止查询,除非您使用
SQL_CALC_FOUND_ROWS
。在这种情况下,可以使用SELECT FOUND_ROWS()
检索行数。参见第 12.15 节“信息功能”。
LIMIT 0
快速返回一个空集。这对于检查查询的有效性很有用。它还可以用于获取使用 MySQL API 的应用程序中结果列元数据的类型的结果列的类型。通过mysqlClient 端程序,您可以使用--column-type-info选项显示结果列类型。如果服务器使用临时 table 来解析查询,则它使用
LIMIT row_count
子句来计算所需的空间。如果没有为
ORDER BY
使用索引,但是也存在LIMIT
子句,则优化器可能能够避免使用合并文件,并使用内存中filesort
操作对内存中的行进行排序。
如果ORDER BY
列中的多行具有相同的值,则服务器可以自由地以任何 Sequences 返回这些行,并且根据整体执行计划,这样做的方式可能有所不同。换句话说,这些行的排序 Sequences 相对于无序列是不确定的。
影响执行计划的一个因素是LIMIT
,因此具有LIMIT
和不具有LIMIT
的ORDER BY
查询可能以不同的 Sequences 返回行。考虑以下查询,该查询按category
列排序,但相对于id
和rating
列不确定:
mysql> SELECT * FROM ratings ORDER BY category;
+----+----------+--------+
| id | category | rating |
+----+----------+--------+
| 1 | 1 | 4.5 |
| 5 | 1 | 3.2 |
| 3 | 2 | 3.7 |
| 4 | 2 | 3.5 |
| 6 | 2 | 3.5 |
| 2 | 3 | 5.0 |
| 7 | 3 | 2.7 |
+----+----------+--------+
包含LIMIT
可能会影响每个category
值中的行 Sequences。例如,这是一个有效的查询结果:
mysql> SELECT * FROM ratings ORDER BY category LIMIT 5;
+----+----------+--------+
| id | category | rating |
+----+----------+--------+
| 1 | 1 | 4.5 |
| 5 | 1 | 3.2 |
| 4 | 2 | 3.5 |
| 3 | 2 | 3.7 |
| 6 | 2 | 3.5 |
+----+----------+--------+
在每种情况下,这些行均按ORDER BY
列排序,这是 SQL 标准所要求的全部。
如果重要的是要确保带有LIMIT
和不带有LIMIT
的行 Sequences 相同,请在ORDER BY
子句中包括其他列以使 Sequences 确定。例如,如果id
值是唯一的,则可以通过以下排序使给定category
值的行以id
Sequences 显示:
mysql> SELECT * FROM ratings ORDER BY category, id;
+----+----------+--------+
| id | category | rating |
+----+----------+--------+
| 1 | 1 | 4.5 |
| 5 | 1 | 3.2 |
| 3 | 2 | 3.7 |
| 4 | 2 | 3.5 |
| 6 | 2 | 3.5 |
| 2 | 3 | 5.0 |
| 7 | 3 | 2.7 |
+----+----------+--------+
mysql> SELECT * FROM ratings ORDER BY category, id LIMIT 5;
+----+----------+--------+
| id | category | rating |
+----+----------+--------+
| 1 | 1 | 4.5 |
| 5 | 1 | 3.2 |
| 3 | 2 | 3.7 |
| 4 | 2 | 3.5 |
| 6 | 2 | 3.5 |
+----+----------+--------+