MySQL Range Optimization
8.2.1.3 Range Optimization
MYSQL的Range Optimization的目的还是尽可能的使用索引
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. It can be used for a single-part or multiple-part index. The following sections give descriptions of conditions under which the optimizer uses range access.
8.2.1.3.1 The Range Access Method for Single-Part Indexes
针对单一索引
For a single-part index, index value intervals can be conveniently represented by corresponding conditions in theWHERE clause, so we speak of range conditions rather than “intervals.”
The definition of a range condition for a single-part index is as follows:
For both
BTREEandHASHindexes, comparison of a key part with a constant value is a range condition when using the=,<=>,IN(),IS NULL, orIS NOT NULLoperators.
Additionally, for
BTREEindexes, comparison of a key part with a constant value is a range condition when using the>,<,>=,<=,BETWEEN,!=, or<>operators, orLIKEcomparisons if the argument toLIKEis a constant string that does not start with a wildcard character.For all types of indexes, multiple range conditions combined with
ORorANDform a range condition.
对于BTREE索引和HASH索引来说,索引的范围优化基本上只适用于等值查询。譬如=, <=>, IN(), IS NULL, IS NOT NULL操作符。
相对于HASH索引,BTREE索引同样支持非等值查询,譬如>, <, >=, <=, BETWEEN, !=, <>和LIKE(注意,like的常量值不能以通配符开头)
“Constant value” in the preceding descriptions means one of the following:
A constant from the query string
The result of an uncorrelated subquery
Any expression composed entirely from subexpressions of the preceding types
常量值一般指三种:查询条件为常量,const表或system表,非关联子查询的结果
其中,const表指的是最多只有一个匹配行,譬如基于主键的查询:
SELECT * FROM tbl_name WHERE primary_key=1; SELECT * FROM tbl_name
WHERE primary_key_part1=1 AND primary_key_part2=2;
Here are some examples of queries with range conditions in the WHERE clause:
SELECT * FROM t1
WHEREkey_col> 1
ANDkey_col< 10; SELECT * FROM t1
WHEREkey_col= 1
ORkey_colIN (15,18,20); SELECT * FROM t1
WHEREkey_colLIKE 'ab%'
ORkey_colBETWEEN 'bar' AND 'foo';
Some nonconstant values may be converted to constants during the constant propagation phase.
以下是MySQL提取范围条件的思路,并不是等价变换,目的还是在于尽可能的使用索引的范围查询,包括后面的红色部分也提到,这样变换后的条件会没有原来的条件严格,MySQL这样做的目的在于利用索引过滤掉很大一部分记录,然后再对剩下的记录进行额外的筛选。
MySQL tries to extract range conditions from the WHERE clause for each of the possible indexes. 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:
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:
Start with original
WHEREclause:(key1 < 'abc' AND (key1 LIKE 'abcde%' OR key1 LIKE '%b')) OR
(key1 < 'bar' AND nonkey = 4) OR
(key1 < 'uux' AND key1 > 'z')Remove
nonkey = 4andkey1 LIKE '%b'because they cannot be used for a range scan. The correct way to remove them is to replace them withTRUE, so that we do not miss any matching rows when doing the range scan. Having replaced them withTRUE, we get:(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(key1 < 'uux' AND key1 > 'z')is always false
Replacing these conditions with constants, we get:
(key1 < 'abc' AND TRUE) OR (key1 < 'bar' AND TRUE) OR (FALSE)
Removing unnecessary
TRUEandFALSEconstants, we obtain:(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. MySQL performs an additional check to filter out rows that satisfy the range condition but not the full WHERE clause.
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.
MySQL does not support merging multiple ranges for the range access method for spatial indexes. 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.
8.2.1.3.2 The Range Access Method for Multiple-Part Indexes
针对复合索引
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)
key_part1key_part2key_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
(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.
By contrast, the condition does not define a single interval and cannot be used by the range access method.key_part3 = 'abc'
如果使用前导列key_part1,则可以使用索引,如果直接使用key_part3,则不能使用索引。
The following descriptions indicate how range conditions work for multiple-part indexes in greater detail.
For
HASHindexes, each interval containing identical values can be used. This means that the interval can be produced only for conditions in the following form:key_part1cmpconst1
ANDkey_part2cmpconst2
AND ...
ANDkey_partNcmpconstN;Here,
const1,const2, … are constants,cmpis one of the=,<=>, orIS NULLcomparison operators, and the conditions cover all index parts. (That is, there areNconditions, one for each part of anN-part index.) For example, the following is a range condition for a three-partHASHindex:key_part1= 1 ANDkey_part2IS NULL ANDkey_part3= 'foo'For the definition of what is considered to be a constant, see Section 8.2.1.3.1, “The Range Access Method for Single-Part Indexes”.
For a
BTREEindex, an interval might be usable for conditions combined withAND, where each condition compares a key part with a constant value using=,<=>,IS NULL,>,<,>=,<=,!=,<>,BETWEEN, orLIKE '(wherepattern''does not start with a wildcard). 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 ifpattern'<>or!=is used).The optimizer attempts to use additional key parts to determine the interval as long as the comparison operator is
=,<=>, orIS NULL. If the operator is>,<,>=,<=,!=,<>,BETWEEN, orLIKE, the optimizer uses it but considers no more key parts. 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> 10The 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.
对于BTREE的复合索引来说,一旦其中的一个索引列使用了非等值查询,则在其后的索引列将无法继续使用索引。
譬如:key_part1 = 'foo' AND key_part2 >= 10 AND key_part3 > 10
因为第二个索引列key_part2使用了非等值查询,则第三个索引列key_part3无法使用索引。
所以,它的变换形式为('foo',10,-inf) < (key_part1,key_part2,key_part3) < ('foo',+inf,+inf),
而不是('foo',10,10) < (key_part1,key_part2,key_part3) < ('foo',+inf,+inf)
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. If the conditions are combined withAND, they form a condition that covers a set of rows contained within the intersection of their intervals. 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_lencolumn in theEXPLAINoutput indicates the maximum length of the key prefix used.In some cases,
key_lenmay indicate that a key part was used, but that might be not what you would expect. Suppose thatkey_part1andkey_part2can beNULL. Then thekey_lencolumn displays two key part lengths for the following condition:key_part1>= 1 ANDkey_part2< 2But, in fact, the condition is converted to this:
key_part1>= 1 ANDkey_part2IS NOT NULL
Section 8.2.1.3.1, “The Range Access Method for Single-Part Indexes”, describes how optimizations are performed to combine or eliminate intervals for range conditions on a single-part index. Analogous steps are performed for range conditions on multiple-part indexes.
8.2.1.3.3 Equality Range Optimization of Many-Valued Comparisons
Consider these expressions, where col_name is an indexed column:
col_nameIN(val1, ...,valN)
col_name=val1OR ... ORcol_name=valN
Each expression is true if col_name is equal to any of several values. 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.Otherwise, the optimizer can estimate the row count for each range using dives into the index or index statistics.
如果是唯一索引,则每一个range的对应的row为1。如果不是唯一索引,优化器有两个方式来评估每个range对应的行数:index dives和index statistics。其中,index dives能提供更精确的估计,但是成本会比较高,index statistics速度较快,但精度没有index dives高,选择哪种方式由eq_range_index_dive_limit决定,5.7.3之前默认值为10,指的是当range的个数小于或等于9时,MySQL默认会选择index dives,超过9个,则选择index statistics。
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. Each pair of dives yields an estimate of the number of rows that have the given value.col_name IN (10, 20, 30)
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. To disable use of statistics and always use index dives, set eq_range_index_dive_limit to 0. To permit use of index dives for comparisons of up to Nequality ranges, set eq_range_index_dive_limit to N + 1.
To update table index statistics for best estimates, use ANALYZE TABLE.
8.2.1.3.4 Range Optimization of Row Constructor Expressions
As of MySQL 5.7.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 for the query to be written 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
INpredicates can be used, notNOT IN.There may only be column references in the row constructor on the
INpredicate's left hand side.There must be more than one row constructor on the
INpredicate's right hand side.Row constructors on the
INpredicate's right hand side must contain only runtime constants, which are either literals or local column references that are bound to constants during execution.
Compared to similar queries executed before MySQL 5.7.3, EXPLAIN output for applicable queries changes from full table or index scan to range scan. Changes are also visible by checking the values of theHandler_read_first, Handler_read_key, and Handler_read_next status variables.
MySQL Range Optimization的更多相关文章
- 8.2.1.3 Range Optimization
8.2.1.3 Range Optimization 范围访问方法使用一个单个的索引来检索表记录的自己,包含在一个或者索引值区间. 它可以用于一个单独的部分或者多个部分的索引,下面章节给出了一个详细的 ...
- MySQL RANGE分区
200 ? "200px" : this.width)!important;} --> 介绍 RANGE分区基于一个给定的连续区间范围,早期版本RANGE主要是基于整数的分区 ...
- MYSQL DISTINCT Optimization
在很多情况下,Distinct和order by的组合需要建立一个内存临时表. 因为distinct关键字可能利用group by,所以了解下mysql如何处理group by有帮助. distin ...
- MYSQL Range
http://www.orczhou.com/index.php/2012/12/mysql-source-code-optimizer-range-and-ref/ http://www.orczh ...
- Mysql Index、B Tree、B+ Tree、SQL Optimization
catalog . 引言 . Mysql索引 . Mysql B/B+ Tree . Mysql SQL Optimization . MySQL Query Execution Process 1. ...
- 看懂mysql执行计划--官方文档
原文地址:https://dev.mysql.com/doc/refman/5.7/en/explain-output.html 9.8.2 EXPLAIN Output Format The EXP ...
- windows 下使用 zip安装包安装MySQL 5.7
以下内容参考官方文档:http://dev.mysql.com/doc/refman/5.7/en/windows-start-command-line.html 解压缩zip到D:\mysql-5. ...
- MYSQL EXPLAIN执行计划命令详解(支持更新中)
本文来自我的github pages博客http://galengao.github.io/ 即www.gaohuirong.cn 摘要: 本篇是根据官网中的每个一点来翻译.举例.验证的:英语不好,所 ...
- MySQL--eq_range_index_dive_limit参数学习,MYSQL 5.6 5.7处理数据分布不均的问题
官方文档如下描述:This variable indicates the number of equality ranges in an equality comparison condition w ...
随机推荐
- 最常见的 20 个 jQuery 面试问题及答案
jQuery 面试问题和答案 JavaScript 是客户端脚本的标准语言,而 jQuery 使得编写 JavaScript 更加简单.你可以只用写几行的jQuery 代码就能实现更多的东西. 它是最 ...
- 不用css3的响应式img(按比例缩小图片)
有时候自己为了控制图片的响应式,按比例缩小放大图片,如果解决这个问题,用js吧,很麻烦.也会损失很大的加载运行速度等:所以我们还是用css来解决这个问题,用css来强制按比例压缩图片的高度或宽度,看代 ...
- java web(七)Cookie的简单使用
一.概述 测试 //1.创建一个Cookie对象 //Cookie cookie1=new Cookie("name","xrk"); //2.调用 ...
- JS 的事件委托机制
以前写上图所示的鼠标点击触发事件,一般都是用如下所示的给每一个表示列表的标签绑定一个click事件(演示用的例子的框架是React): 毫无疑问,这样是比较繁琐的,以后维护修改改个函数名什么的还不方便 ...
- 谢欣伦 - OpenDev原创教程 - 蓝牙设备查找类CxBthRemoteDeviceFind
这是一个精练的蓝牙设备查找类,类名.函数名和变量名均采用匈牙利命名法.小写的x代表我的姓氏首字母(谢欣伦),个人习惯而已,如有雷同,纯属巧合. CxBthRemoteDeviceFind的使用如下: ...
- Angular 1.x 升级到 Angular 2
原项目用ng1.5写的,现在改成ng2.0了,踩了不少坑,不过都忘记了. 如果你也正好要做这个工作,正好看到这个文章,不妨参考下. AngularJs 1.x -> 2.0 ng-repeat ...
- 高级sql注入
1. 避开输入过滤 输入过滤存在于外部和内部,外部属于web应用防火墙WAF,入侵防御系统IPS,入侵检测系统IDS,内部属于代码中对输入进行过滤 过滤select,insert等sql关键字和' | ...
- linux 用户管理(一)
本节内容梗概: 1.用户管理配置文件 2.用户管理命令 3.用户组管理命令 4.批量添加用户 5.用户授权 学东西先讲原理,所以从配置文件入手 1.用户信息文件 /etc/passwd 存放了用户的 ...
- 字节流与数据类型的相互转换---使用struct模块
字节流与数据类型的相互转换---使用struct模块 http://blog.csdn.net/Sunboy_2050/article/details/5974029 Python是一门非常简洁的语言 ...
- FMX保存JPG格式的Stream
刚刚看以前的笔记,估计这个用的人很少 var surf:TBitmapSurface; astream:TmemoryStream; begin surf:=TbitmapSurface.Create ...