索引合并方法用于通过range扫描搜索行并将结果合成一个。合并会产生并集、交集或者正在进行的扫描的交集的并集。
在EXPLAIN输出中,该方法表现为type列内的index_merge。在这种情况下,key列包含一列使用的索引,key_len包含这些索引的最长的关键元素。
例如:
SELECT * FROM tbl_name WHERE key_part1 = 10 OR key_part2 = 20;
SELECT * FROM tbl_name
WHERE (key_part1 = 10 OR key_part2 = 20) AND non_key_part=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输出的Extra字段):
· 交集
· 联合
· 排序并集
后面几节更加详细地描述了这些方法。
注释:索引合并优化算法具有以下几个已知缺陷:
· 如果可以对某些关键字进行范围扫描,则不考虑索引合并。例如,下面的查询:
· SELECT * FROM t1 WHERE (goodkey1 < 10 OR goodkey2 < 20) AND badkey < 30;
对于该查询,可以有两个方案:
1. 使用(goodkey1 < 10 OR goodkey2 < 20)条件进行索引合并扫描。
2. 使用badkey < 30条件进行范围扫描。
然而,优化器只考虑第2个方案。如果这不是你想要的,你可以通过使用IGNORE INDEX或FORCE INDEX让优化器考虑index_merge。下面的查询使用索引合并执行:
SELECT * FROM t1 FORCE INDEX(goodkey1,goodkey2)
WHERE (goodkey1 < 10 OR goodkey2 < 20) AND badkey < 30;
SELECT * FROM t1 IGNORE INDEX(badkey)
WHERE (goodkey1 < 10 OR goodkey2 < 20) AND badkey < 30;
· 如果查询有一个复杂的WHERE子句,有较深的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)
index_merge访问方法的不同变量之间的选择和其它访问方法基于各适用选项的成本估计。