美文网首页
MySQL优化:单索引的选择-index_merge

MySQL优化:单索引的选择-index_merge

作者: 南风nanfeng | 来源:发表于2018-10-12 15:44 被阅读96次
1.多个单索引

where子句后有多个查询条件,MySQL 5.1以前即使分别为每个条件建立索引,查询优化器也只会选择其中一个区分度高索引。笔者使用5.7.20,以下分析均基于此版本,不同版本的MySQL查询优化器给出的结果存在差异。下面开始分情况讨论MySQL查询优化器给出的索引结果。

  • where子句有两个个and条件分别且三个字段都有索引
mysql> EXPLAIN SELECT * FROM order t WHERE t.PrdModel = 'NX549J' AND t.Destination = '国内' AND t.OEM = '福盛创新'; 
+----+-------------+-------+------------+-------------+--------------------------+--------------+---------+------+------+----------+--------------------------------------------+
| id | select_type | table | partitions | type        | possible_keys            | key          | key_len | ref  | rows | filtered | Extra                                      |
+----+-------------+-------+------------+-------------+--------------------------+--------------+---------+------+------+----------+--------------------------------------------+
|  1 | SIMPLE      | t     | NULL       | index_merge | PrdModel,Destination,OEM | OEM,PrdModel | 153,153 | NULL |  614 |    50.00 | Using intersect(OEM,PrdModel); Using where |
+----+-------------+-------+------------+-------------+--------------------------+--------------+---------+------+------+----------+--------------------------------------------+
1 row in set, 1 warning (0.00 sec)


mysql> EXPLAIN SELECT * FROM order t WHERE t.PrdModel = 'NX549J' AND t.Destination = '国内' AND t.OEM = 'XXX技术有限公司'; 
+----+-------------+-------+------------+-------------+--------------------------+----------------------+---------+------+--------+----------+----------------------------------------------------+
| id | select_type | table | partitions | type        | possible_keys            | key                  | key_len | ref  | rows   | filtered | Extra                                              |
+----+-------------+-------+------------+-------------+--------------------------+----------------------+---------+------+--------+----------+----------------------------------------------------+
|  1 | SIMPLE      | t     | NULL       | index_merge | PrdModel,Destination,OEM | PrdModel,Destination | 153,153 | NULL | 320463 |    50.00 | Using intersect(PrdModel,Destination); Using where |
+----+-------------+-------+------------+-------------+--------------------------+----------------------+---------+------+--------+----------+----------------------------------------------------+
1 row in set, 1 warning (0.00 sec)

上例告诉我们实际的索引应用的index_merge,从三索引中选其二,奇怪的是每次选择结果并不是固定,第一次选择intersect(OEM,PrdModel),第二次选择intersect(PrdModel,Destination),尝试从区分度的角度查找原因,上例中三个索引的区分度分别为PrdModel(35045),Destination(22982),OEM(6195)。发现并不是简单的从区分度最高的索引选其二。那么索引合并选择的依据是什么呢?下面尝试从合并的复杂度方面比较:

索引/取值(记录数)/参数 PrdModel Destination OEM
intersect(PrdModel,Destination) NX549J(320147) 国内(8077050) XXX技术有限公司(5418791)
intersect(OEM,PrdModel) NX549J(320147) 国内(8077050) 福盛创新(11094)
intersect(PrdModel,Destination) NX549J(320147) 国内(8077050) is not null (21800063)
intersect(PrdModel,OEM) NX549J(320147) 国内(8077050) is null (537463)
  • 下面借助 官网文档 尝试理解index_merge的使用及选择机制。
    index_merge用在范围查询中,然后尝试合并多个索引检索的结果。笔者分别尝试两个、三个、四个条件的索引发现,index_merge只会选择其二合并索引,这一点官方没有特别说明。官方提到,index_merge只能扫描单表,不能跨表扫描。index merge: 同一个表的多个索引的范围扫描可以对结果进行合并,合并方式分为三种:union, intersection, 以及它们的组合(先内部intersect然后在外面union)。
    官方给出了四个例子。

SELECT * FROM tbl_name WHERE key1 = 10 OR key2 = 20;
SELECT * FROM tbl_name WHERE (key1 = 10 OR key2 = 20) AND non_key = 30;
SELECT * FROM t1, t2 WHERE (t1.key1 IN (1,2) OR t1.key2 LIKE 'value%') AND t2.key1 = t1.some_col;
SELECT * FROM t1, t2 WHERE t1.key1 = 1 AND (t2.key1 = t1.some_col OR t2.key2 = t1.some_col2);

经过测试,发现前三种能够得到index_merge,第四种情况看起来有点怪,两个连表条件,一个和一个查询条件,并不能使用index_merge。

  • 注意,下面是官方给出的建议,where后的条件写的比较复杂时,可能引起查询优化器的错误选择索引,应遵循以下原则:

(x AND y) OR z => (x OR z) AND (y OR z)
(x OR y) AND z => (x AND z) OR (y AND z)

  • index merge 之 intersect
    index intersect merge就是多个索引条件扫描得到的结果进行交集运算,结果如下:

key_part1=const1 AND key_part2=const2 ... AND key_partN=constN

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

key1 = 1 OR key2 = 2 OR key3 = 3;

  • index merge 之 Sort-Union
    简言之,就是需要先取交集再取并集,如多个OR的范围查询,可能有重复的记录,需要先取并集再取交集。

SELECT * FROM tbl_name WHERE key_col1 < 10 OR key_col2 < 20;

相关文章

  • MySQL优化:单索引的选择-index_merge

    1.多个单索引 where子句后有多个查询条件,MySQL 5.1以前即使分别为每个条件建立索引,查询优化器也只会...

  • 2. mysql 为什么会选错索引

    上节我们讲了mysql的整体架构,知道了优化器的作用是优化sql,选择索引,生成执行计划。索引是优化器阶段自己选择...

  • mysql优化概述

    一:mysql优化概述:设计角度:存储引擎的选择,字段类型选择,范式。利用mysql自身的特性:索引,查询缓存,分...

  • MySQL索引知多少

    mysql索引 总结关于mysql的索引,查询优化,SQL技巧等 1 索引类型 B-Tree索引 Hash索引 ...

  • MySQL(4)应用优化

    MySQL应用优化 4.1-MySQL索引优化与设计 索引的作用 快速定位要查找的数据 数据库索引查找 全表扫描 ...

  • MySQL,必须掌握的6个知识点

    目录 一、索引B+ Tree 原理 MySQL 索引 索引优化 索引的优点 索引的使用条件 二、查询性能优化使用 ...

  • 索引合并优化(Index merge optimization)

    MySQL在 5.0版本中引入新特性:索引合并优化(Index merge optimization),当查询中单...

  • Mysql 相关

    MySQL索引 MySQL索引背后的数据结构及算法原理 覆盖索引和回表操作 MySQL性能优化 MySql表分区详...

  • MySQL相关文章索引(2)

    1.MySQL性能优化 对MySQL语句的性能分析与优化 Mysql 监控 Innodb 阻塞状况 MySQL索引...

  • 17.MySQL优化

    《高性能MySQL》——这本书都有的 “字段”优化总结 “索引”优化总结 索引的优化 “查询SQL”优化总结 “引...

网友评论

      本文标题:MySQL优化:单索引的选择-index_merge

      本文链接:https://www.haomeiwen.com/subject/isibaftx.html