The range
access method uses a single index to retrieve a subset of table rows that are contained within one or several index value intervals. RANGE
访问方法使用单个索引来检索包含在一个或多个索引值间隔内的表行子集。It can be used for a single-part or multiple-part index. 它可以用于单个零件或多个零件索引。The following sections describe conditions under which the optimizer uses range access.以下部分描述优化器使用范围访问的条件。
For a single-part index, index value intervals can be conveniently represented by corresponding conditions in the 对于单个部分索引,索引值间隔可以方便地用WHERE
clause, denoted as range conditions rather than “intervals.”WHERE
子句中的相应条件表示,表示为“范围条件”而不是“间隔”
The definition of a range condition for a single-part index is as follows:单个零件索引的范围条件定义如下:
For both 对于BTREE
and HASH
indexes, comparison of a key part with a constant value is a range condition when using the =
, <=>
, IN()
, IS NULL
, or IS NOT NULL
operators.BTREE
索引和HASH
索引,当使用=
、<=>
、IN
、IS NULL
或IS NOT NULL
运算符时,键部分与常量值的比较是一个范围条件。
Additionally, for 此外,对于BTREE
indexes, comparison of a key part with a constant value is a range condition when using the >
, <
, >=
, <=
, BETWEEN
, !=
, or <>
operators, or LIKE
comparisons if the argument to LIKE
is a constant string that does not start with a wildcard character.BTREE
索引,使用>
、<
、>=
、<=
、BETWEEN
、!=
或<>
运算符时,或使用LIKE
比较且LIKE
的参数是不以通配符开头的常量字符串时,则关键部分与常量值的比较是一个范围条件。
For all index types, multiple range conditions combined with 对于所有索引类型,多个范围条件与OR
or AND
form a range condition.OR
或AND
组合形成一个范围条件。
“Constant value” in the preceding descriptions means one of the following:上述说明中的“常量值”是指下列情况之一:
Here are some examples of queries with range conditions in the 以下是WHERE
clause:WHERE
子句中带有范围条件的查询示例:
SELECT * FROM t1 WHEREkey_col
> 1 ANDkey_col
< 10; SELECT * FROM t1 WHEREkey_col
= 1 ORkey_col
IN (15,18,20); SELECT * FROM t1 WHEREkey_col
LIKE 'ab%' ORkey_col
BETWEEN 'bar' AND 'foo';
Some nonconstant values may be converted to constants during the optimizer constant propagation phase.在优化器常量传播阶段,一些非常量值可能会转换为常量。
MySQL tries to extract range conditions from the MySQL尝试从WHERE
clause for each of the possible indexes. WHERE
子句中为每个可能的索引提取范围条件。During the extraction process, conditions that cannot be used for constructing the range condition are dropped, conditions that produce overlapping ranges are combined, and conditions that produce empty ranges are removed.在提取过程中,删除不能用于构造范围条件的条件,合并产生重叠范围的条件,并删除产生空范围的条件。
Consider the following statement, where 考虑下面的语句,其中key1
is an indexed column and nonkey
is not indexed:key1
是索引列,而nonkey
没有索引:
SELECT * FROM t1 WHERE (key1 < 'abc' AND (key1 LIKE 'abcde%' OR key1 LIKE '%b')) OR (key1 < 'bar' AND nonkey = 4) OR (key1 < 'uux' AND key1 > 'z');
The extraction process for key key1
is as follows:key1
的提取过程如下:
Start with original 从原始WHERE
clause:WHERE
子句开始:
(key1 < 'abc' AND (key1 LIKE 'abcde%' OR key1 LIKE '%b')) OR (key1 < 'bar' AND nonkey = 4) OR (key1 < 'uux' AND key1 > 'z')
Remove 删除nonkey = 4
and key1 LIKE '%b'
because they cannot be used for a range scan. nonkey = 4
和key1 LIKE '%b'
,因为它们不能用于范围扫描。The correct way to remove them is to replace them with 删除它们的正确方法是将它们替换为TRUE
, so that we do not miss any matching rows when doing the range scan. TRUE
,这样在执行范围扫描时就不会丢失任何匹配的行。Replacing them with 用TRUE
yields:TRUE
产生代替它们:
(key1 < 'abc' AND (key1 LIKE 'abcde%' OR TRUE)) OR (key1 < 'bar' AND TRUE) OR (key1 < 'uux' AND key1 > 'z')
Collapse conditions that are always true or false:始终为真或假的折叠条件:
(key1 LIKE 'abcde%' OR TRUE)
is always true始终是true
(key1 < 'uux' AND key1 > 'z')
is always false始终是false
Replacing these conditions with constants yields:将这些条件替换为常数会产生:
(key1 < 'abc' AND TRUE) OR (key1 < 'bar' AND TRUE) OR (FALSE)
Removing unnecessary 删除不必要的TRUE
and FALSE
constants yields:TURE
常量和FALSE
常量会产生:
(key1 < 'abc') OR (key1 < 'bar')
Combining overlapping intervals into one yields the final condition to be used for the range scan:将重叠的间隔合并为一个,得到用于范围扫描的最终条件:
(key1 < 'bar')
In general (and as demonstrated by the preceding example), the condition used for a range scan is less restrictive than the 一般来说(如前面的示例所示),用于范围扫描的条件比WHERE
clause. WHERE
子句的限制性小。MySQL performs an additional check to filter out rows that satisfy the range condition but not the full MySQL执行额外的检查来过滤出满足范围条件但不满足完整WHERE
clause.WHERE
子句的行。
The range condition extraction algorithm can handle nested 范围条件提取算法可以处理任意深度的嵌套AND
/OR
constructs of arbitrary depth, and its output does not depend on the order in which conditions appear in WHERE
clause.AND
/OR
构造,其输出不依赖于WHERE
子句中条件出现的顺序。
MySQL does not support merging multiple ranges for the MySQL不支持为空间索引的range
access method for spatial indexes. range
访问方法合并多个范围。To work around this limitation, you can use a 要解决此限制,可以将UNION
with identical SELECT
statements, except that you put each spatial predicate in a different SELECT
.UNION
与相同的SELECT
语句一起使用,只是将每个空间谓词放在不同的SELECT
语句中。
Range conditions on a multiple-part index are an extension of range conditions for a single-part index. 多零件索引的范围条件是单个零件索引范围条件的扩展。A range condition on a multiple-part index restricts index rows to lie within one or several key tuple intervals. 多部分索引的范围条件限制索引行位于一个或多个键元组间隔内。Key tuple intervals are defined over a set of key tuples, using ordering from the index.密钥元组间隔是在一组密钥元组上定义的,使用索引的顺序。
For example, consider a multiple-part index defined as 例如,考虑一个定义为key1(
, and the following set of key tuples listed in key order:key_part1
, key_part2
, key_part3
)key1(
的多个部分索引,以及以下关键顺序列出的关键元组:key_part1
, key_part2
, key_part3
)
key_part1
key_part2
key_part3
NULL 1 'abc' NULL 1 'xyz' NULL 2 'foo' 1 1 'abc' 1 1 'xyz' 1 2 'abc' 2 1 'aaa'
The condition 条件
defines this interval:key_part1
= 1
定义了这个间隔:key_part1
= 1
(1,-inf,-inf) <= (key_part1
,key_part2
,key_part3
) < (1,+inf,+inf)
The interval covers the 4th, 5th, and 6th tuples in the preceding data set and can be used by the range access method.间隔覆盖了前面数据集中的第4、第5和第6个元组,可由范围访问方法使用。
By contrast, the condition 相比之下,条件
does not define a single interval and cannot be used by the range access method.key_part3
= 'abc'
没有定义单个间隔,不能由范围访问方法使用。key_part3
= 'abc'
The following descriptions indicate how range conditions work for multiple-part indexes in greater detail.以下描述更详细地说明了范围条件如何适用于多个零件索引。
For 对于HASH
indexes, each interval containing identical values can be used. HASH
索引,可以使用包含相同值的每个间隔。This means that the interval can be produced only for conditions in the following form:这意味着只能针对以下形式的条件生成间隔:
key_part1
cmp
const1
ANDkey_part2
cmp
const2
AND ... ANDkey_partN
cmp
constN
;
Here, 这里,const1
, const2
, … are constants, cmp
is one of the =
, <=>
, or IS NULL
comparison operators, and the conditions cover all index parts. const1
,const2
……是常量,cmp
是比较运算符=
,<=>
,或者IS NULL
之一,条件覆盖所有索引部分。(That is, there are (也就是说,有N
conditions, one for each part of an N
-part index.) N
个条件,N
部分索引的每个部分对应一个条件。)For example, the following is a range condition for a three-part 例如,以下是三部分HASH
index:HASH
索引的范围条件:
key_part1
= 1 ANDkey_part2
IS NULL ANDkey_part3
= 'foo'
For the definition of what is considered to be a constant, see Range Access Method for Single-Part Indexes.有关被视为常量的内容的定义,请参见单部分索引的范围访问方法。
For a 对于BTREE
index, an interval might be usable for conditions combined with AND
, where each condition compares a key part with a constant value using =
, <=>
, IS NULL
, >
, <
, >=
, <=
, !=
, <>
, BETWEEN
, or LIKE '
(where pattern
''
does not start with a wildcard). pattern
'BTREE
索引,间隔可能适用于与AND
组合的条件,其中每个条件使用=
,<=>
、IS NULL
、>
、<
、>=
、<=
、!=
、<>
、BETWEEN
或者LIKE '
(其中pattern
''
不以通配符开头)将关键部分与常量值进行比较。pattern
'An interval can be used as long as it is possible to determine a single key tuple containing all rows that match the condition (or two intervals if 只要有可能确定一个包含所有匹配条件的行的单键元组,就可以使用间隔(或者两个间隔,如果使用了<>
or !=
is used).<>
或者!=
)。
The optimizer attempts to use additional key parts to determine the interval as long as the comparison operator is 只要比较运算符为=
, <=>
, or IS NULL
. =
、<=>
,或IS NULL
,优化器会尝试使用其他关键部件确定区间。If the operator is 如果运算符为>
, <
, >=
, <=
, !=
, <>
, BETWEEN
, or LIKE
, the optimizer uses it but considers no more key parts. >
、<
、>=
、<=
、!=
、<>
、BETWEEN
或者LIKE
,优化器使用它,但不考虑更多的关键部分。For the following expression, the optimizer uses 对于下面的表达式,优化器在第一次比较中使用=
from the first comparison. =
。It also uses 它还从第二个比较中使用>=
from the second comparison but considers no further key parts and does not use the third comparison for interval construction:>=
,但不考虑其他关键部分,也不使用间隔构造的第三个比较:
key_part1
= 'foo' ANDkey_part2
>= 10 ANDkey_part3
> 10
The single interval is:单个间隔为:
('foo',10,-inf) < (key_part1
,key_part2
,key_part3
) < ('foo',+inf,+inf)
It is possible that the created interval contains more rows than the initial condition. 创建的间隔可能包含比初始条件更多的行。For example, the preceding interval includes the value 例如,前面的间隔包含不满足原始条件的值('foo', 11, 0)
, which does not satisfy the original condition.('foo', 11, 0)
。
If conditions that cover sets of rows contained within intervals are combined with 如果覆盖间隔内包含的行集合的条件与OR
, they form a condition that covers a set of rows contained within the union of their intervals. OR
组合,则它们形成覆盖间隔并集内包含的行集合的条件。If the conditions are combined with 如果这些条件与AND
, they form a condition that covers a set of rows contained within the intersection of their intervals. AND
组合在一起,则它们形成了一个条件,该条件覆盖了包含在其间隔交集内的一组行。For example, for this condition on a two-part index:例如,对于两部分索引的这种情况:
(key_part1
= 1 ANDkey_part2
< 2) OR (key_part1
> 5)
The intervals are:间隔为:
(1,-inf) < (key_part1
,key_part2
) < (1,2) (5,-inf) < (key_part1
,key_part2
)
In this example, the interval on the first line uses one key part for the left bound and two key parts for the right bound. 在本例中,第一行的间隔使用一个关键部分作为左边界,两个关键部分作为右边界。The interval on the second line uses only one key part. 第二行的间隔只使用一个关键部分。The key_len
column in the EXPLAIN
output indicates the maximum length of the key prefix used.EXPLAIN
输出中的key_len
列指示所用密钥前缀的最大长度。
In some cases, 在某些情况下,key_len
may indicate that a key part was used, but that might be not what you would expect. key_len
可能表示使用了关键部件,但这可能不是您所期望的。Suppose that 假设key_part1
and key_part2
can be NULL
. key_part1
和key_part2
可以为NULL
。Then the 然后key_len
column displays two key part lengths for the following condition:key_len
列显示以下条件下的两个键零件长度:
key_part1
>= 1 ANDkey_part2
< 2
But, in fact, the condition is converted to this:但是,事实上,条件转换为:
key_part1
>= 1 ANDkey_part2
IS NOT NULL
For a description of how optimizations are performed to combine or eliminate intervals for range conditions on a single-part index, see Range Access Method for Single-Part Indexes. 有关如何执行优化以组合或消除单个零件索引上范围条件的间隔的描述,请参见单个零件索引的范围访问方法。Analogous steps are performed for range conditions on multiple-part indexes.对多个零件索引的范围条件执行类似的步骤。
Consider these expressions, where 考虑这些表达式,其中col_name
is an indexed column:col_name
是索引列:
col_name
IN(val1
, ...,valN
)col_name
=val1
OR ... ORcol_name
=valN
Each expression is true if 如果col_name
is equal to any of several values. col_name
等于多个值中的任何一个,则每个表达式都为true
。These comparisons are equality range comparisons (where the “range” is a single value). 这些比较是相等范围比较(其中“范围”是单个值)。The optimizer estimates the cost of reading qualifying rows for equality range comparisons as follows:优化器估计读取相等范围比较的合格行的成本,如下所示:
If there is a unique index on 如果col_name
, the row estimate for each range is 1 because at most one row can have the given value.col_name
上有唯一索引,则每个范围的行估计数为1,因为最多一行可以有给定的值。
Otherwise, any index on 否则,col_name
is nonunique and the optimizer can estimate the row count for each range using dives into the index or index statistics.col_name
上的任何索引都是非唯一的,优化器可以使用深入索引或索引统计信息来估计每个范围的行数。
With index dives, the optimizer makes a dive at each end of a range and uses the number of rows in the range as the estimate. 使用索引跳转,优化器在范围的每一端跳转一次,并使用范围中的行数作为估计。For example, the expression 例如,表达式
has three equality ranges and the optimizer makes two dives per range to generate a row estimate. col_name
IN (10, 20, 30)
有三个相等范围,优化器对每个范围进行两次下潜以生成行估计。col_name
IN (10, 20, 30)Each pair of dives yields an estimate of the number of rows that have the given value.每对潜水产生一个具有给定值的行数估计值。
Index dives provide accurate row estimates, but as the number of comparison values in the expression increases, the optimizer takes longer to generate a row estimate. 索引潜水提供了精确的行估计,但是随着表达式中比较值的数量增加,优化器生成行估计所需的时间也会延长。Use of index statistics is less accurate than index dives but permits faster row estimation for large value lists.使用索引统计信息的准确性不如使用索引潜水,但可以更快地估计大值列表的行。
The eq_range_index_dive_limit
system variable enables you to configure the number of values at which the optimizer switches from one row estimation strategy to the other. eq_range_index_dive_limit
系统变量允许您配置优化器从一行估计策略切换到另一行估计策略的值的数量。To permit use of index dives for comparisons of up to 若要允许使用索引潜水来比较多达N
equality ranges, set eq_range_index_dive_limit
to N
+ 1. N
个相等范围,请将eq_range_index_dive_limit
设置为N
+1。To disable use of statistics and always use index dives regardless of 若要禁用统计信息并始终使用索引潜水而不考虑N
, set eq_range_index_dive_limit
to 0.N
,请将eq_range_index_dive_limit
设置为0。
To update table index statistics for best estimates, use 要更新表索引统计信息以获得最佳估计,请使用ANALYZE TABLE
.ANALYZE table
。
Prior to MySQL 8.0, there is no way of skipping the use of index dives to estimate index usefulness, except by using the 在MySQL 8.0之前,除了使用eq_range_index_dive_limit
system variable. eq_range_index_dive_limit
系统变量外,没有任何方法可以跳过使用索引潜水来估计索引的有用性。In MySQL 8.0, index dive skipping is possible for queries that satisfy all these conditions:在MySQL 8.0中,对于满足所有这些条件的查询,索引跳转是可能的:
The query is for a single table, not a join on multiple tables.查询是针对单个表的,而不是针对多个表的联接。
A single-index 存在单个索引FORCE INDEX
index hint is present. FORCE INDEX
索引提示。The idea is that if index use is forced, there is nothing to be gained from the additional overhead of performing dives into the index.其思想是,如果强制使用索引,那么执行索引潜水的额外开销将一无所获。
The index is nonunique and not a 索引是非唯一的,不是FULLTEXT
index.FULLTEXT
(全文)索引。
No subquery is present.不存在子查询。
No 不存在DISTINCT
, GROUP BY
, or ORDER BY
clause is present.DISTINCT
、GROUP BY
或ORDER BY
子句。
For 对于EXPLAIN FOR CONNECTION
, the output changes as follows if index dives are skipped:EXPLAIN For CONNECTION
,如果跳过索引潜水,则输出更改如下:
For traditional output, the 对于传统输出,rows
and filtered
values are NULL
.rows
值和filtered
值为空。
For JSON output, 对于JSON输出,不显示rows_examined_per_scan
and rows_produced_per_join
do not appear, skip_index_dive_due_to_force
is true
, and cost calculations are not accurate.rows_examined_per_scan
和rows_produced_per_join
,skip_index_dive_due_to_force
为true
,成本计算不准确。
Without 如果没有FOR CONNECTION
, EXPLAIN
output does not change when index dives are skipped.FOR CONNECTION
,当跳过索引潜水时,EXPLAIN
输出不会更改。
After execution of a query for which index dives are skipped, the corresponding row in the 在执行跳过索引删除的查询后,INFORMATION_SCHEMA.OPTIMIZER_TRACE
table contains an index_dives_for_range_access
value of skipped_due_to_force_index
.INFORMATION_SCHEMA.OPTIMIZER_TRACE
表中的相应行包含一个skipped_due_to_force_index
的index_dives_for_range_access
值。
Consider the following scenario:考虑下面的情景:
CREATE TABLE t1 (f1 INT NOT NULL, f2 INT NOT NULL, PRIMARY KEY(f1, f2)); INSERT INTO t1 VALUES (1,1), (1,2), (1,3), (1,4), (1,5), (2,1), (2,2), (2,3), (2,4), (2,5); INSERT INTO t1 SELECT f1, f2 + 5 FROM t1; INSERT INTO t1 SELECT f1, f2 + 10 FROM t1; INSERT INTO t1 SELECT f1, f2 + 20 FROM t1; INSERT INTO t1 SELECT f1, f2 + 40 FROM t1; ANALYZE TABLE t1; EXPLAIN SELECT f1, f2 FROM t1 WHERE f2 > 40;
To execute this query, MySQL can choose an index scan to fetch all rows (the index includes all columns to be selected), then apply the 为了执行这个查询,MySQL可以选择一个索引扫描来获取所有的行(索引包括所有要选择的列),然后应用f2 > 40
condition from the WHERE
clause to produce the final result set.WHERE
子句中的f2>40
条件来生成最终结果集。
A range scan is more efficient than a full index scan, but cannot be used in this case because there is no condition on 范围扫描比全索引扫描效率更高,但在这种情况下不能使用,因为第一个索引列f1
, the first index column. f1
没有条件。However, as of MySQL 8.0.13, the optimizer can perform multiple range scans, one for each value of 但是,从MySQL8.0.13开始,优化器可以使用类似于松散索引扫描的Skip-Scan方法(参见第8.2.1.17节,“按优化分组”):f1
, using a method called Skip Scan that is similar to Loose Index Scan (see Section 8.2.1.17, “GROUP BY Optimization”):
Skip between distinct values of the first index part, 在第一个索引部分f1
(the index prefix).f1
(索引前缀)的不同值之间跳过。
Perform a subrange scan on each distinct prefix value for the 对f2 > 40
condition on the remaining index part.f2 > 40
的每个不同前缀值执行子范围扫描剩余索引部分的条件。
For the data set shown earlier, the algorithm operates like this:对于前面显示的数据集,算法的操作方式如下:
Get the first distinct value of the first key part (获取第一个关键部分的第一个不同值(f1 = 1
).f1=1
)。
Construct the range based on the first and second key parts (根据第一个和第二个关键部分(f1 = 1 AND f2 > 40
).f1=1 AND f2>40
)。
Perform a range scan.执行范围扫描。
Get the next distinct value of the first key part (获取第一个关键部分的下一个不同值(f1 = 2
).f1=2
)。
Construct the range based on the first and second key parts (根据第一个和第二个关键部分(f1 = 2 AND f2 > 40
).f1 = 2 AND f2 > 40
)构造范围。
Perform a range scan.执行范围扫描。
Using this strategy decreases the number of accessed rows because MySQL skips the rows that do not qualify for each constructed range. 使用这种策略可以减少被访问的行数,因为MySQL会跳过不符合每个构造范围的行。This Skip Scan access method is applicable under the following conditions:此跳过扫描访问方法适用于以下情况:
Table T has at least one compound index with key parts of the form ([A_1, ..., A_表T至少有一个复合索引,其中包含形式([A_1, ..., A_k
,] B_1, ..., B_m
, C [, D_1, ..., D_n
]). k
,] B_1, ..., B_m
, C [, D_1, ..., D_n
])的关键部分。Key parts A and D may be empty, but B and C must be nonempty.关键部分A和D可以是空的,但B和C必须是非空的。
The query references only one table.查询只引用一个表。
The query does not use 查询不使用GROUP BY
or DISTINCT
.GROUP BY
或DISTINCT
。
The query references only columns in the index.查询只引用索引中的列。
The predicates on A_1, ..., A_A_1,…,A_k
must be equality predicates and they must be constants. k
上的谓词必须是相等谓词,并且必须是常量。This includes the 这包括IN()
operator.IN()
运算符。
The query must be a conjunctive query; that is, an 查询必须是连接查询;即,与AND
of OR
conditions: OR
条件结合的AND
:(
cond1
(key_part1
) OR cond2
(key_part1
)) AND (cond1
(key_part2
) OR ...) AND ...
There must be a range condition on C.C上必须有一个范围条件。
Conditions on D columns are permitted. D柱上的条件是允许的。Conditions on D must be in conjunction with the range condition on C.D上的条件必须与C上的范围条件相结合。
Use of Skip Scan is indicated in 跳过扫描的使用在EXPLAIN
output as follows:EXPLAIN
输出中指示如下:
在Using index for skip scan
in the Extra
column indicates that the loose index Skip Scan access method is used.Extra
列中Using index for skip scan
表示使用松散索引跳过扫描访问方法。
If the index can be used for Skip Scan, the index should be visible in the 如果索引可用于跳过扫描,则索引应在possible_keys
column.possible_keys
列中可见。
Use of Skip Scan is indicated in optimizer trace output by a 跳过扫描的使用在优化器跟踪输出中由以下形式的"skip scan"
element of this form:"skip scan"
元素指示:
"skip_scan_range": { "type": "skip_scan", "index":index_used_for_skip_scan
, "key_parts_used_for_access": [key_parts_used_for_access
], "range": [range
] }
You may also see a 您还可以看到"best_skip_scan_summary"
element. "best_skip_scan_summary"
元素。If Skip Scan is chosen as the best range access variant, a 如果选择跳过扫描作为最佳范围访问变量,则会写入"chosen_range_access_summary"
is written. "chosen_range_access_summary"
。If Skip Scan is chosen as the overall best access method, a 如果选择跳过扫描作为总体最佳访问方法,则会出现"best_access_path"
element is present.best_access_path"
元素。
Use of Skip Scan is subject to the value of the 跳过扫描的使用取决于skip_scan
flag of the optimizer_switch
system variable. optimizer_switch
系统变量的skip_scan
标志的值。See Section 8.9.2, “Switchable Optimizations”. 参见第8.9.2节,“可切换优化”。By default, this flag is 默认情况下,此标志处于on
. on
状态。To disable it, set 要禁用它,请将skip_scan
to off
.skip_scan
设置为off
。
In addition to using the 除了使用optimizer_switch
system variable to control optimizer use of Skip Scan session-wide, MySQL supports optimizer hints to influence the optimizer on a per-statement basis. optimizer_switch
系统变量来控制优化器在整个跳过扫描会话范围内的使用之外,MySQL还支持优化器提示来影响每个语句的优化器。See Section 8.9.3, “Optimizer Hints”.请参阅第8.9.3节,“优化器提示”。
The optimizer is able to apply the range scan access method to queries of this form:优化器能够将范围扫描访问方法应用于以下形式的查询:
SELECT ... FROM t1 WHERE ( col_1, col_2 ) IN (( 'a', 'b' ), ( 'c', 'd' ));
Previously, for range scans to be used, it was necessary to write the query as:以前,要使用范围扫描,必须将查询编写为:
SELECT ... FROM t1 WHERE ( col_1 = 'a' AND col_2 = 'b' ) OR ( col_1 = 'c' AND col_2 = 'd' );
For the optimizer to use a range scan, queries must satisfy these conditions:要使优化器使用范围扫描,查询必须满足以下条件:
Only 只使用IN()
predicates are used, not NOT IN()
.IN()
谓词,不使用NOT IN()
。
On the left side of the 在IN()
predicate, the row constructor contains only column references.IN()
谓词的左侧,行构造函数只包含列引用。
On the right side of the 在IN()
predicate, row constructors contain only runtime constants, which are either literals or local column references that are bound to constants during execution.IN()
谓词的右侧,行构造函数只包含运行时常量,这些常量是在执行期间绑定到常量的文本或本地列引用。
On the right side of the 在IN()
predicate, there is more than one row constructor.IN()
谓词的右侧,有多个行构造函数。
For more information about the optimizer and row constructors, see Section 8.2.1.22, “Row Constructor Expression Optimization”有关优化器和行构造函数的更多信息,请参阅第8.2.1.22节,“行构造函数表达式优化”
To control the memory available to the range optimizer, use the 要控制范围优化器可用的内存,请使用range_optimizer_max_mem_size
system variable:range_optimizer_max_mem_size
系统变量:
A value of 0 means “no limit.”值为0表示“无限制”
With a value greater than 0, the optimizer tracks the memory consumed when considering the range access method. 当值大于0时,优化器将跟踪在考虑范围访问方法时所消耗的内存。If the specified limit is about to be exceeded, the range access method is abandoned and other methods, including a full table scan, are considered instead. 如果即将超过指定的限制,则放弃范围访问方法,而考虑其他方法,包括全表扫描。This could be less optimal. 这可能不太理想。If this happens, the following warning occurs (where 如果发生这种情况,将出现以下警告(其中N
is the current range_optimizer_max_mem_size
value):N
是当前range_optimizer_max_mem_size
值):
Warning 3170 Memory capacity of N
bytes for
'range_optimizer_max_mem_size' exceeded. Range
optimization was not done for this query.
For 对于UPDATE
and DELETE
statements, if the optimizer falls back to a full table scan and the sql_safe_updates
system variable is enabled, an error occurs rather than a warning because, in effect, no key is used to determine which rows to modify. UPDATE
语句和DELETE
语句,如果优化器退回到完整表扫描,并且启用了sql_safe_updates
系统变量,则会发生错误而不是警告,因为实际上没有使用键来确定要修改的行。For more information, see Using Safe-Updates Mode (--safe-updates).有关更多信息,请参阅使用安全更新模式(--Safe Updates)。
For individual queries that exceed the available range optimization memory and for which the optimizer falls back to less optimal plans, increasing the 对于超出可用范围优化内存且优化器退回到较低优化计划的单个查询,增加range_optimizer_max_mem_size
value may improve performance.range_optimizer_max_mem_size
值可能会提高性能。
To estimate the amount of memory needed to process a range expression, use these guidelines:要估计处理范围表达式所需的内存量,请使用以下准则:
For a simple query such as the following, where there is one candidate key for the range access method, each predicate combined with 对于一个简单的查询,例如下面的查询,其中范围访问方法有一个候选键,每个结合OR
uses approximately 230 bytes:OR
的谓词使用大约230字节:
SELECT COUNT(*) FROM t
WHERE a=1 OR a=2 OR a=3 OR .. . a=N
;
Similarly for a query such as the following, each predicate combined with 类似地,对于以下查询,每个结合AND
uses approximately 125 bytes:AND
的谓词使用大约125字节:
SELECT COUNT(*) FROM t
WHERE a=1 AND b=1 AND c=1 ... N
;
For a query with 对于具有IN()
predicates:IN()
谓词的查询:
SELECT COUNT(*) FROM t WHERE a IN (1,2, ...,M
) AND b IN (1,2, ...,N
);
Each literal value in an IN()
list counts as a predicate combined with OR
. IN()
列表中的每个文本值都算作与OR
组合的谓词。If there are two 如果有两个IN()
lists, the number of predicates combined with OR
is the product of the number of literal values in each list. IN()
列表,则与OR
组合的谓词数是每个列表中文字值数的乘积。Thus, the number of predicates combined with 因此,在前面的例子中与OR
in the preceding case is M
× N
.OR
结合的谓词的数目是m
× n
。