深入理解 index merge 是使用索引进行优化的重要基础之一。

index merge
       当where谓词中存在多个条件(或者join)涉及到多个字段,它们之间进行 AND 或者 OR,那么此时就有可能会使用到 index merge 技术。简单的说,index merge 技术其实就是:对多个索引分别进行条件扫描,然后将它们各自的结果进行合并(intersect/union)。
       MySQL5.0之前,一个表一次只能使用一个索引,无法同时使用多个索引分别进行条件扫描。但是从5.1开始,引入了 index merge 优化技术,对同一个表可以使用多个索引分别进行条件扫描。

index merge: 同一个表的多个索引的范围扫描可以对结果进行合并,合并方式分为三种:union, intersection, 以及它们的组合sort_union(先内部intersect然后在外面union)。

  • index merge 之 intersect

The Index Merge intersection algorithm performs simultaneous scans on all used indexes and produces the intersection of row sequences that it receives from the merged index scans. (intersect merge运行方式:多个索引同时扫描,然后结果取交集)

If one of the merged conditions is a condition over a primary key of an InnoDB table, it is not used for row retrieval, but is used to filter out rows retrieved using other conditions.

简单而言,index intersect merge就是多个索引条件扫描得到的结果进行交集运算。显然在多个索引提交之间是 AND 运算时,才会出现 index intersect merge. 下面两种where条件或者它们的组合时会进行 index intersect merge:
       1) 条件使用到复合索引中的所有字段或者左前缀字段(对单字段索引也适用)
           key_part1=const1 AND key_part2=const2 ... AND key_partN=constN
       2) 主键上的任何范围条件
           例子:
          SELECT * FROM innodb_table WHERE primary_key < 10 AND key_col1=20;
          SELECT * FROM tbl_name WHERE (key1_part1=1 AND key1_part2=2) AND key2=2;
       上面只说到复合索引,但是其实单字段索引显然也是一样的。比如 select * from tab where key1=xx and key2 =xxx; 也是有可能进行index intersect merge的。另外上面两种情况的 AND 组合也一样可能会进行 index intersect merge.

If all columns used in the query are covered by the used indexes, full table rows are not retrieved (EXPLAIN output contains Using index in Extra field in this case). Here is an example of such a query:(索引覆盖扫描,无需回表)

If the used indexes do not cover all columns used in the query, full rows are retrieved only when the range conditions for all used keys are satisfied.(索引不能覆盖,则对满足条件的再进行回表)  eg:SELECT COUNT(*) FROM t1 WHERE key1=1 AND key2=1;

  • index merge 之 union

简单而言,index uion merge就是多个索引条件扫描,对得到的结果进行并集运算,显然是多个条件之间进行的是 OR 运算。

下面几种类型的 where 条件,以及他们的组合可能会使用到 index union merge算法:

  1. 条件使用到复合索引中的所有字段或者左前缀字段(对单字段索引也适用)
  2. 主键上的任何范围条件
  3. 任何符合 index intersect merge 的where条件;

上面三种 where 条件进行 OR 运算时,可能会使用 index union merge算法。

例子:

SELECT * FROM t1 WHERE key1=1 OR key2=2 OR key3=3;
        SELECT * FROM innodb_table WHERE (key1=1 AND key2=2) OR (key3='foo' AND key4='bar') AND key5=5;

  • index merge 之 sort_union

This access algorithm is employed when the WHERE clause was converted to several range conditions combined by OR, but for which the Index Merge method union algorithm is not applicable.(多个条件扫描进行 OR 运算,但是不符合 index union merge算法的,此时可能会使用 sort_union算法)

The difference between the sort-union algorithm and the union algorithm is that the sort-union algorithm must first fetch row IDs for all rows and sort them before returning any rows.(sort-union合并算法和union合并算法的不同点,在于返回结果之前是否排序)

  • index merge的局限

