8.2.1.17 LIMIT 查询优化
8.2.1.17 LIMIT Query Optimization 8.2.1.17 LIMIT 查询优化
原文:https://dev.mysql.com/doc/refman/5.7/en/limit-optimization.html
If you need only a specified number of rows from a result set, use a LIMIT clause in the query, rather than fetching the whole result set and throwing away the extra data.
如果您只需要从结果集中获取指定数量的行,那么在查询中使用 LIMIT 子句,而不是获取整个结果集并丢弃额外的数据。
MySQL sometimes optimizes a query that has a LIMIT clause and no row_countHAVING clause:
MySQL 有时会优化一个具有 LIMIT row count 子句和没有 HAVING 子句的查询:
-
If you select only a few rows with
LIMIT, MySQL uses indexes in some cases when normally it would prefer to do a full table scan.如果使用 LIMIT 只选择几行,MySQL 在某些情况下会使用索引,而通常情况下它更愿意进行全表扫描。
-
If you combine
LIMITwithrow_countORDER BY, MySQL stops sorting as soon as it has found the firstrow_countrows of the sorted result, rather than sorting the entire result. If ordering is done by using an index, this is very fast. If a filesort must be done, all rows that match the query without theLIMITclause are selected, and most or all of them are sorted, before the firstrow_countare found. After the initial rows have been found, MySQL does not sort any remainder of the result set.如果将 LIMIT row _ count 和 ORDER BY 组合在一起,那么 MySQL 在找到排序结果的第一行 count 行时就停止排序,而不是对整个结果进行排序。如果使用索引进行排序,这是非常快的。如果必须进行文件分类,则选择与查询匹配但不包含 LIMIT 子句的所有行,并在找到第一行计数之前对其中的大部分或全部进行排序。在找到初始行之后,MySQL 不会对结果集的其余部分进行排序。
One manifestation of this behavior is that an
ORDER BYquery with and withoutLIMITmay return rows in different order, as described later in this section.这种行为的一个表现是,带有和不带 LIMIT 的 ORDER BY 查询可能以不同的顺序返回行,如本节后面所述。
-
If you combine
LIMITwithrow_countDISTINCT, MySQL stops as soon as it findsrow_countunique rows.如果将 LIMIT row _ count 和 DISTINCT 组合在一起,MySQL 会在发现 row _ count 唯一行时立即停止。
-
In some cases, a
GROUP BYcan be resolved by reading the index in order (or doing a sort on the index), then calculating summaries until the index value changes. In this case,LIMITdoes not calculate any unnecessaryrow_countGROUP BYvalues.在某些情况下,可以通过按顺序读取索引(或对索引进行排序) ,然后计算汇总,直到索引值发生变化,从而解析 GROUP BY。在这种情况下,LIMIT 行计数不会计算任何不必要的 groupby 值。
-
As soon as MySQL has sent the required number of rows to the client, it aborts the query unless you are using
SQL_CALC_FOUND_ROWS. In that case, the number of rows can be retrieved withSELECT FOUND_ROWS(). See Section 12.16, “Information Functions”.一旦 MySQL 向客户端发送了所需的行数,它就会中止查询,除非您使用的是 sql_calc _ found _ rows。在这种情况下,可以使用 selectfound _ rows ()检索行数。见第12.16节“信息功能”。
-
LIMIT 0quickly returns an empty set. This can be useful for checking the validity of a query. It can also be employed to obtain the types of the result columns within applications that use a MySQL API that makes result set metadata available. With the mysql client program, you can use the--column-type-infooption to display result column types.LIMIT 0迅速返回一个空集。这对于检查查询的有效性很有用。它还可以用来获取应用程序中结果列的类型,这些应用程序使用 MySQL API 使结果集元数据可用。使用 mysql 客户机程序,可以使用 -- column-type-info 选项来显示结果列类型。
-
If the server uses temporary tables to resolve a query, it uses the
LIMITclause to calculate how much space is required.row_count如果服务器使用临时表解析查询,则使用 LIMIT row _ count 子句计算所需的空间。
-
If an index is not used for
ORDER BYbut aLIMITclause is also present, the optimizer may be able to avoid using a merge file and sort the rows in memory using an in-memoryfilesortoperation.如果没有为 ORDER BY 使用索引,但是也存在 LIMIT 子句,优化器可以避免使用合并文件,并使用内存中的文件分类操作对内存中的行进行排序。
If multiple rows have identical values in the ORDER BY columns, the server is free to return those rows in any order, and may do so differently depending on the overall execution plan. In other words, the sort order of those rows is nondeterministic with respect to the nonordered columns.
如果多行在 ORDER BY 列中具有相同的值,服务器可以以任意顺序返回这些行,并且可以根据总体执行计划以不同的方式返回。换句话说,这些行相对于无序列的排序顺序是不确定的。
One factor that affects the execution plan is LIMIT, so an ORDER BY query with and without LIMIT may return rows in different orders. Consider this query, which is sorted by the category column but nondeterministic with respect to the id and rating columns:
影响执行计划的一个因素是 LIMIT,因此带有和不带 LIMIT 的 orderby 查询可能会以不同的顺序返回行。考虑一下这个查询,它是按类别列排序的,但是对于 id 和等级列不确定:
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 |
+----+----------+--------+
Including LIMIT may affect order of rows within each category value. For example, this is a valid query result:
包含 LIMIT 可能会影响每个类别值中的行顺序。例如,这是一个有效的查询结果:
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 |
+----+----------+--------+
In each case, the rows are sorted by the ORDER BY column, which is all that is required by the SQL standard.
在每种情况下,行都按 orderby 列进行排序,这是 SQL 标准所需的全部内容。
If it is important to ensure the same row order with and without LIMIT, include additional columns in the ORDER BY clause to make the order deterministic. For example, if id values are unique, you can make rows for a given category value appear in id order by sorting like this:
如果确保有和没有 LIMIT 的相同行顺序很重要,那么在 ORDER BY 子句中包含额外的列,以确保顺序具有确定性。例如,如果 id 值是唯一的,你可以通过这样的排序使给定类别值的行按 id 顺序出现:
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 |
+----+----------+--