索引合并是使用多个范围扫描去检索行数据并最终合并他们的结果为一个结果集的方法。这种合并至能发生在单一表的索引扫描上;不能夸表合并扫描结果。这个合并会产生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);




在EXPLAIN输出中,索引合并方法作为index_merge列类型出现。在这种情况下,该列包含了所有使用了的索引的集合,且key_len的值是所有索引中最长那一部分的长度。
  注意:索引合并优化有如下总所周知的不足:
  1)如果你的查询是一个复杂查询包含了很深的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)索引合并不适用于full-text类型的索引上。
索引合并方法有一些算法,在EXPLAIN输出的Extra列上展示:
  1)Using intersect(...) 交集
  2)Using union(...)   并集
  3)Using sort_union(...)  排序并集
下面的部分更加详细的描述了这些算法。优化器在选择不同的可能的索引合并方案和其他的优化方式的依据是不同变量选项的花费评估。
使用索引合并的值来自optimizer_switch系统变量的值,包括index_merge, index_merge_intersection, index_merge_union, and index_merge_sort_union。具体请看8.9.3的Switchable 优化。默认所有这些标志都是开启的,可以通过设置index_merge 为off来只使用某一值,也可以只使用其他一些值。
>索引合并的交集算法
该算法被使用,当一个where条件被转化为多个区域条件对不同的key值通过and操作结合的,其中的每个条件都类似如下条件:
 1)一个N部分的表达式,其中索引包含这N部分(也就是覆盖索引的全部):
 key_part1 = const1 AND key_part2 = const2 ... AND key_partN = constN
 2)在innodb数据库表中的主键上的任何范围条件。
 例如:
  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;
索引合并的交集就是同时扫描所有可以用的索引并且获取所有结果的交集。
如果查询所使用的列都在使用的索引中,那么查询并不需要查询表中的完整行数据(EXPLAIN输出的EXtra列的值中有Using index)。如下是一个举例:
select count(*) from t1 where key1=1 and key2=1;
如果使用的索引列不能覆盖查询中的所有输出列,则符合查询索引条件的行数据将会全行扫描。
如果合并条件之一是一个覆盖主键的条件,在innoDB表中,将不会使用行检索,但会过滤行通过使用其他条件。
>索引合并的并集算法
该算法的准则类似于索引合并的交集算法。该算法将会被使用,如果表中的where条件可以转换为几个范围条件,通过OR操作合并的不同的keys,并且每一个条件都类似如下的表达式:
1)一个N部分表达式的形式,索引就是由N部分组成(也就是说,索引的所有部分都被覆盖):
key_part1 = const1 AND key_part2 = const2 ... AND key_partN = constN
2)在innoDB表中主键上的任何条件覆盖
3)一个符合索引合并交集算法的条件可以应用。
例如:
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;
>索引合并的有序并集算法
该算法在索引合并算法不可用的情况下,但是where条件中的查询可以转换为多个区域条件通过OR操作结合的情况下使用。
例如:
SELECT * FROM tbl_name
  WHERE key_col1 < 10 OR key_col2 < 20;


SELECT * FROM tbl_name
  WHERE (key_col1 > 10 OR key_col2 = 20) AND nonkey_col = 30;
sort union算法和union算法的不同是sort union算法必须先取得所有行的id集合并且在返回之前先对他们排好序。


到此关于索引合并的优化就结束了,接下来我们要介绍的是1.4的Engine Condition Pushdown Optimization。