### 8.9.2 可切换优化

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

这[`优化器开关`](server-system-variables.html#sysvar_optimizer_switch)系统变量可以控制优化器的行为。它的值是一组标志，每个标志的值`在`要么`离开`指示相应的优化器行为是启用还是禁用。此变量具有全局值和会话值，可以在运行时更改。全局默认值可以在服务器启动时设置。

要查看当前的优化器标志集，请选择变量值：

```
mysql> SELECT @@optimizer_switch\G
*************************** 1. row ***************************
@@optimizer_switch: index_merge=on,index_merge_union=on,
                    index_merge_sort_union=on,index_merge_intersection=on,
                    engine_condition_pushdown=on,index_condition_pushdown=on,
                    mrr=on,mrr_cost_based=on,block_nested_loop=on,
                    batched_key_access=off,materialization=on,semijoin=on,
                    loosescan=on,firstmatch=on,duplicateweedout=on,
                    subquery_materialization_cost_based=on,
                    use_index_extensions=on,condition_fanout_filter=on,
                    derived_merge=on,use_invisible_indexes=off,skip_scan=on,
                    hash_join=on,subquery_to_derived=off,
                    prefer_ordering_index=on,hypergraph_optimizer=off,
                    derived_condition_pushdown=on
1 row in set (0.00 sec)
```

改变值[`优化器开关`](server-system-variables.html#sysvar_optimizer_switch)，分配一个由一个或多个命令的逗号分隔列表组成的值：

```
SET [GLOBAL|SESSION] optimizer_switch='command[,command]...';
```

每个*`命令`*value 应具有下表中显示的形式之一。

| 命令语法 | 意义 |
| ---- | --- |
| `默认` | 将每个优化重置为其默认值 |
| `*`opt_name`*=默认` | 将命名优化设置为其默认值 |
| `*`opt_name`*=关闭` | 禁用命名优化 |
| `*`opt_name`*=开启` | 启用命名优化 |

值中命令的顺序无关紧要，尽管`默认`如果存在，则首先执行命令。设置一个*`opt_name`*标记为`默认`将其设置为`在`要么`离开`是它的默认值。指定任何给定的*`opt_name`*不允许在值中多次出现并导致错误。值中的任何错误都会导致分配失败并出现错误，留下的值[`优化器开关`](server-system-variables.html#sysvar_optimizer_switch)不变。

以下列表描述了允许的*`opt_name`*标志名称，按优化策略分组：

-   批量密钥访问标志

    -   [](<>) [`batched_key_access`](switchable-optimizations.html#optflag_batched-key-access)（默认`离开`)

        控制 BKA 连接算法的使用。

        为了[`batched_key_access`](switchable-optimizations.html#optflag_batched-key-access)设置为时有任何效果`在`， 这[`先生`](switchable-optimizations.html#optflag_mrr)标志也必须是`在`.目前，MRR的成本估算过于悲观。因此，也有必要为[`mrr_cost_based`](switchable-optimizations.html#optflag_mrr-cost-based)成为`离开`用于使用 BKA。

        有关详细信息，请参阅[第 8.2.1.12 节，“阻止嵌套循环和批量密钥访问连接”](bnl-bka-optimization.html).

-   阻止嵌套循环标志

    -   [](<>) [`block_nested_loop`](switchable-optimizations.html#optflag_block-nested-loop)（默认`在`)

        控制 BNL 连接算法的使用。在 MySQL 8.0.18 及更高版本中，这也控制哈希连接的使用，就像[`BNL`](optimizer-hints.html#optimizer-hints-table-level)和[`NO_BNL`](optimizer-hints.html#optimizer-hints-table-level)优化器提示。在 MySQL 8.0.20 及更高版本中，从 MySQL 服务器中删除了块嵌套循环支持，并且此标志仅控制哈希联接的使用，引用的优化器提示也是如此。

        有关详细信息，请参阅[第 8.2.1.12 节，“阻止嵌套循环和批量密钥访问连接”](bnl-bka-optimization.html).

-   条件过滤标志

    -   [](<>) [`条件扇出过滤器`](switchable-optimizations.html#optflag_condition-fanout-filter)（默认`在`)

        控制条件过滤的使用。

        有关详细信息，请参阅[第 8.2.1.13 节，“条件过滤”](condition-filtering.html).

-   派生条件下推标志

    -   [](<>) [`派生条件下推`](switchable-optimizations.html#optflag_derived-condition-pushdown)（默认`在`)

        控制派生条件下推。

        有关详细信息，请参阅[第 8.2.2.5 节，“导出条件下推优化”](derived-condition-pushdown-optimization.html)

-   派生表合并标志

    -   [](<>) [`派生合并`](switchable-optimizations.html#optflag_derived-merge)（默认`在`)

        控制将派生表和视图合并到外部查询块中。

        这[`派生合并`](switchable-optimizations.html#optflag_derived-merge)flag 控制优化器是否尝试将派生表、视图引用和公用表表达式合并到外部查询块中，假设没有其他规则阻止合并；例如，一个`算法`视图指令优先于[`派生合并`](switchable-optimizations.html#optflag_derived-merge)环境。默认情况下，标志是`在`启用合并。

        有关详细信息，请参阅[第 8.2.2.4 节，“通过合并或实现优化派生表、视图引用和公用表表达式”](derived-table-optimization.html).

-   发动机状态下推标志

    -   [](<>) [`engine_condition_pushdown`](switchable-optimizations.html#optflag_engine-condition-pushdown)（默认`在`)

        控制发动机状态下推。

        有关详细信息，请参阅[第 8.2.1.5 节，“发动机工况下推优化”](engine-condition-pushdown-optimization.html).

-   哈希连接标志

    -   [](<>) [`hash_join`](switchable-optimizations.html#optflag_hash-join)（默认`在`)

        仅在 MySQL 8.0.18 中控制哈希联接，在任何后续版本中都无效。在 MySQL 8.0.19 及更高版本中，要控制哈希联接的使用，请使用[`block_nested_loop`](switchable-optimizations.html#optflag_block-nested-loop)标志，而不是。

        有关详细信息，请参阅[第 8.2.1.4 节，“哈希连接优化”](hash-joins.html).

-   索引条件下推标志

    -   [](<>) [`index_condition_pushdown`](switchable-optimizations.html#optflag_index-condition-pushdown)（默认`在`)

        控制索引条件下推。

        有关详细信息，请参阅[第 8.2.1.6 节，“索引条件下推优化”](index-condition-pushdown-optimization.html).

-   索引扩展标志

    -   [](<>) [`使用索引扩展`](switchable-optimizations.html#optflag_use-index-extensions)（默认`在`)

        控制索引扩展的使用。

        有关详细信息，请参阅[第 8.3.10 节，“索引扩展的使用”](index-extensions.html).

-   索引合并标志

    -   [](<>) [`index_merge`](switchable-optimizations.html#optflag_index-merge)（默认`在`)

        控制所有索引合并优化。

    -   [](<>) [`index_merge_intersection`](switchable-optimizations.html#optflag_index-merge-intersection)（默认`在`)

        控制索引合并交叉点访问优化。

    -   [](<>) [`index_merge_sort_union`](switchable-optimizations.html#optflag_index-merge-sort-union)（默认`在`)

        控制索引合并排序联合访问优化。

    -   [](<>) [`index_merge_union`](switchable-optimizations.html#optflag_index-merge-union)（默认`在`)

        控制索引合并联合访问优化。

        有关详细信息，请参阅[第 8.2.1.3 节，“索引合并优化”](index-merge-optimization.html).

-   索引可见性标志

    -   [](<>) [`使用_invisible_indexes`](switchable-optimizations.html#optflag_use-invisible-indexes)（默认`离开`)

        控制不可见索引的使用。

        有关详细信息，请参阅[第 8.3.12 节，“不可见索引”](invisible-indexes.html).

-   限制优化标志

    -   [](<>) [`prefer_ordering_index`](switchable-optimizations.html#optflag_prefer-ordering-index)（默认`在`)

        控制是否在查询具有`订购方式`要么`通过...分组`与`限制`子句中，优化器尝试使用有序索引而不是无序索引、文件排序或其他一些优化。每当优化器确定使用它可以更快地执行查询时，默认情况下都会执行此优化。

        因为做出这种决定的算法不能处理所有可能的情况（部分原因是假设数据的分布总是或多或少是均匀的），所以在某些情况下，这种优化可能是不可取的。在 MySQL 8.0.21 之前，无法禁用此优化，但在 MySQL 8.0.21 及更高版本中，虽然它仍然是默认行为，但可以通过设置[`prefer_ordering_index`](switchable-optimizations.html#optflag_prefer-ordering-index)标记为`离开`.

        有关更多信息和示例，请参阅[第 8.2.1.19 节，“限制查询优化”](limit-optimization.html).

-   多范围读取标志

    -   [](<>) [`先生`](switchable-optimizations.html#optflag_mrr)（默认`在`)

        控制多范围读取策略。

    -   [](<>) [`mrr_cost_based`](switchable-optimizations.html#optflag_mrr-cost-based)（默认`在`)

        控制基于成本的 MRR 的使用，如果[`mrr=on`](switchable-optimizations.html#optflag_mrr).

        有关详细信息，请参阅[第 8.2.1.11 节，“多范围读取优化”](mrr-optimization.html).

-   半连接标志

    -   [](<>) [`重复除草`](switchable-optimizations.html#optflag_duplicateweedout)（默认`在`)

        控制 semijoin Duplicate Weedout 策略。

    -   [](<>) [`第一场比赛`](switchable-optimizations.html#optflag_firstmatch)（默认`在`)

        控制半联接 FirstMatch 策略。

    -   [](<>) [`松散扫描`](switchable-optimizations.html#optflag_loosescan)（默认`在`)

        控制半连接 LooseScan 策略（不要与 Loose Index Scan 混淆`通过...分组`）。

    -   [](<>) [`半连接`](switchable-optimizations.html#optflag_semijoin)（默认`在`)

        控制所有半连接策略。

        在 MySQL 8.0.17 及更高版本中，这也适用于反连接优化。

        这[`半连接`](switchable-optimizations.html#optflag_semijoin),[`第一场比赛`](switchable-optimizations.html#optflag_firstmatch),[`松散扫描`](switchable-optimizations.html#optflag_loosescan)， 和[`重复除草`](switchable-optimizations.html#optflag_duplicateweedout)标志可以控制半连接策略。这[`半连接`](switchable-optimizations.html#optflag_semijoin)flag 控制是否使用半连接。如果设置为`在`， 这[`第一场比赛`](switchable-optimizations.html#optflag_firstmatch)和[`松散扫描`](switchable-optimizations.html#optflag_loosescan)标志可以更好地控制允许的半连接策略。

        如果[`重复除草`](switchable-optimizations.html#optflag_duplicateweedout)semijoin 策略被禁用，除非所有其他适用的策略也被禁用，否则不会使用它。

        如果[`半连接`](switchable-optimizations.html#optflag_semijoin)和[`物化`](switchable-optimizations.html#optflag_materialization)都是`在`, semijoins 在适用的情况下也使用物化。这些标志是`在`默认。

        有关详细信息，请参阅[第 8.2.2.1 节，“使用半连接转换优化 IN 和 EXISTS 子查询谓词”](semijoins.html).

-   跳过扫描标志

    -   [](<>) [`跳过扫描`](switchable-optimizations.html#optflag_skip-scan)（默认`在`)

        控制跳过扫描访问方法的使用。

        有关详细信息，请参阅[跳过扫描范围访问方法](range-optimization.html#range-access-skip-scan).

-   子查询实现标志

    -   [](<>) [`物化`](switchable-optimizations.html#optflag_materialization)（默认`在`)

        控制物化（包括半连接物化）。

    -   [](<>) [`subquery_materialization_cost_based`](switchable-optimizations.html#optflag_subquery-materialization-cost-based)（默认`在`)

        使用基于成本的实现选择。

        这[`物化`](switchable-optimizations.html#optflag_materialization)flag 控制是否使用子查询实现。如果[`半连接`](switchable-optimizations.html#optflag_semijoin)和[`物化`](switchable-optimizations.html#optflag_materialization)都是`在`, semijoins 在适用的情况下也使用物化。这些标志是`在`默认。

        这[`subquery_materialization_cost_based`](switchable-optimizations.html#optflag_subquery-materialization-cost-based)标志可以控制子查询实现和子查询之间的选择`在`-到-`存在`子查询转换。如果国旗是`在`（默认），优化器在子查询实现和子查询实现之间执行基于成本的选择`在`-到-`存在`如果可以使用任一方法，则进行子查询转换。如果国旗是`离开`，优化器选择子查询实现`在`-到-`存在`子查询转换。

        有关详细信息，请参阅[第 8.2.2 节，“优化子查询、派生表、视图引用和公用表表达式”](subquery-optimization.html).

-   子查询转换标志

    -   [](<>) [`subquery_to_derived`](switchable-optimizations.html#optflag_subquery-to-derived)（默认`离开`)

        从 MySQL 8.0.21 开始，优化器在许多情况下能够将标量子查询转换为`选择`,`在哪里`,`加入`， 要么`拥有`子句到派生表上的左外连接。（根据派生表的可空性，这有时可以进一步简化为内部连接。）这可以用于满足以下条件的子查询：

        -   子查询不使用任何非确定性函数，例如[`兰德（）`](mathematical-functions.html#function_rand).

        -   子查询不是`任何`要么`全部`可以重写以使用的子查询[`最小（）`](aggregate-functions.html#function_min)要么[`最大限度（）`](aggregate-functions.html#function_max).

        -   父查询不设置用户变量，因为重写它可能会影响执行顺序，如果在同一个查询中多次访问该变量，可能会导致意外结果。

        -   子查询不应关联，也就是说，它不应引用外部查询中表中的列，或包含在外部查询中评估的聚合。

            在 MySQL 8.0.22 之前，子查询不能包含`通过...分组`条款。

            这种优化也可以应用于作为参数的表子查询`在`,`不在`,`存在`， 要么`不存在`, 不包含`通过...分组`.

            此标志的默认值为`离开`，因为在大多数情况下，启用此优化不会产生任何明显的性能改进（在许多情况下甚至会使查询运行得更慢），但您可以通过设置[`subquery_to_derived`](switchable-optimizations.html#optflag_subquery-to-derived)标记为`在`.它主要用于测试。

            例如，使用标量子查询：

        ```
        d
        mysql> CREATE TABLE t1(a INT);

        mysql> CREATE TABLE t2(a INT);

        mysql> INSERT INTO t1 VALUES ROW(1), ROW(2), ROW(3), ROW(4);

        mysql> INSERT INTO t2 VALUES ROW(1), ROW(2);

        mysql> SELECT * FROM t1
            ->     WHERE t1.a > (SELECT COUNT(a) FROM t2);
        +------+
        | a    |
        +------+
        |    3 |
        |    4 |
        +------+

        mysql> SELECT @@optimizer_switch LIKE '%subquery_to_derived=off%';
        +-----------------------------------------------------+
        | @@optimizer_switch LIKE '%subquery_to_derived=off%' |
        +-----------------------------------------------------+
        |                                                   1 |
        +-----------------------------------------------------+

        mysql> EXPLAIN SELECT * FROM t1 WHERE t1.a > (SELECT COUNT(a) FROM t2)\G
        *************************** 1. row ***************************
                   id: 1
          select_type: PRIMARY
                table: t1
           partitions: NULL
                 type: ALL
        possible_keys: NULL
                  key: NULL
              key_len: NULL
                  ref: NULL
                 rows: 4
             filtered: 33.33
                Extra: Using where
        *************************** 2. row ***************************
                   id: 2
          select_type: SUBQUERY
                table: t2
           partitions: NULL
                 type: ALL
        possible_keys: NULL
                  key: NULL
              key_len: NULL
                  ref: NULL
                 rows: 2
             filtered: 100.00
                Extra: NULL

        mysql> SET @@optimizer_switch='subquery_to_derived=on';

        mysql> SELECT @@optimizer_switch LIKE '%subquery_to_derived=off%';
        +-----------------------------------------------------+
        | @@optimizer_switch LIKE '%subquery_to_derived=off%' |
        +-----------------------------------------------------+
        |                                                   0 |
        +-----------------------------------------------------+

        mysql> SELECT @@optimizer_switch LIKE '%subquery_to_derived=on%';
        +----------------------------------------------------+
        | @@optimizer_switch LIKE '%subquery_to_derived=on%' |
        +----------------------------------------------------+
        |                                                  1 |
        +----------------------------------------------------+

        mysql> EXPLAIN SELECT * FROM t1 WHERE t1.a > (SELECT COUNT(a) FROM t2)\G
        *************************** 1. row ***************************
                   id: 1
          select_type: PRIMARY
                table: <derived2>
           partitions: NULL
                 type: ALL
        possible_keys: NULL
                  key: NULL
              key_len: NULL
                  ref: NULL
                 rows: 1
             filtered: 100.00
                Extra: NULL
        *************************** 2. row ***************************
                   id: 1
          select_type: PRIMARY
                table: t1
           partitions: NULL
                 type: ALL
        possible_keys: NULL
                  key: NULL
              key_len: NULL
                  ref: NULL
                 rows: 4
             filtered: 33.33
                Extra: Using where; Using join buffer (hash join)
        *************************** 3. row ***************************
                   id: 2
          select_type: DERIVED
                table: t2
           partitions: NULL
                 type: ALL
        possible_keys: NULL
                  key: NULL
              key_len: NULL
                  ref: NULL
                 rows: 2
             filtered: 100.00
                Extra: NULL
        ```

        从执行中可以看出[`显示警告`](show-warnings.html)紧随第二个[`解释`](explain.html)语句，启用优化后，查询`SELECT * FROM t1 WHERE t1.a > (SELECT COUNT(a) FROM t2)`以类似于此处所示的形式重写：

        ```
        SELECT t1.a FROM t1
            JOIN  ( SELECT COUNT(t2.a) AS c FROM t2 ) AS d
                    WHERE t1.a > d.c;
        ```

        示例，使用查询`在 （*`子查询`*)`：

        ```
        mysql> DROP TABLE IF EXISTS t1, t2;

        mysql> CREATE TABLE t1 (a INT, b INT);
        mysql> CREATE TABLE t2 (a INT, b INT);

        mysql> INSERT INTO t1 VALUES ROW(1,10), ROW(2,20), ROW(3,30);
        mysql> INSERT INTO t2
            ->    VALUES ROW(1,10), ROW(2,20), ROW(3,30), ROW(1,110), ROW(2,120), ROW(3,130);

        mysql> SELECT * FROM t1
            ->     WHERE   t1.b < 0
            ->             OR
            ->             t1.a IN (SELECT t2.a + 1 FROM t2);
        +------+------+
        | a    | b    |
        +------+------+
        |    2 |   20 |
        |    3 |   30 |
        +------+------+

        mysql> SET @@optimizer_switch="subquery_to_derived=off";

        mysql> EXPLAIN SELECT * FROM t1
            ->             WHERE   t1.b < 0
            ->                     OR
            ->                     t1.a IN (SELECT t2.a + 1 FROM t2)\G
        *************************** 1. row ***************************
                   id: 1
          select_type: PRIMARY
                table: t1
           partitions: NULL
                 type: ALL
        possible_keys: NULL
                  key: NULL
              key_len: NULL
                  ref: NULL
                 rows: 3
             filtered: 100.00
                Extra: Using where
        *************************** 2. row ***************************
                   id: 2
          select_type: DEPENDENT SUBQUERY
                table: t2
           partitions: NULL
                 type: ALL
        possible_keys: NULL
                  key: NULL
              key_len: NULL
                  ref: NULL
                 rows: 6
             filtered: 100.00
                Extra: Using where

        mysql> SET @@optimizer_switch="subquery_to_derived=on";

        mysql> EXPLAIN SELECT * FROM t1
            ->             WHERE   t1.b < 0
            ->                     OR
            ->                     t1.a IN (SELECT t2.a + 1 FROM t2)\G
        *************************** 1. row ***************************
                   id: 1
          select_type: PRIMARY
                table: t1
           partitions: NULL
                 type: ALL
        possible_keys: NULL
                  key: NULL
              key_len: NULL
                  ref: NULL
                 rows: 3
             filtered: 100.00
                Extra: NULL
        *************************** 2. row ***************************
                   id: 1
          select_type: PRIMARY
                table: <derived2>
           partitions: NULL
                 type: ref
        possible_keys: <auto_key0>
                  key: <auto_key0>
              key_len: 9
                  ref: std2.t1.a
                 rows: 2
             filtered: 100.00
                Extra: Using where; Using index
        *************************** 3. row ***************************
                   id: 2
          select_type: DERIVED
                table: t2
           partitions: NULL
                 type: ALL
        possible_keys: NULL
                  key: NULL
              key_len: NULL
                  ref: NULL
                 rows: 6
             filtered: 100.00
                Extra: Using temporary
        ```

        检查并简化结果[`显示警告`](show-warnings.html)执行后[`解释`](explain.html)关于这个查询表明，当[`subquery_to_derived`](switchable-optimizations.html#optflag_subquery-to-derived)启用标志，`从 t1 中选择 *，其中 t1.b < 0 或 t1.a IN（从 t2 中选择 t2.a + 1）`以类似于此处所示的形式重写：

        ```
        SELECT a, b FROM t1
            LEFT JOIN (SELECT DISTINCT a + 1 AS e FROM t2) d
            ON t1.a = d.e
            WHERE   t1.b < 0
                    OR
                    d.e IS NOT NULL;
        ```

        示例，使用查询`存在 (*`子查询`*)`以及与上一个示例中相同的表和数据：

        ```
        mysql> SELECT * FROM t1
            ->     WHERE   t1.b < 0
            ->             OR
            ->             EXISTS(SELECT * FROM t2 WHERE t2.a = t1.a + 1);
        +------+------+
        | a    | b    |
        +------+------+
        |    1 |   10 |
        |    2 |   20 |
        +------+------+

        mysql> SET @@optimizer_switch="subquery_to_derived=off";

        mysql> EXPLAIN SELECT * FROM t1
            ->             WHERE   t1.b < 0
            ->                     OR
            ->                     EXISTS(SELECT * FROM t2 WHERE t2.a = t1.a + 1)\G
        *************************** 1. row ***************************
                   id: 1
          select_type: PRIMARY
                table: t1
           partitions: NULL
                 type: ALL
        possible_keys: NULL
                  key: NULL
              key_len: NULL
                  ref: NULL
                 rows: 3
             filtered: 100.00
                Extra: Using where
        *************************** 2. row ***************************
                   id: 2
          select_type: DEPENDENT SUBQUERY
                table: t2
           partitions: NULL
                 type: ALL
        possible_keys: NULL
                  key: NULL
              key_len: NULL
                  ref: NULL
                 rows: 6
             filtered: 16.67
                Extra: Using where

        mysql> SET @@optimizer_switch="subquery_to_derived=on";

        mysql> EXPLAIN SELECT * FROM t1
            ->             WHERE   t1.b < 0
            ->                     OR
            ->                     EXISTS(SELECT * FROM t2 WHERE t2.a = t1.a + 1)\G
        *************************** 1. row ***************************
                   id: 1
          select_type: PRIMARY
                table: t1
           partitions: NULL
                 type: ALL
        possible_keys: NULL
                  key: NULL
              key_len: NULL
                  ref: NULL
                 rows: 3
             filtered: 100.00
                Extra: NULL
        *************************** 2. row ***************************
                   id: 1
          select_type: PRIMARY
                table: <derived2>
           partitions: NULL
                 type: ALL
        possible_keys: NULL
                  key: NULL
              key_len: NULL
                  ref: NULL
                 rows: 6
             filtered: 100.00
                Extra: Using where; Using join buffer (hash join)
        *************************** 3. row ***************************
                   id: 2
          select_type: DERIVED
                table: t2
           partitions: NULL
                 type: ALL
        possible_keys: NULL
                  key: NULL
              key_len: NULL
                  ref: NULL
                 rows: 6
             filtered: 100.00
                Extra: Using temporary
        ```

        如果我们执行[`显示警告`](show-warnings.html)跑完之后[`解释`](explain.html)关于查询`SELECT * FROM t1 WHERE t1.b < 0 OR EXISTS(SELECT * FROM t2 WHERE t2.a = t1.a + 1)`什么时候[`subquery_to_derived`](switchable-optimizations.html#optflag_subquery-to-derived)已启用，并简化结果的第二行，我们看到它已被重写为类似于以下的形式：

        ```
        SELECT a, b FROM t1
        LEFT JOIN (SELECT DISTINCT 1 AS e1, t2.a AS e2 FROM t2) d
        ON t1.a + 1 = d.e2
        WHERE   t1.b < 0
                OR
                d.e1 IS NOT NULL;
        ```

        有关详细信息，请参阅[第 8.2.2.4 节，“通过合并或实现优化派生表、视图引用和公用表表达式”](derived-table-optimization.html)， 也[第 8.2.1.19 节，“限制查询优化”](limit-optimization.html)， 和[第 8.2.2.1 节，“使用半连接转换优化 IN 和 EXISTS 子查询谓词”](semijoins.html).

    当您将值分配给[`优化器开关`](server-system-variables.html#sysvar_optimizer_switch)，未提及的标志保留其当前值。这使得可以在单个语句中启用或禁用特定的优化器行为而不影响其他行为。该语句不依赖于存在哪些其他优化器标志以及它们的值是什么。假设启用了所有索引合并优化：


```
mysql> SELECT @@optimizer_switch\G
*************************** 1. row ***************************
@@optimizer_switch: index_merge=on,index_merge_union=on,
                    index_merge_sort_union=on,index_merge_intersection=on,
                    engine_condition_pushdown=on,index_condition_pushdown=on,
                    mrr=on,mrr_cost_based=on,block_nested_loop=on,
                    batched_key_access=off,materialization=on,semijoin=on,
                    loosescan=on, firstmatch=on,
                    subquery_materialization_cost_based=on,
                    use_index_extensions=on,condition_fanout_filter=on,
                    derived_merge=on,use_invisible_indexes=off,skip_scan=on,
                    hash_join=on,subquery_to_derived=off,
                    prefer_ordering_index=on
```

如果服务器对某些查询使用 Index Merge Union 或 Index Merge Sort-Union 访问方法，并且您想检查优化器在没有它们的情况下是否可以更好地执行，请像这样设置变量值：

```
mysql> SET optimizer_switch='index_merge_union=off,index_merge_sort_union=off';

mysql> SELECT @@optimizer_switch\G
*************************** 1. row ***************************
@@optimizer_switch: index_merge=on,index_merge_union=off,
                    index_merge_sort_union=off,index_merge_intersection=on,
                    engine_condition_pushdown=on,index_condition_pushdown=on,
                    mrr=on,mrr_cost_based=on,block_nested_loop=on,
                    batched_key_access=off,materialization=on,semijoin=on,
                    loosescan=on, firstmatch=on,
                    subquery_materialization_cost_based=on,
                    use_index_extensions=on,condition_fanout_filter=on,
                    derived_merge=on,use_invisible_indexes=off,skip_scan=on,
                    hash_join=on,subquery_to_derived=off,
                    prefer_ordering_index=on
```
