View Code

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');

对于key1索引的提取过程如下:

1、执行原来的WHERE从句:

View Code

(key1 < 'abc' AND (key1 LIKE 'abcde%' OR key1 LIKE '%b')) OR (key1 < 'bar' AND nonkey = 4) OR (key1 < 'uux' AND key1 > 'z')

2、删除掉nonkey=4和Key LIKE '%b' ,因为他们不能被用来进行范围扫描。删除他们并用TRUE来替代,所以我们在进行范围扫描的时候,不会错过任何一个匹配的行记录,用TRUE替换掉之后,就是:

(key1 < 'abc' AND (key1 LIKE 'abcde%' OR TRUE)) OR (key1 < 'bar' AND TRUE) OR(key1 < 'uux' AND key1 > 'z')

3、折叠总是为真或者为假的条件

(key1 LIKE 'abcde%' OR TRUE)总是真

(key1 < 'uux' AND key1 > 'z') 总是假

使用常量替换掉这些条件,就是

(key1 < 'abc' AND TRUE) OR (key1 < 'bar' AND TRUE) OR (FALSE)

删除掉不必要的TRUE和FALSE常量,就会得到

(key1 < 'abc') OR (key1 < 'bar')

4、组合重叠的区域到一个区域,最终被用来范围查询的条件如下:

(key1 < 'bar')

一般来说(正如上面的例子中所阐述的那样),用来范围查询的条件在执行时并不像WHERE从句的那么严格,MySQL会使用另外的判断会过滤掉那些满足范围查询条件但却不满足WHERE条件的行记录。

范围查询提取算法可以处理嵌套了任意深度的AND/OR结构,而且他的输出不依赖于WHERE从句中出现的条件的顺序。

目前,MySQL不支持合并多个索引产生的范围查询的多个区间的方法。要解决此限制,您可以使用相同的SELECT语句,然后进行UNION,除非您使用不同的SELECT语句。

多列索引的范围查询优化

多列索引的范围查询是对单列索引范围查询的扩展,一个多列索引的范围查询将索引行限制在一个或者多个“键元组间隔”。“键元组间隔”通过一组关键元组,使用索引的顺序 来定义。

举例来说,考虑一个多列索引,这个索引被定义为:key1(key_part1,key_part2,key_part3),下面列出了一组按照key_part1为顺序的关键元组。

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'

条件key_part1 = 1 定义了下面这个区间:

这个区间覆盖了上述数据集中的第4、5、6行记录,这个区间可以使用范围查询。相比之下,条件key_part3 = 'abc' 没有定义一个单独的区间,而且不能使用范围查询。下面的描述展示了多列索引的范围条件使用的更多细节。

对于HASH索引,每个区间包含恒定的值才能使用,这就意味着区间只能被使用在下面的这种形式:

key_part1 cmp const1

AND key_part2 cmp const2

AND ...

AND key_partN cmp constN;

这里,const1,const2,....都是常量,cmp是任意一个=,<=>, 或者条件覆盖了所有的索引列,(这就是说,有N个条件,每一个都对应N列索引的一个列),举例来说,下面的就是一个3列的HASH索引的范围条件。

对于一个B+树索引,一个区间通过AND关键字连接即可可用,每个条件使用=,<=>,IS NULL,>,=,<=,!=,<>,BETWEEN, 或者但是模式不能以通配符开始)等符号来比较一个索引列和一个常量值。只要能通过一个单独的列元组能决定一个完整的行记录,而这个行记录匹配这个条件(或者两个区间如果<>或者!=使用),这个区间就会使用。

当比较操作符是=, <=>, 或者>,=,<=,!=,<>,BETWEEN, 或者优化器将不会这么做。对于下面的表达式,优化器会使用第一个比较式的‘=’,也会使用第二个比较式的‘>=’ ,但是不会考虑更多列,而且从来不会使用第三个表达式去构造区间。

key_part1 = 'foo' AND key_part2 >= 10 AND key_part3 > 10

单独的区间就是:

