原文地址:https://dev.mysql.com/doc/refman/5.7/en/index-merge-optimization.html
译文:
8.2.1.3 索引合并优化
索引合并访问方法使用多范围扫描检索行,并把检索结果合并成一个。这种访问方法仅合并来自单个表的索引扫描,而不是跨多个表的扫描。合并可以产生其底层扫描结果的并集、交集或交集的并集。
可能用到索引合并的查询示例:
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);
Note
索引合并优化算法有如下已知的限制:
1)如果你的查询中有一个使用深度嵌套and/or的where子句,MySQL不会选择最优计划,而是会尝试使用如下恒等变换来分散and/or:
(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)索引合并不适用于全文索引。
在explain的输出结果中,索引合并的方法在类型列中显示为index_merge。在这种情况下,key列包含一系列被使用的索引,key_len列包含所有这些索引中最长的索引。
索引合并优化有几种算法,显示在explain输出结果的extra列中:
1)使用intersect(...)
2)使用union(...)
3)使用sort_union(...)
下面各部分内容更加详细地描述了这些算法。优化器基于不同选择的成本估计选择可能的索引合并算法和其他访问方法。
索引合并的使用取决于optimizer_switch系统变量的index_merge、index_merge_cross、index_merge_union和index_merge_sort_union这些标志的值。这些标志的默认值都是on,如果要使用某种具体的算法,把index_merge的值设为off,把另外的标志设置成允许的值。
索引合并交集访问算法
该访问方法适用于where子句被转换为不同索引键与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字段里显示使用的索引)。下面就是这样的一个查询例子:
SELECT COUNT(*) FROM t1 WHERE key1 = 1 AND key2 = 1;
如果使用的索引没有覆盖查询中的所有列,则只有在满足所有使用的索引键的范围条件时才会检索全表行。
如果合并条件之一是作用于InnoDB表主键的范围条件,它不会用于行检索,而是用于过滤使用其他条件检索出的行。
索引合并并集访问方法
这种算法的标准与索引合并交集算法相似。该访问方法适用于表的where子句被转换为不同索引键与or组合的多个范围条件时,条件如下所示:
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;
排序并集算法与并集算法的不同之处在于排序并集算法在返回行前必须先取出所有行的ID并根据ID排序。
PS:由于水平有限,译文中难免存在谬误,欢迎批评指正。