optimizer_switch 系统变量用于控制优化器行为。它的值是一组标志,每个标志的值可以是 on 或 off,以指示相应的优化器行为是启用还是禁用。该变量具有全局值和会话值,并且可以在运行时更改。全局默认值可以在服务器启动时设置。The optimizer_switch system
variable enables control over optimizer behavior. Its value is a
set of flags, each of which has a value of on
or off to indicate whether the corresponding
optimizer behavior is enabled or disabled. This variable has
global and session values and can be changed at runtime. The
global default can be set at server startup.
要查看当前的优化器标志集,请选择变量值:To see the current set of optimizer flags, select the variable value:
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,hash_set_operations=on
1 row in set (0.00 sec)
要更改 optimizer_switch 的值,请分配一个由一个或多个命令组成的逗号分隔的值:To change the value of
optimizer_switch, assign a
value consisting of a comma-separated list of one or more
commands:
SET [GLOBAL|SESSION] optimizer_switch='command[,command]...';
每个 command 值应具有下表所示的形式之一。Each command value should have one of
the forms shown in the following table.
| 命令语法Command Syntax | 意义Meaning |
|---|---|
defaultdefault |
将每个优化重置为默认值Reset every optimization to its default value |
opt_name=default |
将指定的优化设置为其默认值Set the named optimization to its default value |
opt_name=off |
禁用指定的优化Disable the named optimization |
opt_name=on |
启用指定的优化Enable the named optimization |
值中命令的顺序无关紧要,但如果存在,default 命令会首先执行。将 opt_name 标志设置为 default 会将其设置为 on 或 off 中的默认值。值中不允许重复指定任何给定的 opt_name,否则会导致错误。值中出现的任何错误都会导致赋值失败,并出现错误,同时保持 optimizer_switch 的值不变。The order of the commands in the value does not matter, although
the default command is executed first if
present. Setting an opt_name flag to
default sets it to whichever of
on or off is its default
value. Specifying any given opt_name
more than once in the value is not permitted and causes an
error. Any errors in the value cause the assignment to fail with
an error, leaving the value of
optimizer_switch unchanged.
下面的列表描述了允许的 opt_name 标志名称,按优化策略分组:The following list describes the permissible
opt_name flag names, grouped by
optimization strategy:
批量密钥访问标志Batched Key Access Flags
batched_key_access(默认off)batched_key_access(defaultoff)控制 BKA 连接算法的使用。Controls use of BKA join algorithm.
要使
batched_key_access在设置为on时生效,mrr标志也必须设置为on。目前,MRR 的成本估算过于悲观。因此,为了使用 BKA,mrr_cost_based也必须设置为off。Forbatched_key_accessto have any effect when set toon, themrrflag must also beon. Currently, the cost estimation for MRR is too pessimistic. Hence, it is also necessary formrr_cost_basedto beofffor BKA to be used.欲了解更多信息,请参见 第 10.2.1.12 节,“块嵌套循环和批量键访问连接”。For more information, see Section 10.2.1.12, “Block Nested-Loop and Batched Key Access Joins”.
块嵌套循环标志Block Nested-Loop Flags
block_nested_loop(默认on)block_nested_loop(defaulton)控制哈希连接的使用,与
BNL和NO_BNL优化器提示作用相同。Controls use of hash joins, as do theBNLandNO_BNLoptimizer hints.
欲了解更多信息,请参见 第 10.2.1.12 节,“块嵌套循环和批量键访问连接”。For more information, see Section 10.2.1.12, “Block Nested-Loop and Batched Key Access Joins”.
条件过滤标志Condition Filtering Flags
condition_fanout_filter(默认on)condition_fanout_filter(defaulton)控制条件过滤的使用。Controls use of condition filtering.
欲了解更多信息,请参见 第 10.2.1.13 节,“条件过滤”。For more information, see Section 10.2.1.13, “Condition Filtering”.
派生条件下推标志Derived Condition Pushdown Flags
derived_condition_pushdown(默认on)derived_condition_pushdown(defaulton)控制派生条件下推。Controls derived condition pushdown.
欲了解更多信息,请参见 第 10.2.2.5 节,“派生条件下推优化”For more information, see Section 10.2.2.5, “Derived Condition Pushdown Optimization”
派生表合并标志Derived Table Merging Flags
derived_merge(默认on)derived_merge(defaulton)控制派生表和视图合并到外部查询块中。Controls merging of derived tables and views into outer query block.
derived_merge标志控制优化器是否尝试将派生表、视图引用和公共表表达式合并到外部查询块中,前提是没有其他规则阻止合并;例如,视图的ALGORITHM指令优先于derived_merge设置。默认情况下,该标志为on以启用合并。Thederived_mergeflag controls whether the optimizer attempts to merge derived tables, view references, and common table expressions into the outer query block, assuming that no other rule prevents merging; for example, anALGORITHMdirective for a view takes precedence over thederived_mergesetting. By default, the flag isonto enable merging.欲了解更多信息,请参见 第 10.2.2.4 节,“通过合并或物化优化派生表、视图引用和公共表表达式”。For more information, see Section 10.2.2.4, “Optimizing Derived Tables, View References, and Common Table Expressions with Merging or Materialization”.
引擎状态下推标志Engine Condition Pushdown Flags
engine_condition_pushdown(默认on)engine_condition_pushdown(defaulton)控制发动机状态下推。Controls engine condition pushdown.
欲了解更多信息,请参见第 10.2.1.5 节,“引擎条件下推优化”。For more information, see Section 10.2.1.5, “Engine Condition Pushdown Optimization”.
哈希连接标志Hash Join Flags
hash_join(默认on)hash_join(defaulton)在 MySQL 8.4 中无效。请改用
block_nested_loop标志。Has no effect in MySQL 8.4. Use theblock_nested_loopflag, instead.
更多信息,请参见 第 10.2.1.4 节,“哈希连接优化”。For more information, see Section 10.2.1.4, “Hash Join Optimization”.
索引条件下推标志Index Condition Pushdown Flags
index_condition_pushdown(默认on)index_condition_pushdown(defaulton)控制索引条件下推。Controls index condition pushdown.
欲了解更多信息,请参见 第 10.2.1.6 节,“索引条件下推优化”。For more information, see Section 10.2.1.6, “Index Condition Pushdown Optimization”.
索引 扩展 标志Index Extensions Flags
use_index_extensions(默认on)use_index_extensions(defaulton)控制索引扩展的使用。Controls use of index extensions.
欲了解更多信息,请参见 第 10.3.10 节,“使用索引扩展”。For more information, see Section 10.3.10, “Use of Index Extensions”.
索引合并标志Index Merge Flags
index_merge(默认on)index_merge(defaulton)控制所有索引合并优化。Controls all Index Merge optimizations.
index_merge_intersection(默认on)index_merge_intersection(defaulton)控制索引合并交集访问优化。Controls the Index Merge Intersection Access optimization.
index_merge_sort_union(默认on)index_merge_sort_union(defaulton)控制索引合并排序-联合访问优化。Controls the Index Merge Sort-Union Access optimization.
index_merge_union(默认on)index_merge_union(defaulton)控制索引合并联合访问优化。Controls the Index Merge Union Access optimization.
更多信息,请参见第 10.2.1.3 节,“索引合并优化”。For more information, see Section 10.2.1.3, “Index Merge Optimization”.
索引可见性标志Index Visibility Flags
use_invisible_indexes(默认off)use_invisible_indexes(defaultoff)控制不可见索引的使用。Controls use of invisible indexes.
欲了解更多信息,请参见 第 10.3.12 节,“隐形索引”。For more information, see Section 10.3.12, “Invisible Indexes”.
限制优化标志Limit Optimization Flags
prefer_ordering_index(默认on)prefer_ordering_index(defaulton)控制在查询包含
ORDER BY或GROUP BY并带有LIMIT子句的情况下,优化器是否尝试使用有序索引,而不是无序索引、文件排序或其他优化。每当优化器判断使用该优化可以加快查询执行时,将默认执行此优化。Controls whether, in the case of a query having anORDER BYorGROUP BYwith aLIMITclause, the optimizer tries to use an ordered index instead of an unordered index, a filesort, or some other optimization. This optimization is performed by default whenever the optimizer determines that using it would allow for faster execution of the query.由于用于做出此决定的算法无法处理所有可能的情况(部分原因是其假设数据的分布总是或多或少均匀的),因此在某些情况下,这种优化可能并不理想。可以通过将
prefer_ordering_index标志设置为off来禁用此优化。Because the algorithm that makes this determination cannot handle every conceivable case (due in part to the assumption that the distribution of data is always more or less uniform), there are cases in which this optimization may not be desirable. This optimization can be disabled by setting theprefer_ordering_indexflag tooff.
有关更多信息和示例,请参见 第 10.2.1.19 节,“LIMIT 查询优化”。For more information and examples, see Section 10.2.1.19, “LIMIT Query Optimization”.
多范围读取标志Multi-Range Read Flags
控制多范围读取策略。Controls the Multi-Range Read strategy.
mrr_cost_based(默认on)mrr_cost_based(defaulton)如果
mrr=on,则控制基于成本的 MRR 使用。Controls use of cost-based MRR ifmrr=on.
更多信息,请参见 第 10.2.1.11 节,“多范围读取优化”。For more information, see Section 10.2.1.11, “Multi-Range Read Optimization”.
半连接标志Semijoin Flags
duplicateweedout(默认on)duplicateweedout(defaulton)控制半连接重复消除策略。Controls the semijoin Duplicate Weedout strategy.
firstmatch(默认on)firstmatch(defaulton)控制半连接的首匹配策略。Controls the semijoin FirstMatch strategy.
loosescan(默认on)loosescan(defaulton)控制半连接 LooseScan 策略(不要与用于
GROUP BY的松散索引扫描混淆)。Controls the semijoin LooseScan strategy (not to be confused with Loose Index Scan forGROUP BY).semijoin(默认on)semijoin(defaulton)控制所有半连接策略。Controls all semijoin strategies.
这也适用于反连接优化。This also applies to the antijoin optimization.
semijoin、firstmatch、loosescan和duplicateweedout标志可以控制半连接策略。semijoin标志控制是否使用半连接。如果将其设置为on,则firstmatch和loosescan标志将允许对允许的半连接策略进行更精细的控制。Thesemijoin,firstmatch,loosescan, andduplicateweedoutflags enable control over semijoin strategies. Thesemijoinflag controls whether semijoins are used. If it is set toon, thefirstmatchandloosescanflags enable finer control over the permitted semijoin strategies.如果
duplicateweedout半连接策略被禁用,除非所有其他适用策略也被禁用,否则不会使用它。If theduplicateweedoutsemijoin strategy is disabled, it is not used unless all other applicable strategies are also disabled.如果
semijoin和materialization都为on,半连接在适用时也会使用物化。这些标志默认是on。Ifsemijoinandmaterializationare bothon, semijoins also use materialization where applicable. These flags areonby default.更多信息,请参见 使用半连接转换优化 IN 和 EXISTS 子查询谓词。For more information, see Optimizing IN and EXISTS Subquery Predicates with Semijoin Transformations.
设置操作标志Set Operations Flags
hash_set_operations(默认on)hash_set_operations(defaulton)启用针对涉及
EXCEPT和INTERSECT的集合操作的哈希表优化;默认启用。否则,将使用基于临时表的去重方法,如 MySQL 之前的版本中所使用。Enables the hash table optimization for set operations involvingEXCEPTandINTERSECT); enabled by default. Otherwise, temporary table based de-duplication is used, as in previous versions of MySQL.此优化使用的哈希内存量可以通过
set_operations_buffer_size系统变量进行控制;通常增加此值会使使用这些操作的语句执行时间更短。The amount of memory used for hashing by this optimization can be controlled using theset_operations_buffer_sizesystem variable; increasing this generally results in faster execution times for statements using these operations.
跳过扫描标志Skip Scan Flags
更多信息,请参见 跳跃扫描范围访问方法。For more information, see Skip Scan Range Access Method.
子查询物化标志Subquery Materialization Flags
materialization(默认on)materialization(defaulton)控制物化(包括半连接物化)。Controls materialization (including semijoin materialization).
subquery_materialization_cost_based(默认on)subquery_materialization_cost_based(defaulton)使用基于成本的物化选择。Use cost-based materialization choice.
materialization标志控制是否使用子查询物化。如果semijoin和materialization都是on的,半连接在适用时也使用物化。这些标志默认都是on的。Thematerializationflag controls whether subquery materialization is used. Ifsemijoinandmaterializationare bothon, semijoins also use materialization where applicable. These flags areonby default.subquery_materialization_cost_based标志允许控制在子查询物化和IN-到-EXISTS子查询转换之间的选择。如果该标志为on(默认值),优化器将在可以使用任一方法的情况下,基于成本在子查询物化和IN-到-EXISTS子查询转换之间进行选择。如果该标志为off,优化器会选择子查询物化而不是IN-到-EXISTS子查询转换。Thesubquery_materialization_cost_basedflag enables control over the choice between subquery materialization andIN-to-EXISTSsubquery transformation. If the flag ison(the default), the optimizer performs a cost-based choice between subquery materialization andIN-to-EXISTSsubquery transformation if either method could be used. If the flag isoff, the optimizer chooses subquery materialization overIN-to-EXISTSsubquery transformation.更多信息,请参见 第 10.2.2 节,“优化子查询、派生表、视图引用和公共表表达式”。For more information, see Section 10.2.2, “Optimizing Subqueries, Derived Tables, View References, and Common Table Expressions”.
子查询转换标志Subquery Transformation Flags
subquery_to_derived(默认off)subquery_to_derived(defaultoff)优化器在许多情况下能够将
SELECT、WHERE、JOIN或HAVING子句中的标量子查询转换为衍生表的左外连接。(根据衍生表的可空性,这有时可以进一步简化为内连接。)这可以用于满足以下条件的子查询:The optimizer is able in many cases to transform a scalar subquery in aSELECT,WHERE,JOIN, orHAVINGclause into a left outer join on a derived table. (Depending on the nullability of the derived table, this can sometimes be simplified further to an inner join.) This can be done for a subquery which meets the following conditions:子查询不使用任何非确定性函数,例如
RAND()。The subquery does not make use of any nondeterministic functions, such asRAND().子查询不是可以重写为使用
MIN()或MAX()的ANY或ALL子查询。The subquery is not anANYorALLsubquery which can be rewritten to useMIN()orMAX().父查询不会设置用户变量,因为重写它可能会影响执行顺序,如果在同一查询中多次访问该变量,可能会导致意外结果。The parent query does not set a user variable, since rewriting it may affect the order of execution, which could lead to unexpected results if the variable is accessed more than once in the same query.
子查询不应是相关查询,也就是说,它不应引用外部查询中表的列,或包含在外部查询中计算的聚合函数。The subquery should not be correlated, that is, it should not reference a column from a table in the outer query, or contain an aggregate that is evaluated in the outer query.
这个优化也可以应用于作为
IN、NOT IN、EXISTS或NOT EXISTS参数的表子查询,这些子查询不包含GROUP BY。This optimization can also be applied to a table subquery which is the argument toIN,NOT IN,EXISTS, orNOT EXISTS, that does not contain aGROUP BY.此标志的默认值为
off,因为在大多数情况下,启用此优化不会产生显著的性能提升(在许多情况下甚至可能使查询运行得更慢),但你可以通过将subquery_to_derived标志设置为on来启用该优化。它主要用于测试。The default value for this flag isoff, since, in most cases, enabling this optimization does not produce any noticeable improvement in performance (and in many cases can even make queries run more slowly), but you can enable the optimization by setting thesubquery_to_derivedflag toon. It is primarily intended for use in testing.示例,使用标量子查询:Example, using a scalar subquery:
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正如在执行第二个
EXPLAIN语句后立即执行SHOW WARNINGS可以看到的那样,在启用优化后,查询SELECT * FROM t1 WHERE t1.a > (SELECT COUNT(a) FROM t2)会以类似于此处所示的形式被重写:As can be seen from executingSHOW WARNINGSimmediately following the secondEXPLAINstatement, with the optimization enabled, the querySELECT * FROM t1 WHERE t1.a > (SELECT COUNT(a) FROM t2)is rewritten in a form similar to what is shown here:SELECT t1.a FROM t1 JOIN ( SELECT COUNT(t2.a) AS c FROM t2 ) AS d WHERE t1.a > d.c;示例,使用带有
IN (subquery)的查询:Example, using a query withIN (:subquery)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在执行
EXPLAIN对此查询后,检查并简化SHOW WARNINGS的结果显示,当启用subquery_to_derived标志时,SELECT * FROM t1 WHERE t1.b < 0 OR t1.a IN (SELECT t2.a + 1 FROM t2)会被重写为类似此处所示的形式:Checking and simplifying the result ofSHOW WARNINGSafter executingEXPLAINon this query shows that, when thesubquery_to_derivedflag enabled,SELECT * FROM t1 WHERE t1.b < 0 OR t1.a IN (SELECT t2.a + 1 FROM t2)is rewritten in a form similar to what is shown here: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;示例,使用带有
EXISTS (subquery)的查询,以及与前一个示例相同的表和数据:Example, using a query withEXISTS (and the same tables and data as in the previous example:subquery)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如果在启用了
subquery_to_derived后,在查询SHOW WARNINGS上运行EXPLAIN后执行SELECT * FROM t1 WHERE t1.b < 0 OR EXISTS(SELECT * FROM t2 WHERE t2.a = t1.a + 1),并简化结果的第二行,我们可以看到它已被重写为类似于这样的形式:If we executeSHOW WARNINGSafter runningEXPLAINon the querySELECT * FROM t1 WHERE t1.b < 0 OR EXISTS(SELECT * FROM t2 WHERE t2.a = t1.a + 1)whensubquery_to_derivedhas been enabled, and simplify the second row of the result, we see that it has been rewritten in a form which resembles this: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;有关更多信息,请参见第 10.2.2.4 节,“使用合并或物化优化派生表、视图引用和公共表表达式”,以及第 10.2.1.19 节,“LIMIT 查询优化”,以及使用半连接转换优化 IN 和 EXISTS 子查询谓词。For more information, see Section 10.2.2.4, “Optimizing Derived Tables, View References, and Common Table Expressions with Merging or Materialization”, as well as Section 10.2.1.19, “LIMIT Query Optimization”, and Optimizing IN and EXISTS Subquery Predicates with Semijoin Transformations.
当你给 optimizer_switch 赋值时,未提及的标志将保持其当前值。这使得在单条语句中启用或禁用特定的优化器行为成为可能,而不会影响其他行为。该语句不依赖于其他优化器标志是否存在以及它们的值。假设所有索引合并优化都已启用:When you assign a value to
optimizer_switch, flags that
are not mentioned keep their current values. This makes it
possible to enable or disable specific optimizer behaviors in a
single statement without affecting other behaviors. The
statement does not depend on what other optimizer flags exist
and what their values are. Suppose that all Index Merge
optimizations are enabled:
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 访问方法,并且您想检查优化器在不使用这些方法时是否能表现更好,请按如下方式设置变量值:If the server is using the Index Merge Union or Index Merge Sort-Union access methods for certain queries and you want to check whether the optimizer can perform better without them, set the variable value like this:
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