('foo',10,-inf) < (key_part1,key_part2,key_part3) < ('foo',+inf,+inf)

这就是说创建的区间包含的行记录可能会多于初始的条件所对应的行记录,比如,前面的区间包括('foo', 11, 0), 但是却不满足原始的条件。如果条件使用OR覆盖了一组行记录,那么这些查询将会包含这些行记录的并集。如果条件使用AND,他们就会产生这些区间的交集,比如说,下面这种使用了覆盖两个列的索引:

(key_part1 = 1 AND key_part2 < 2) OR (key_part1 > 5)

那么这个区间就是:

(1,-inf) < (key_part1,key_part2) < (1,2)

(5,-inf) < (key_part1,key_part2)

在这个例子中,第一行会使用一个键列来确定区间的左边界,使用两个键列来确定右边界。而第二行仅仅使用一个 键列。在执行计划的输出中,会使用key_len列来说明使用的键前缀的最大长度。在某种程度上 ,key_len列会说明使用的键列,但是可能不是你想要的。假设key_part1和key_part2有可能为NULL,那么在下面这种情况下,key_len列会显示两个键的长度:

key_part1 >= 1 AND key_part2 < 2

但是,实际上,这个条件会被转化为:

key_part1 >= 1 AND key_part2 IS NOT NULL

多值比较的等值范围优化

考虑这些表达式,col_name是索引列:

col_name IN(val1, ..., valN)

col_name = val1 OR ... OR col_name = valN

如果col_name和括号中的任何一个值相等,那么这个表达式就为真,这些都是等值范围比较(“范围”是个单值),优化器使用以下方法来估算读取满足条件的行记录所付出的的代价:

1、如果col_name是个唯一索引列,那么每个范围的估算都是1,因为对于给定值,最多只有一个行记录满足条件;

2、否则,优化器会使用索引或者索引统计特征对每个范围的行记录数进行估算

使用index dives,优化器会在范围的末端使用dive,而且使用范围的行记录数估算。

举例来说,表达式col_nameIN (10, 20, 30)有三个等值的范围,优化器会对每个范围进行两次dives来估算,每一对的dives产生给定值的相应的行记录数的估算。

index dives 提供了精确的行估算,但是当表达式中需要比较的值的数量增加时,优化器会使用更长的时间来估算,而使用索引特征虽然精确度低一些,但是在估算更大值得列表时会更快一些。

当优化器需要从一个估算策略转换到另一个时,可以使用eq_range_index_dive_limit 这个系统变量进行配置。如果禁用索引特征,总是使用index dives ,可以设置eq_range_index_dive_limit为0。如果允许使用比较的index dives增长到N 等值范围,可以设置eq_range_index_dive_limit为N+1;

eq_range_index_dive_limit 是MySQL5.6中的变量,在5.6.5之前,优化器一直使用index dives,这等价于eq_range_index_dive_limit= 0;

为了获得更好的估算,您可以使用ANALYZE TABLE.,更新索引统计特征。