1)If your query has a complex WHERE clause with deep AND/OR nesting and MySQL does not choose the optimal plan, try distributing terms using the following identity laws(如果我们的条件比较复杂,用到多个 and / or 条件运算,而MySQL没有使用最优的执行计划,那么可以使用下面的两个等式将条件进行转换一下)
           (x AND y) OR z = (x OR z) AND (y OR z)
           (x OR y) AND z = (x AND z) OR (y AND z)
      2)Index Merge is not applicable to full-text indexes. We plan to extend it to cover these in a future MySQL release.(全文索引没有index merge)
      3)Before MySQL 5.6.6, if a range scan is possible on some key, the optimizer will not consider using Index Merge Union or Index Merge Sort-Union algorithms. For example, consider this query:
           SELECT * FROM t1 WHERE (goodkey1 < 10 OR goodkey2 < 20) AND badkey < 30;
           For this query, two plans are possible:
           An Index Merge scan using the (goodkey1 < 10 OR goodkey2 < 20) condition.
           A range scan using the badkey < 30 condition.
           However, the optimizer considers only the second plan.
           这一点对以低版本的MySQL是一个很大的缺陷。就是如果where条件中有 >, <, >=, <=等条件,那么优化器不会使用 index merge,而且还会忽略其他的索引,不会使用它们,哪怕他们的选择性更优。

  • 对 index merge 的进一步优化

index merge使得我们可以使用到多个索引同时进行扫描,然后将结果进行合并。听起来好像是很好的功能,但是如果出现了 index intersect merge,那么一般同时也意味着我们的索引建立得不太合理,因为 index intersect merge 是可以通过建立 复合索引进行更一步优化的。

比如下面的select:

SELECT * FROM t1 WHERE key1=1 AND key2=2 AND key3=3;
       显然我们是可以在这三个字段上建立一个复合索引来进行优化的,这样就只需要扫描一个索引一次,而不是对三个所以分别扫描一次。

  • 复合索引的最左前缀原则

对复合索引的非最左前缀字段进行 OR 运算,是无法使用到复合索引的。比如:

SELECT * FROM tbl_name WHERE (key_col1 > 10 OR key_col2 = 20) AND nonkey_col=30;
       原因是,MySQL中的索引,使用的是B+tree, 也就是说他是:先按照复合索引的 第一个字段的大小来排序,插入到 B+tree 中的,当第一个字段值相同时,在按照第二个字段的值比较来插入的。那么如果我们需要对: OR key_col2 = 20 这样的条件也使用复合索引,那么该怎么操作呢?应该要对复合索引进行全扫描,找出所有 key_col2 =20 的项,然后还要回表去判断 nonkey_col=30,显然代价太大了。所以一般而言 OR key_col2 = 20 这样的条件是无法使用到复合索引的。如果一定要使用索引,那么可以在 col2 上单独建立一个索引。

创建复合索引,哪个字段放在最前面,并不需要按照where谓词出现的顺序来建立,而是根据哪个字段经常出现在where条件中以及字段的选择性好坏来判断。

