#### 8.2.1.3 索引合并优化

[](<>)[](<>)[](<>)

Index Merge 访问方法检索具有多个[`范围`](explain-output.html#jointype_range)扫描并将它们的结果合并为一个。此访问方法仅合并来自单个表的索引扫描，而不是跨多个表的扫描。合并可以生成其底层扫描的并集、​​交集或交集并集。

可以使用索引合并的示例查询：

```
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);
```

笔记

索引合并优化算法具有以下已知限制：

-   如果您的查询有复杂的`在哪里`深的从句[`和`](logical-operators.html#operator_and)/[`要么`](logical-operators.html#operator_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)
    ```

-   索引合并不适用于全文索引。

    在[`解释`](explain.html)输出，索引合并方法显示为[`index_merge`](explain-output.html#jointype_index_merge)在里面`类型`柱子。在这种情况下，`钥匙`列包含使用的索引列表，并且`key_len`包含这些索引的最长关键部分的列表。

    Index Merge 访问方法有几种算法，显示在`额外的`现场[`解释`](explain.html)输出：

-   `使用 intersect(...)`

-   `使用联合（...）`

-   `使用 sort_union(...)`

    以下部分更详细地描述了这些算法。优化器根据各种可用选项的成本估计在不同可能的索引合并算法和其他访问方法之间进行选择。

-   [索引合并交叉点访问算法](index-merge-optimization.html#index-merge-intersection)

-   [索引合并联合访问算法](index-merge-optimization.html#index-merge-union)

-   [索引合并排序联合访问算法](index-merge-optimization.html#index-merge-sort-union)

-   [影响索引合并优化](index-merge-optimization.html#index-merge-influencing)

##### 索引合并交叉点访问算法

此访问算法适用于`在哪里`子句转换为不同键上的多个范围条件，并结合[`和`](logical-operators.html#operator_and)，并且每个条件都是以下之一：

-   一个*`ñ`*-此形式的部分表达式，其中索引恰好具有*`ñ`*部分（即涵盖所有索引部分）：

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

-   主键上的任何范围条件`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.html)输出包含`使用索引`在`额外的`在这种情况下字段）。以下是此类查询的示例：

```
SELECT COUNT(*) FROM t1 WHERE key1 = 1 AND key2 = 1;
```

如果使用的索引未覆盖查询中使用的所有列，则仅当满足所有使用的键的范围条件时才检索完整的行。

如果一个合并的条件是一个超过一个主键的条件`InnoDB`table，它不用于行检索，而是用于过滤掉使用其他条件检索到的行。

##### 索引合并联合访问算法

此算法的标准类似于索引合并交集算法的标准。该算法适用于表的`在哪里`子句转换为不同键上的多个范围条件，并结合[`要么`](logical-operators.html#operator_or)，并且每个条件都是以下之一：

-   一个*`ñ`*-此形式的部分表达式，其中索引恰好具有*`ñ`*部分（即涵盖所有索引部分）：

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

-   一个主键上的任何范围条件`InnoDB`桌子。

-   索引合并交集算法适用的条件。

    例子：


```
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;
```

##### 索引合并排序联合访问算法

此访问算法适用于`在哪里`子句转换为几个范围条件组合[`要么`](logical-operators.html#operator_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 并在返回任何行之前对它们进行排序。

##### 影响索引合并优化

指数合并的使用取决于[`index_merge`](switchable-optimizations.html#optflag_index-merge),[`index_merge_intersection`](switchable-optimizations.html#optflag_index-merge-intersection),[`index_merge_union`](switchable-optimizations.html#optflag_index-merge-union)， 和[`index_merge_sort_union`](switchable-optimizations.html#optflag_index-merge-sort-union)的旗帜[`优化器开关`](server-system-variables.html#sysvar_optimizer_switch)系统变量。看[第 8.9.2 节，“可切换的优化”](switchable-optimizations.html).默认情况下，所有这些标志都是`在`.要仅启用某些算法，请设置[`index_merge`](switchable-optimizations.html#optflag_index-merge)到`离开`，并且仅启用应允许的其他那些。

除了使用[`优化器开关`](server-system-variables.html#sysvar_optimizer_switch)系统变量来控制优化器在会话范围内使用索引合并算法，MySQL 支持优化器提示以在每个语句的基础上影​​响优化器。看[第 8.9.3 节，“优化器提示”](optimizer-hints.html).