mysql5.6 in走索引吗_MySQL5.6 单列、多列索引以及IN语句的优化(翻译)相关推荐

  1. SQL Server 索引和表体系结构(包含列索引)

    包含列索引 概述 包含列索引也是非聚集索引,索引结构跟聚集索引结构是一样,有一点不同的地方就是包含列索引的非键列只存储在叶子节点:包含列索引的列分为键列和非键列,所谓的非键列就是INCLUDE中包含的 ...

  2. pandas使用pivot_table函数构建透视表:index指定聚合的行索引、columns指定聚合的列索引、aggfunc使用列表指定多个聚合函数(形成复合列索引)

    pandas使用pivot_table函数构建透视表:index参数指定聚合的行索引.columns参数指定聚合的列索引.values参数指定需要进行聚合的数值数据列.aggfunc使用列表指定多个聚 ...

  3. java报错无效的列索引,java.sql.SQLException: 无效的列索引

    java.sql.SQLException: 无效的列索引 "无效的列索引"其实是个低级的错误,原因无非几个: 1.sql串的?号数目和提供的变量数目不一致: 例如:jdbcTem ...

  4. mysql优化-----多列索引的左前缀规则

    索引优化策略1:索引类型1.1B-tree索引 关注的是:Btree索引的左前缀匹配规则,索引在排序和分组上发挥的作用.注:名叫btree索引,大的方面看都用的二叉树.平衡树.但具体的实现上,各引擎稍 ...

  5. mysql单列索引和多列索引_mysql索引类型 normal, unique, full text

    问题1:mysql索引类型normal,unique,full text的区别是什么? normal:表示普通索引 unique:表示唯一的,不允许重复的索引,如果该字段信息保证不会重复例如身份证号用 ...

  6. mysql三个字段最优索引_mysql 多列索引优化

    Mysql所有的列都可以使用索引,.对相关列使用索引是提高SELECT操作性能的最佳途径.根据存储引擎定义每个表的最大索引数和最大索引长度.所有存储引擎支持每个表至少16个索引,总索引长度至少256字 ...

  7. mysql多列索引用处_MySQL索引使用说明(单列索引和多列索引)

    1. 单列索引 在性能优化过程中,选择在哪些列上创建索引是最重要的步骤之一.可以考虑使用索引的主要有两种类型的列:在Where子句中出现的列,在join子句中出现的列.请看下面这个查询: 这个查询与前 ...

  8. mysql聚集索引可以多列吗_MySQL使用单列索引和多列索引

    讨论MySQL选择索引时单列单列索引和多列索引使用,以及多列索引的最左前缀原则. 1. 单列索引 在性能优化过程中,选择在哪些列上创建索引是最重要的步骤之一.可以考虑使用索引的主要有两种类型的列:在W ...

  9. mysql百万数据根据索引查询_mysql创建多列索引查询百万表数据的性能优化经验分享...

    最近发现最代码网站中的收到的评论,提到我的,心情被赞的查询异常缓慢,通过nginx日志发现响应时间快的在5s,慢的有13s,终于忍无可忍花时间来解决了. 执行explain之后的截图如下: 可以看到p ...

最新文章

  1. 碉堡的小程序:用 Python 制作演示迷宫算法的 gif 动画
  2. Javascript--键盘事件的组合使用
  3. 普华永道:AI规模化应用,基础知识先行
  4. Linux 上与系统负载有关的命令
  5. IPC$概念及入侵方式研究
  6. LeetCode 364. 加权嵌套序列和 II(重复叠加)
  7. HD1394 Minimum Inversion Number
  8. oracle中dual最多存多大_ORACLE中dual用法详解
  9. Linux PXE详解
  10. 三星获得加州自动驾驶测试许可,与Google苹果正面刚
  11. windows游戏编程:球球大作战(吃鸡版)源码
  12. kube-scheduler源码分析(三)之 scheduleOne
  13. unity遇到的问题
  14. 不可不知的设计师接活报价公式
  15. TSRC挑战赛:WAF之SQL注入绕过挑战实录
  16. R语言单因素方差分析(附代码)
  17. 手机录制连续点赞并周期执行(免代码)
  18. 化妆品用植物干细胞的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  19. 配制ubuntu - 使用大全整理 (其中有转载内容,如果有您的文章,请与我联系,我将加入你的名称)
  20. 初学者都能看懂的 Spring 源码之依赖注入(DI)源码分析

热门文章

  1. 构建之法第4.17章读书笔记
  2. 【codeforces 799A】Carrot Cakes
  3. 算法笔记_132:最大流量问题(Java)
  4. VC消息传递(对话框间传递参数)
  5. PS抠图神器: KnockOut 2.0安装汉化和使用教程
  6. String.Format数字格式化输出 {0:N2} {0:D2} {0:C2}
  7. 大家一起做训练 第一场 A Next Test
  8. 精通RPM之--制作篇(rpmbuild)
  9. linux加protobuf变量环境,protobuf简单介绍和ubuntu 16.04环境下安装教程
  10. python爬取京东商品信息代码_Python利用Xpath选择器爬取京东网商品信息