MySQL index merge的更多相关文章

  1. MySQL Index Merge Optimization

    Index Merge用在通过一些range scans得到检索数据行和合并成一个整体.合并可以通过 unions,intersections,或者unions-intersection运用在底层的扫 ...

  2. MySQL 优化之 index merge(索引合并)

    深入理解 index merge 是使用索引进行优化的重要基础之一.理解了 index merge 技术,我们才知道应该如何在表上建立索引. 1. 为什么会有index merge 我们的 where ...

  3. MySQL 查询优化之 Index Merge

    MySQL 查询优化之 Index Merge Index Merge Intersection 访问算法 Index Merge Union 访问算法 Index Merge Sort-Union ...

  4. MySQL中Index Merge简介

    索引合并优化 官网翻译 MySQL5.7文档 索引合并是为了减少几个范围(type中的range类型:range can be used when a key column is compared t ...

  5. index merge的一次优化

    手机微博4040端口SQL优化 现象 某端口常态化延迟,通过使用pt-query-digest发现主要由于一条count(*)语句引发,具体如下: # .5s .58M rss, .84M vsz # ...

  6. 8.2.1.4 Index Merge Optimization 索引合并优化:

    8.2.1.4 Index Merge Optimization 索引合并优化: 索引合并方法是用于检索记录 使用多个 范围扫描和合并它们的结果集到一起 mysql> show index fr ...

  7. MySQL Index详解

    FROM:http://blog.csdn.net/tianmo2010/article/details/7930482 ①MySQL Index 一.SHOW INDEX会返回以下字段 1.Tabl ...

  8. 【MySQL】Merge Index导致死锁

    水稻:最近有个朋友生产环境出现MySQL死锁问题,一听是死锁,那必须去看看啊,于是饶(si)有(qu)兴(huo)致(lai)的研究了好几天 菜瓜:MySQL死锁,赶紧分享一下 水稻:能否先让我装完X ...

  9. Mysql 之 MERGE 存储引擎

    MERGE 存储引擎把一组 MyISAM 数据表当做一个逻辑单元来对待,让我们可以同时对他们进行查询.构成一个 MERGE 数据表结构的各成员 MyISAM 数据表必须具有完全一样的表结构.每一个成员 ...

随机推荐

  1. 六顶思维帽的思考,敏捷开发?——By Me

    人类的思维可以分为很多种,其中按照思维的深度和广度的侧重,可以分为纵向思维和横向思维两种: 简单的来说,“六顶思维帽”可以简单的理解为下图所示: 如何使用这种思维方式呢?举个例子:先输入一个待讨论的事 ...

  2. 利用EasySQLMAIL实现自动数据提取和邮件发送功能 (1)

    转自:http://blog.sina.com.cn/s/blog_1549483b70102wioy.html 最近几个月每天都在发通报.过程很繁琐,动作很机械,整个人就是一部机器,执行SQL,填E ...

  3. Oracle 11g数据库详解

    常见异常: ORA-14025:不能为实体化视图或实体化视图日志指定PARTITION ORA-14026:PARTITION和CLUSTER子句互相排斥 ORA-14027:仅可以指定一个PARTI ...

  4. Selenium WebDriver 工作原理

    WebDriver与之前Selenium的js注入实现不同:Selenium通过JS来定位元素处理元素(基本上所有元素都可以定位到)WebDriver通过WebDriver API定位处理元素:通过浏 ...

  5. Django-form进阶+详细版

    Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 一.创建Form类 #!/usr/bin/en ...

  6. [笔记]使用Go语言Redigo包在Docker容器内连接Redis容器的方法

    Docker容器之间的连接可以带来不少方便,下面记录下如何在自己容器内通过环境变量连接与之连接的Redis容器的方法. 先起一个Redis的Docker容器,命名为 redis,再起一个自己的Dock ...

  7. flume hdfs配置详解

    flume采集中HDFS参数解析 就是个备忘录,方便以后直接查阅,不用再网上找了!!!! 配置解析 Flume中的HDFS Sink应该是非常常用的,其中的配置参数也比较多,在这里记录备忘一下. ch ...

  8. jQuery/CSS3 图片边框线条变换动画

    在线演示 本地下载

  9. 分布式集群Session原理及实现共享

    1.什么是Session/Cookie? 用户使用网站的服务,基本上需要浏览器与Web服务器的多次交互.HTTP协议本身是无状态的,当用户的第一次访问请求结束后,后端服务器就无法知道下一次来访问的还是 ...

  10. float 为什么可以表示很大的整数

    1.float型:单精度浮点数在机内占4个字节,用32位二进制描述(注意:计算机中1个字节=8位). 2.浮点数在机内用指数型式表示,分解为:数符,尾数,指数符,指数四部分. 3.可以算出float型 ...