控制优化器策略的一种方法是设置 optimizer_switch 系统变量(参见 第 10.9.2 节,“可切换的优化”)。对该变量的更改会影响随后所有查询的执行;如果希望不同查询有不同的影响,则需要在每个查询之前更改 optimizer_switch。One means of control over optimizer strategies is to set the
optimizer_switch system
variable (see Section 10.9.2, “Switchable Optimizations”).
Changes to this variable affect execution of all subsequent
queries; to affect one query differently from another, it is
necessary to change
optimizer_switch before each
one.
控制优化器的另一种方式是使用优化器提示,可以在单个语句中指定。因为优化器提示是按语句应用的,它们提供了比使用 optimizer_switch 更精细的语句执行计划控制。例如,你可以在一个语句中为一张表启用优化,而为另一张表禁用优化。语句中的提示优先于 optimizer_switch 标志。Another way to control the optimizer is by using optimizer
hints, which can be specified within individual statements.
Because optimizer hints apply on a per-statement basis, they
provide finer control over statement execution plans than can be
achieved using
optimizer_switch. For example,
you can enable an optimization for one table in a statement and
disable the optimization for a different table. Hints within a
statement take precedence over
optimizer_switch flags.
示例:Examples:
SELECT /*+ NO_RANGE_OPTIMIZATION(t3 PRIMARY, f2_idx) */ f1 FROM t3 WHERE f1 > 30 AND f1 < 33; SELECT /*+ BKA(t1) NO_BKA(t2) */ * FROM t1 INNER JOIN t2 WHERE ...; SELECT /*+ NO_ICP(t1, t2) */ * FROM t1 INNER JOIN t2 WHERE ...; SELECT /*+ SEMIJOIN(FIRSTMATCH, LOOSESCAN) */ * FROM t1 ...; EXPLAIN SELECT /*+ NO_ICP(t1) */ * FROM t1 WHERE ...; SELECT /*+ MERGE(dt) */ * FROM (SELECT * FROM t1) AS dt; INSERT /*+ SET_VAR(foreign_key_checks=OFF) */ INTO t2 VALUES(2);
此处描述的优化器提示不同于索引提示,索引提示在 第 10.9.4 节,“索引提示” 中描述。优化器提示和索引提示可以单独使用,也可以同时使用。Optimizer hints, described here, differ from index hints, described in Section 10.9.4, “Index Hints”. Optimizer and index hints may be used separately or together.
优化器提示适用于不同的作用域级别:Optimizer hints apply at different scope levels:
全局:提示影响整个语句Global: The hint affects the entire statement
查询块:提示影响语句中的特定查询块Query block: The hint affects a particular query block within a statement
表级:提示影响查询块中的特定表Table-level: The hint affects a particular table within a query block
索引级:提示影响表中的特定索引Index-level: The hint affects a particular index within a table
下表总结了可用的优化器提示、它们影响的优化器策略以及它们适用的作用域或作用域级别。更多详细信息将在后面提供。The following table summarizes the available optimizer hints, the optimizer strategies they affect, and the scope or scopes at which they apply. More details are given later.
表 10.2 可用的优化器提示Table 10.2 Optimizer Hints Available
| 提示名称Hint Name | 说明Description | 适用范围Applicable Scopes |
|---|---|---|
BKA, NO_BKABKA,
NO_BKA |
影响批量键访问连接处理Affects Batched Key Access join processing | 查询块,表Query block, table |
BNL, NO_BNLBNL,
NO_BNL |
影响哈希连接优化Affects hash join optimization | 查询块,表Query block, table |
DERIVED_CONDITION_PUSHDOWN, NO_DERIVED_CONDITION_PUSHDOWNDERIVED_CONDITION_PUSHDOWN,
NO_DERIVED_CONDITION_PUSHDOWN |
使用或忽略用于物化派生表的派生条件下推优化Use or ignore the derived condition pushdown optimization for materialized derived tables | 查询块,表Query block, table |
GROUP_INDEX, NO_GROUP_INDEXGROUP_INDEX,
NO_GROUP_INDEX |
在 GROUP BY 操作中使用或忽略指定的索引Use or ignore the specified index or indexes for index scans in
GROUP BY operations |
索引Index |
HASH_JOIN, NO_HASH_JOINHASH_JOIN,
NO_HASH_JOIN |
影响哈希连接优化(在 MySQL 8.4 中无效)Affects Hash Join optimization (No effect in MySQL 8.4) | 查询块,表Query block, table |
INDEX, NO_INDEXINDEX,
NO_INDEX |
充当 JOIN_INDEX、GROUP_INDEX 和 ORDER_INDEX 的组合,或充当 NO_JOIN_INDEX、NO_GROUP_INDEX 和 NO_ORDER_INDEX 的组合Acts as the combination of JOIN_INDEX,
GROUP_INDEX, and
ORDER_INDEX, or as the
combination of
NO_JOIN_INDEX,
NO_GROUP_INDEX, and
NO_ORDER_INDEX |
索引Index |
INDEX_MERGE,NO_INDEX_MERGEINDEX_MERGE,
NO_INDEX_MERGE |
影响索引合并优化Affects Index Merge optimization | 表,索引Table, index |
JOIN_FIXED_ORDERJOIN_FIXED_ORDER |
使用 FROM 子句中指定的表顺序作为连接顺序Use table order specified in FROM clause for join
order |
查询块Query block |
JOIN_INDEX, NO_JOIN_INDEXJOIN_INDEX,
NO_JOIN_INDEX |
对任何访问方法使用或忽略指定的索引或索引集合Use or ignore the specified index or indexes for any access method | 索引Index |
JOIN_ORDERJOIN_ORDER |
使用提示中指定的表顺序进行连接顺序Use table order specified in hint for join order | 查询块Query block |
JOIN_PREFIXJOIN_PREFIX |
使用提示中指定的表顺序作为连接顺序的第一个表Use table order specified in hint for first tables of join order | 查询块Query block |
JOIN_SUFFIXJOIN_SUFFIX |
使用提示中指定的表顺序来进行最后的连接表顺序Use table order specified in hint for last tables of join order | 查询块Query block |
MAX_EXECUTION_TIMEMAX_EXECUTION_TIME |
限制语句执行时间Limits statement execution time | 全球Global |
MERGE, NO_MERGEMERGE,
NO_MERGE |
影响派生表/视图合并到外部查询块Affects derived table/view merging into outer query block | 表Table |
MRR, NO_MRRMRR,
NO_MRR |
影响多范围读取优化Affects Multi-Range Read optimization | 表,索引Table, index |
NO_ICPNO_ICP |
影响索引条件下推优化Affects Index Condition Pushdown optimization | 表,索引Table, index |
NO_RANGE_OPTIMIZATIONNO_RANGE_OPTIMIZATION |
影响范围优化Affects range optimization | 表,索引Table, index |
ORDER_INDEX, NO_ORDER_INDEXORDER_INDEX,
NO_ORDER_INDEX |
使用或忽略指定的索引进行行排序Use or ignore the specified index or indexes for sorting rows | 索引Index |
QB_NAMEQB_NAME |
为查询块分配名称Assigns name to query block | 查询块Query block |
RESOURCE_GROUPRESOURCE_GROUP |
在语句执行期间设置资源组Set resource group during statement execution | 全球Global |
SEMIJOIN, NO_SEMIJOINSEMIJOIN,
NO_SEMIJOIN |
影响半连接和反连接策略Affects semijoin and antijoin strategies | 查询块Query block |
SKIP_SCAN, NO_SKIP_SCANSKIP_SCAN,
NO_SKIP_SCAN |
影响跳过扫描优化Affects Skip Scan optimization | 表,索引Table, index |
SET_VARSET_VAR |
在语句执行期间设置变量Set variable during statement execution | 全球Global |
SUBQUERYSUBQUERY |
影响物化,IN-到-EXISTS 子查询策略Affects materialization,
IN-to-EXISTS
subquery strategies |
查询块Query block |
禁用优化会阻止优化器使用它。启用优化意味着如果适用于语句执行,优化器可以自由使用该策略,但并不意味着优化器一定会使用它。Disabling an optimization prevents the optimizer from using it. Enabling an optimization means the optimizer is free to use the strategy if it applies to statement execution, not that the optimizer necessarily uses it.
MySQL 支持在 SQL 语句中使用注释,如 第 11.7 节,“注释” 所述。优化器提示必须在 /* ... */ 注释中指定。也就是说,优化器提示使用 /*+ ... */ C 风格注释语法的一种变体,并且在 /* 注释开头序列之后有一个 + 字符。示例:MySQL supports comments in SQL statements as described in
Section 11.7, “Comments”. Optimizer hints must be specified
within /*+ ... */ comments. That is,
optimizer hints use a variant of /* ... */
C-style comment syntax, with a + character
following the /* comment opening sequence.
Examples:
/*+ BKA(t1) */ /*+ BNL(t1, t2) */ /*+ NO_RANGE_OPTIMIZATION(t4 PRIMARY) */ /*+ QB_NAME(qb2) */
在 + 字符之后允许有空白字符。Whitespace is permitted after the +
character.
解析器在 SELECT、UPDATE、INSERT、REPLACE 和 DELETE 语句的初始关键字之后识别优化器提示注释。提示允许在以下上下文中使用:The parser recognizes optimizer hint comments after the
initial keyword of SELECT,
UPDATE,
INSERT,
REPLACE, and
DELETE statements. Hints are
permitted in these contexts:
在查询和数据更改语句的开头:At the beginning of query and data change statements:
SELECT /*+ ... */ ... INSERT /*+ ... */ ... REPLACE /*+ ... */ ... UPDATE /*+ ... */ ... DELETE /*+ ... */ ...
在查询块的开头:At the beginning of query blocks:
(SELECT /*+ ... */ ... ) (SELECT ... ) UNION (SELECT /*+ ... */ ... ) (SELECT /*+ ... */ ... ) UNION (SELECT /*+ ... */ ... ) UPDATE ... WHERE x IN (SELECT /*+ ... */ ...) INSERT ... SELECT /*+ ... */ ...
在以
EXPLAIN开头的可提示语句中。例如:In hintable statements prefaced byEXPLAIN. For example:EXPLAIN SELECT /*+ ... */ ... EXPLAIN UPDATE ... WHERE x IN (SELECT /*+ ... */ ...)
这意味着你可以使用
EXPLAIN来查看优化器提示如何影响执行计划。在EXPLAIN之后立即使用SHOW WARNINGS可以查看提示的使用情况。随后EXPLAIN显示的扩展SHOW WARNINGS输出指示了哪些提示被使用。被忽略的提示不会显示。The implication is that you can useEXPLAINto see how optimizer hints affect execution plans. UseSHOW WARNINGSimmediately afterEXPLAINto see how hints are used. The extendedEXPLAINoutput displayed by a followingSHOW WARNINGSindicates which hints were used. Ignored hints are not displayed.
提示注释可以包含多个提示,但查询块不能包含多个提示注释。这是有效的:A hint comment may contain multiple hints, but a query block cannot contain multiple hint comments. This is valid:
SELECT /*+ BNL(t1) BKA(t2) */ ...
但这是无效的:But this is invalid:
SELECT /*+ BNL(t1) */ /* BKA(t2) */ ...
当提示注释包含多个提示时,可能会出现重复和冲突的情况。适用以下一般指南。对于特定的提示类型,可能适用附加规则,如提示描述中所示。When a hint comment contains multiple hints, the possibility of duplicates and conflicts exists. The following general guidelines apply. For specific hint types, additional rules may apply, as indicated in the hint descriptions.
重复提示:对于像
/*+ MRR(idx1) MRR(idx1) */这样的提示,MySQL 使用第一个提示并发出关于重复提示的警告。Duplicate hints: For a hint such as/*+ MRR(idx1) MRR(idx1) */, MySQL uses the first hint and issues a warning about the duplicate hint.冲突提示:对于像
/*+ MRR(idx1) NO_MRR(idx1) */这样的提示,MySQL 使用第一个提示并发出关于第二个冲突提示的警告。Conflicting hints: For a hint such as/*+ MRR(idx1) NO_MRR(idx1) */, MySQL uses the first hint and issues a warning about the second conflicting hint.
查询块名称是标识符,并遵循关于名称有效性和如何引用它们的常规规则(参见 第 11.2 节,“模式对象名称”)。Query block names are identifiers and follow the usual rules about what names are valid and how to quote them (see Section 11.2, “Schema Object Names”).
提示名称、查询块名称和策略名称不区分大小写。对表和索引名称的引用遵循常规标识符的大小写敏感性规则(参见 第 11.2.3 节,“标识符大小写敏感性”)。Hint names, query block names, and strategy names are not case-sensitive. References to table and index names follow the usual identifier case-sensitivity rules (see Section 11.2.3, “Identifier Case Sensitivity”).
连接顺序提示会影响优化器连接表的顺序。Join-order hints affect the order in which the optimizer joins tables.
JOIN_FIXED_ORDER 提示的语法:Syntax of the
JOIN_FIXED_ORDER hint:
hint_name([@query_block_name])
其他连接顺序提示的语法:Syntax of other join-order hints:
hint_name([@query_block_name]tbl_name[,tbl_name] ...)hint_name(tbl_name[@query_block_name] [,tbl_name[@query_block_name]] ...)
语法涉及以下术语:The syntax refers to these terms:
hint_name:允许使用的提示名称如下:hint_name: These hint names are permitted:JOIN_FIXED_ORDER:强制优化器按照FROM子句中出现的顺序连接表。这与指定SELECT STRAIGHT_JOIN相同。JOIN_FIXED_ORDER: Force the optimizer to join tables using the order in which they appear in theFROMclause. This is the same as specifyingSELECT STRAIGHT_JOIN.JOIN_ORDER:指示优化器按照指定的表顺序进行连接。该提示适用于指定的表。优化器可能会将未在连接顺序中命名的表放置在指定表之间或其他位置。JOIN_ORDER: Instruct the optimizer to join tables using the specified table order. The hint applies to the named tables. The optimizer may place tables that are not named anywhere in the join order, including between specified tables.JOIN_PREFIX:指示优化器在连接执行计划的前几个表中使用指定的表顺序进行表连接。此提示适用于指定的表。优化器会将所有其他表放在指定表之后。JOIN_PREFIX: Instruct the optimizer to join tables using the specified table order for the first tables of the join execution plan. The hint applies to the named tables. The optimizer places all other tables after the named tables.JOIN_SUFFIX:指示优化器在连接执行计划的最后几个表中使用指定的表顺序进行表连接。此提示适用于指定的表。优化器会将所有其他表放在指定表之前。JOIN_SUFFIX: Instruct the optimizer to join tables using the specified table order for the last tables of the join execution plan. The hint applies to the named tables. The optimizer places all other tables before the named tables.
tbl_name:语句中使用的表名。表示该名称提示适用于它所指的所有表。JOIN_FIXED_ORDER提示没有指定表名,并且适用于其出现的查询块的FROM子句中的所有表。tbl_name: The name of a table used in the statement. A hint that names tables applies to all tables that it names. TheJOIN_FIXED_ORDERhint names no tables and applies to all tables in theFROMclause of the query block in which it occurs.如果表有别名,提示必须引用别名,而不是表名。If a table has an alias, hints must refer to the alias, not the table name.
提示中的表名不能带有模式名。Table names in hints cannot be qualified with schema names.
query_block_name:提示适用于的查询块。如果提示中不包含前导的@,则提示适用于其出现的查询块。对于query_block_name语法,提示适用于指定查询块中的指定表。要为查询块分配名称,请参阅 为查询块命名的优化器提示。tbl_name@query_block_namequery_block_name: The query block to which the hint applies. If the hint includes no leading@, the hint applies to the query block in which it occurs. Forquery_block_namesyntax, the hint applies to the named table in the named query block. To assign a name to a query block, see Optimizer Hints for Naming Query Blocks.tbl_name@query_block_name
示例:Example:
SELECT
/*+ JOIN_PREFIX(t2, t5@subq2, t4@subq1)
JOIN_ORDER(t4@subq1, t3)
JOIN_SUFFIX(t1) */
COUNT(*) FROM t1 JOIN t2 JOIN t3
WHERE t1.f1 IN (SELECT /*+ QB_NAME(subq1) */ f1 FROM t4)
AND t2.f1 IN (SELECT /*+ QB_NAME(subq2) */ f1 FROM t5);
提示控制合并到外部查询块的半连接表的行为。如果子查询 subq1 和 subq2 被转换为半连接,则表 t4@subq1 和 t5@subq2 会合并到外部查询块。在这种情况下,外部查询块中指定的提示会控制 t4@subq1、t5@subq2 表的行为。Hints control the behavior of semijoin tables that are merged
to the outer query block. If subqueries
subq1 and subq2 are
converted to semijoins, tables t4@subq1 and
t5@subq2 are merged to the outer query
block. In this case, the hint specified in the outer query
block controls the behavior of t4@subq1,
t5@subq2 tables.
优化器根据以下原则解析连接顺序提示:The optimizer resolves join-order hints according to these principles:
多个提示实例Multiple hint instances
每种类型的
JOIN_PREFIX和JOIN_SUFFIX提示只会应用一次。之后的同类型提示将被忽略并发出警告。JOIN_ORDER可以指定多次。Only oneJOIN_PREFIXandJOIN_SUFFIXhint of each type are applied. Any later hints of the same type are ignored with a warning.JOIN_ORDERcan be specified several times.示例:Examples:
/*+ JOIN_PREFIX(t1) JOIN_PREFIX(t2) */
第二个
JOIN_PREFIX提示将被忽略并发出警告。The secondJOIN_PREFIXhint is ignored with a warning./*+ JOIN_PREFIX(t1) JOIN_SUFFIX(t2) */
两个提示都是适用的。没有出现警告。Both hints are applicable. No warning occurs.
/*+ JOIN_ORDER(t1, t2) JOIN_ORDER(t2, t3) */
两个提示都是适用的。没有出现警告。Both hints are applicable. No warning occurs.
冲突的提示Conflicting hints
在某些情况下,提示可能会发生冲突,例如当
JOIN_ORDER和JOIN_PREFIX的表顺序无法同时应用时:In some cases hints can conflict, such as whenJOIN_ORDERandJOIN_PREFIXhave table orders that are impossible to apply at the same time:SELECT /*+ JOIN_ORDER(t1, t2) JOIN_PREFIX(t2, t1) */ ... FROM t1, t2;
在这种情况下,首先指定的提示会被应用,而后续冲突的提示将被忽略且不会发出警告。一个有效但无法应用的提示也会被静默忽略,不会发出警告。In this case, the first specified hint is applied and subsequent conflicting hints are ignored with no warning. A valid hint that is impossible to apply is silently ignored with no warning.
被忽略的提示Ignored hints
如果提示中指定的表存在循环依赖,该提示将被忽略。A hint is ignored if a table specified in the hint has a circular dependency.
示例:Example:
/*+ JOIN_ORDER(t1, t2) JOIN_PREFIX(t2, t1) */
JOIN_ORDER提示将表t2设置为依赖于t1。JOIN_PREFIX提示被忽略,因为表t1不能依赖于t2。被忽略的提示不会在扩展的EXPLAIN输出中显示。TheJOIN_ORDERhint sets tablet2dependent ont1. TheJOIN_PREFIXhint is ignored because tablet1cannot be dependent ont2. Ignored hints are not displayed in extendedEXPLAINoutput.与
const表的交互Interaction withconsttablesMySQL 优化器会在连接顺序中首先放置
const表,并且const表的位置不能被提示所影响。连接顺序提示中对const表的引用会被忽略,尽管该提示仍然有效。例如,这些是等效的:The MySQL optimizer placesconsttables first in the join order, and the position of aconsttable cannot be affected by hints. References toconsttables in join-order hints are ignored, although the hint is still applicable. For example, these are equivalent:JOIN_ORDER(t1,
const_tbl, t2) JOIN_ORDER(t1, t2)在扩展
EXPLAIN输出中显示的已接受提示会包括按指定顺序的const表。Accepted hints shown in extendedEXPLAINoutput includeconsttables as they were specified.与连接操作类型的交互Interaction with types of join operations
MySQL 支持多种类型的连接:
LEFT、RIGHT、INNER、CROSS、STRAIGHT_JOIN。与指定连接类型冲突的提示会被忽略且不会发出警告。MySQL supports several type of joins:LEFT,RIGHT,INNER,CROSS,STRAIGHT_JOIN. A hint that conflicts with the specified type of join is ignored with no warning.示例:Example:
SELECT /*+ JOIN_PREFIX(t1, t2) */FROM t2 LEFT JOIN t1;
这里发生了提示中请求的连接顺序与
LEFT JOIN所需顺序之间的冲突。该提示被忽略且不会发出警告。Here a conflict occurs between the requested join order in the hint and the order required by theLEFT JOIN. The hint is ignored with no warning.
表级提示影响:Table-level hints affect:
使用块嵌套循环(BNL)和批量键访问(BKA)连接处理算法(参见 第 10.2.1.12 节,“块嵌套循环和批量键访问连接”)。Use of the Block Nested-Loop (BNL) and Batched Key Access (BKA) join-processing algorithms (see Section 10.2.1.12, “Block Nested-Loop and Batched Key Access Joins”).
无论是衍生表、视图引用,还是公用表表达式,是否应该合并到外部查询块中,或者使用内部临时表实现物化。Whether derived tables, view references, or common table expressions should be merged into the outer query block, or materialized using an internal temporary table.
使用派生表条件下推优化。参见 第 10.2.2.5 节,“派生条件下推优化”。Use of the derived table condition pushdown optimization. See Section 10.2.2.5, “Derived Condition Pushdown Optimization”.
这些提示类型适用于特定表,或查询块中的所有表。These hint types apply to specific tables, or all tables in a query block.
表级提示的语法:Syntax of table-level hints:
hint_name([@query_block_name] [tbl_name[,tbl_name] ...])hint_name([tbl_name@query_block_name[,tbl_name@query_block_name] ...])
语法涉及以下术语:The syntax refers to these terms:
hint_name:允许使用的提示名称如下:hint_name: These hint names are permitted:BKA,NO_BKA:为指定表启用或禁用批量键访问。BKA,NO_BKA: Enable or disable batched key access for the specified tables.BNL,NO_BNL:启用或禁用哈希连接优化。BNL,NO_BNL: Enable and disable the hash join optimization.DERIVED_CONDITION_PUSHDOWN,NO_DERIVED_CONDITION_PUSHDOWN:启用或禁用对指定表使用派生表条件下推。如需更多信息,请参见 第 10.2.2.5 节,“派生条件下推优化”。DERIVED_CONDITION_PUSHDOWN,NO_DERIVED_CONDITION_PUSHDOWN: Enable or disable use of derived table condition pushdown for the specified tables. For more information, see Section 10.2.2.5, “Derived Condition Pushdown Optimization”.HASH_JOIN,NO_HASH_JOIN:这些提示在 MySQL 8.4 中没有效果;请改用BNL或NO_BNL。HASH_JOIN,NO_HASH_JOIN: These hints have no effect in MySQL 8.4; useBNLorNO_BNLinstead.MERGE,NO_MERGE:为指定的表、视图引用或公共表表达式启用合并;或禁用合并而改用物化。MERGE,NO_MERGE: Enable merging for the specified tables, view references or common table expressions; or disable merging and use materialization instead.
Note要使用块嵌套循环或批量键访问提示为外连接的任何内部表启用连接缓冲,必须为外连接的所有内部表启用连接缓冲。To use a block nested loop or batched key access hint to enable join buffering for any inner table of an outer join, join buffering must be enabled for all inner tables of the outer join.
tbl_name:语句中使用的表的名称。该提示适用于它所指定的所有表。如果提示未指定任何表,则适用于其出现的查询块中的所有表。tbl_name: The name of a table used in the statement. The hint applies to all tables that it names. If the hint names no tables, it applies to all tables of the query block in which it occurs.如果表有别名,提示必须引用别名,而不是表名。If a table has an alias, hints must refer to the alias, not the table name.
提示中的表名不能带有模式名。Table names in hints cannot be qualified with schema names.
query_block_name:提示适用于的查询块。如果提示中不包含前导的@,则提示适用于其出现的查询块。对于query_block_name语法,提示适用于指定查询块中的指定表。要为查询块分配名称,请参阅 为查询块命名的优化器提示。tbl_name@query_block_namequery_block_name: The query block to which the hint applies. If the hint includes no leading@, the hint applies to the query block in which it occurs. Forquery_block_namesyntax, the hint applies to the named table in the named query block. To assign a name to a query block, see Optimizer Hints for Naming Query Blocks.tbl_name@query_block_name
示例:Examples:
SELECT /*+ NO_BKA(t1, t2) */ t1.* FROM t1 INNER JOIN t2 INNER JOIN t3; SELECT /*+ NO_BNL() BKA(t1) */ t1.* FROM t1 INNER JOIN t2 INNER JOIN t3; SELECT /*+ NO_MERGE(dt) */ * FROM (SELECT * FROM t1) AS dt;
表级提示适用于从前一个表接收记录的表,而不是发送表。考虑以下语句:A table-level hint applies to tables that receive records from previous tables, not sender tables. Consider this statement:
SELECT /*+ BNL(t2) */ FROM t1, t2;
如果优化器选择先处理t1,它会在开始读取t2之前,通过缓冲t1的行来对t2应用块嵌套循环连接。如果优化器改为选择先处理t2,则提示无效,因为t2是发送表。If the optimizer chooses to process t1
first, it applies a Block Nested-Loop join to
t2 by buffering the rows from
t1 before starting to read from
t2. If the optimizer instead chooses to
process t2 first, the hint has no effect
because t2 is a sender table.
对于MERGE和NO_MERGE提示,适用以下优先规则:For the MERGE and
NO_MERGE hints, these
precedence rules apply:
提示优先于任何非技术约束的优化器启发式方法。(如果提供提示作为建议没有效果,则说明优化器有理由忽略它。)A hint takes precedence over any optimizer heuristic that is not a technical constraint. (If providing a hint as a suggestion has no effect, the optimizer has a reason for ignoring it.)
提示优先于
derived_merge标志,该标志属于optimizer_switch系统变量。A hint takes precedence over thederived_mergeflag of theoptimizer_switchsystem variable.对于视图引用,视图定义中的
ALGORITHM={MERGE|TEMPTABLE}子句优先于引用该视图的查询中指定的提示。For view references, anALGORITHM={MERGE|TEMPTABLE}clause in the view definition takes precedence over a hint specified in the query referencing the view.
索引级提示会影响优化器对特定表或索引使用的索引处理策略。这些提示类型会影响索引条件下推(ICP)、多范围读取(MRR)、索引合并以及范围优化的使用(参见 第 10.2.1 节,“优化 SELECT 语句”)。Index-level hints affect which index-processing strategies the optimizer uses for particular tables or indexes. These hint types affect use of Index Condition Pushdown (ICP), Multi-Range Read (MRR), Index Merge, and range optimizations (see Section 10.2.1, “Optimizing SELECT Statements”).
索引级提示的语法:Syntax of index-level hints:
hint_name([@query_block_name]tbl_name[index_name[,index_name] ...])hint_name(tbl_name@query_block_name[index_name[,index_name] ...])
语法涉及以下术语:The syntax refers to these terms:
hint_name:允许使用的提示名称如下:hint_name: These hint names are permitted:GROUP_INDEX,NO_GROUP_INDEX:启用或禁用指定索引以用于GROUP BY操作的索引扫描。等效于索引提示FORCE INDEX FOR GROUP BY、IGNORE INDEX FOR GROUP BY。GROUP_INDEX,NO_GROUP_INDEX: Enable or disable the specified index or indexes for index scans forGROUP BYoperations. Equivalent to the index hintsFORCE INDEX FOR GROUP BY,IGNORE INDEX FOR GROUP BY.INDEX,NO_INDEX:作用相当于JOIN_INDEX、GROUP_INDEX和ORDER_INDEX的组合,强制服务器在任何和所有范围内使用指定的索引,或者相当于NO_JOIN_INDEX、NO_GROUP_INDEX和NO_ORDER_INDEX的组合,使服务器在任何和所有范围内忽略指定的索引。相当于FORCE INDEX、IGNORE INDEX。INDEX,NO_INDEX: Acts as the combination ofJOIN_INDEX,GROUP_INDEX, andORDER_INDEX, forcing the server to use the specified index or indexes for any and all scopes, or as the combination ofNO_JOIN_INDEX,NO_GROUP_INDEX, andNO_ORDER_INDEX, which causes the server to ignore the specified index or indexes for any and all scopes. Equivalent toFORCE INDEX,IGNORE INDEX.INDEX_MERGE,NO_INDEX_MERGE:为指定的表或索引启用或禁用索引合并访问方法。有关此访问方法的信息,请参见 第 10.2.1.3 节,“索引合并优化”。这些提示适用于所有三种索引合并算法。INDEX_MERGE,NO_INDEX_MERGE: Enable or disable the Index Merge access method for the specified table or indexes. For information about this access method, see Section 10.2.1.3, “Index Merge Optimization”. These hints apply to all three Index Merge algorithms.INDEX_MERGE提示强制优化器对指定表使用指定索引集的索引合并。如果未指定索引,优化器会考虑所有可能的索引组合并选择成本最低的组合。如果索引组合不适用于给定语句,则该提示可能会被忽略。TheINDEX_MERGEhint forces the optimizer to use Index Merge for the specified table using the specified set of indexes. If no index is specified, the optimizer considers all possible index combinations and selects the least expensive one. The hint may be ignored if the index combination is inapplicable to the given statement.NO_INDEX_MERGE提示禁止涉及任意指定索引的索引合并组合。如果提示未指定索引,则该表不允许使用索引合并。TheNO_INDEX_MERGEhint disables Index Merge combinations that involve any of the specified indexes. If the hint specifies no indexes, Index Merge is not permitted for the table.JOIN_INDEX,NO_JOIN_INDEX:强制 MySQL 对任何访问方法使用或忽略指定的索引,例如ref、range、index_merge等。等同于FORCE INDEX FOR JOIN、IGNORE INDEX FOR JOIN。JOIN_INDEX,NO_JOIN_INDEX: Forces MySQL to use or ignore the specified index or indexes for any access method, such asref,range,index_merge, and so on. Equivalent toFORCE INDEX FOR JOIN,IGNORE INDEX FOR JOIN.MRR,NO_MRR:启用或禁用指定表或索引的 MRR。MRR 提示仅适用于InnoDB和MyISAM表。有关此访问方法的信息,请参见 第 10.2.1.11 节,“多范围读取优化”。MRR,NO_MRR: Enable or disable MRR for the specified table or indexes. MRR hints apply only toInnoDBandMyISAMtables. For information about this access method, see Section 10.2.1.11, “Multi-Range Read Optimization”.NO_ICP:禁用指定表或索引的 ICP。默认情况下,ICP 是一种候选优化策略,因此没有启用它的提示。有关此访问方法的信息,请参见 第 10.2.1.6 节,“索引条件下推优化”。NO_ICP: Disable ICP for the specified table or indexes. By default, ICP is a candidate optimization strategy, so there is no hint for enabling it. For information about this access method, see Section 10.2.1.6, “Index Condition Pushdown Optimization”.NO_RANGE_OPTIMIZATION:禁用指定表或索引的索引范围访问。此提示还会禁用该表或索引的索引合并和松散索引扫描。默认情况下,范围访问是一种候选优化策略,因此没有用于启用它的提示。NO_RANGE_OPTIMIZATION: Disable index range access for the specified table or indexes. This hint also disables Index Merge and Loose Index Scan for the table or indexes. By default, range access is a candidate optimization strategy, so there is no hint for enabling it.当范围数量可能很高且范围优化需要大量资源时,这个提示可能会很有用。This hint may be useful when the number of ranges may be high and range optimization would require many resources.
ORDER_INDEX,NO_ORDER_INDEX:使 MySQL 使用或忽略用于排序行的指定索引。等同于FORCE INDEX FOR ORDER BY、IGNORE INDEX FOR ORDER BY。ORDER_INDEX,NO_ORDER_INDEX: Cause MySQL to use or to ignore the specified index or indexes for sorting rows. Equivalent toFORCE INDEX FOR ORDER BY,IGNORE INDEX FOR ORDER BY.SKIP_SCAN,NO_SKIP_SCAN:为指定的表或索引启用或禁用跳跃扫描访问方法。有关此访问方法的信息,请参阅 跳跃扫描范围访问方法。SKIP_SCAN,NO_SKIP_SCAN: Enable or disable the Skip Scan access method for the specified table or indexes. For information about this access method, see Skip Scan Range Access Method.SKIP_SCAN提示强制优化器对指定表使用指定的一组索引进行 Skip Scan。如果未指定索引,优化器将考虑所有可能的索引并选择成本最低的一个。如果索引不适用于给定语句,该提示可能被忽略。TheSKIP_SCANhint forces the optimizer to use Skip Scan for the specified table using the specified set of indexes. If no index is specified, the optimizer considers all possible indexes and selects the least expensive one. The hint may be ignored if the index is inapplicable to the given statement.NO_SKIP_SCAN提示禁用指定索引的 Skip Scan。如果提示未指定索引,则该表不允许使用 Skip Scan。TheNO_SKIP_SCANhint disables Skip Scan for the specified indexes. If the hint specifies no indexes, Skip Scan is not permitted for the table.
tbl_name:提示适用的表。tbl_name: The table to which the hint applies.index_name:命名表中索引的名称。该提示适用于它所指定的所有索引。如果提示未指定任何索引,则适用于表中的所有索引。index_name: The name of an index in the named table. The hint applies to all indexes that it names. If the hint names no indexes, it applies to all indexes in the table.要引用主键,请使用名称
PRIMARY。要查看表的索引名称,请使用SHOW INDEX。To refer to a primary key, use the namePRIMARY. To see the index names for a table, useSHOW INDEX.query_block_name:提示适用于的查询块。如果提示中不包含前导的@,则提示适用于其出现的查询块。对于query_block_name语法,提示适用于指定查询块中的指定表。要为查询块分配名称,请参阅 为查询块命名的优化器提示。tbl_name@query_block_namequery_block_name: The query block to which the hint applies. If the hint includes no leading@, the hint applies to the query block in which it occurs. Forquery_block_namesyntax, the hint applies to the named table in the named query block. To assign a name to a query block, see Optimizer Hints for Naming Query Blocks.tbl_name@query_block_name
示例:Examples:
SELECT /*+ INDEX_MERGE(t1 f3, PRIMARY) */ f2 FROM t1 WHERE f1 = 'o' AND f2 = f3 AND f3 <= 4; SELECT /*+ MRR(t1) */ * FROM t1 WHERE f2 <= 3 AND 3 <= f3; SELECT /*+ NO_RANGE_OPTIMIZATION(t3 PRIMARY, f2_idx) */ f1 FROM t3 WHERE f1 > 30 AND f1 < 33; INSERT INTO t3(f1, f2, f3) (SELECT /*+ NO_ICP(t2) */ t2.f1, t2.f2, t2.f3 FROM t1,t2 WHERE t1.f1=t2.f1 AND t2.f2 BETWEEN t1.f1 AND t1.f2 AND t2.f2 + 1 >= t1.f1 + 1); SELECT /*+ SKIP_SCAN(t1 PRIMARY) */ f1, f2 FROM t1 WHERE f2 > 40;
以下示例使用索引合并提示,但其他索引级提示在提示忽略和优化器提示相对于optimizer_switch系统变量或索引提示的优先级方面遵循相同原则。The following examples use the Index Merge hints, but other
index-level hints follow the same principles regarding hint
ignoring and precedence of optimizer hints in relation to the
optimizer_switch system
variable or index hints.
假设表 t1 有列 a、b、c 和 d;并且在 a、b 和 c 上分别存在名为 i_a、i_b 和 i_c 的索引:Assume that table t1 has columns
a, b,
c, and d; and that
indexes named i_a, i_b,
and i_c exist on a,
b, and c, respectively:
SELECT /*+ INDEX_MERGE(t1 i_a, i_b, i_c)*/ * FROM t1 WHERE a = 1 AND b = 2 AND c = 3 AND d = 4;
在这种情况下,(i_a, i_b, i_c) 使用索引合并。Index Merge is used for (i_a, i_b, i_c) in
this case.
SELECT /*+ INDEX_MERGE(t1 i_a, i_b, i_c)*/ * FROM t1 WHERE b = 1 AND c = 2 AND d = 3;
在这种情况下,(i_b, i_c) 使用索引合并。Index Merge is used for (i_b, i_c) in this
case.
/*+ INDEX_MERGE(t1 i_a, i_b) NO_INDEX_MERGE(t1 i_b) */
NO_INDEX_MERGE 被忽略,因为同一表已有前置提示。NO_INDEX_MERGE is ignored
because there is a preceding hint for the same table.
/*+ NO_INDEX_MERGE(t1 i_a, i_b) INDEX_MERGE(t1 i_b) */
INDEX_MERGE 被忽略,因为同一张表之前已经有一个提示。INDEX_MERGE is ignored
because there is a preceding hint for the same table.
对于 INDEX_MERGE 和 NO_INDEX_MERGE 优化器提示,适用以下优先规则:For the INDEX_MERGE and
NO_INDEX_MERGE optimizer
hints, these precedence rules apply:
如果指定了优化器提示并且适用,它将优先于
optimizer_switch系统变量的 Index Merge 相关标志。If an optimizer hint is specified and is applicable, it takes precedence over the Index Merge-related flags of theoptimizer_switchsystem variable.SET optimizer_switch='index_merge_intersection=off'; SELECT /*+ INDEX_MERGE(t1 i_b, i_c) */ * FROM t1 WHERE b = 1 AND c = 2 AND d = 3;
提示优先于
optimizer_switch。在这种情况下,(i_b, i_c)使用索引合并。The hint takes precedence overoptimizer_switch. Index Merge is used for(i_b, i_c)in this case.SET optimizer_switch='index_merge_intersection=on'; SELECT /*+ INDEX_MERGE(t1 i_b) */ * FROM t1 WHERE b = 1 AND c = 2 AND d = 3;
提示仅指定了一个索引,因此不适用,并且
optimizer_switch标志(on)生效。如果优化器评估认为成本高效,则使用索引合并。The hint specifies only one index, so it is inapplicable, and theoptimizer_switchflag (on) applies. Index Merge is used if the optimizer assesses it to be cost efficient.SET optimizer_switch='index_merge_intersection=off'; SELECT /*+ INDEX_MERGE(t1 i_b) */ * FROM t1 WHERE b = 1 AND c = 2 AND d = 3;
提示仅指定了一个索引,因此不适用,并且
optimizer_switch标志(off)生效。不使用索引合并。The hint specifies only one index, so it is inapplicable, and theoptimizer_switchflag (off) applies. Index Merge is not used.索引级优化器提示
GROUP_INDEX、INDEX、JOIN_INDEX和ORDER_INDEX都优先于相应的FORCE INDEX提示;也就是说,它们会导致FORCE INDEX提示被忽略。同样,NO_GROUP_INDEX、NO_INDEX、NO_JOIN_INDEX和NO_ORDER_INDEX提示也优先于任何IGNORE INDEX等效提示,也会导致它们被忽略。The index-level optimizer hintsGROUP_INDEX,INDEX,JOIN_INDEX, andORDER_INDEXall take precedence over the equivalentFORCE INDEXhints; that is, they cause theFORCE INDEXhints to be ignored. Likewise, theNO_GROUP_INDEX,NO_INDEX,NO_JOIN_INDEX, andNO_ORDER_INDEXhints all take precedence over anyIGNORE INDEXequivalents, also causing them to be ignored.索引级优化器提示
GROUP_INDEX、NO_GROUP_INDEX、INDEX、NO_INDEX、JOIN_INDEX、NO_JOIN_INDEX、ORDER_INDEX和NO_ORDER_INDEX提示优先于所有其他优化器提示,包括其他索引级优化器提示。任何其他优化器提示仅应用于这些提示允许的索引。The index-level optimizer hintsGROUP_INDEX,NO_GROUP_INDEX,INDEX,NO_INDEX,JOIN_INDEX,NO_JOIN_INDEX,ORDER_INDEX, andNO_ORDER_INDEXhints all take precedence over all other optimizer hints, including other index-level optimizer hints. Any other optimizer hints are applied only to the indexes permitted by these.GROUP_INDEX、INDEX、JOIN_INDEX和ORDER_INDEX提示都等同于FORCE INDEX,而不是USE INDEX。这是因为使用一个或多个这些提示意味着只有在无法使用命名索引之一查找表中的行时才会进行表扫描。要让 MySQL 使用与给定USE INDEX实例相同的索引或索引集,可以使用NO_INDEX、NO_JOIN_INDEX、NO_GROUP_INDEX、NO_ORDER_INDEX或这些组合中的某些选项。TheGROUP_INDEX,INDEX,JOIN_INDEX, andORDER_INDEXhints are all equivalent toFORCE INDEXand not toUSE INDEX. This is because using one or more of these hints means that a table scan is used only if there is no way to use one of the named indexes to find rows in the table. To cause MySQL to use the same index or set of indexes as with a given instance ofUSE INDEX, you can useNO_INDEX,NO_JOIN_INDEX,NO_GROUP_INDEX,NO_ORDER_INDEX, or some combination of these.要复制查询
USE INDEX中SELECT a,c FROM t1 USE INDEX FOR ORDER BY (i_a) ORDER BY a的效果,可以使用NO_ORDER_INDEX优化器提示来覆盖表上的所有索引,除了所需的索引,如下所示:To replicate the effect thatUSE INDEXhas in the querySELECT a,c FROM t1 USE INDEX FOR ORDER BY (i_a) ORDER BY a, you can use theNO_ORDER_INDEXoptimizer hint to cover all indexes on the table except the one that is desired like this:SELECT /*+ NO_ORDER_INDEX(t1 i_b,i_c) */ a,c FROM t1 ORDER BY a;尝试将针对整个表的
NO_ORDER_INDEX与USE INDEX FOR ORDER BY结合使用无法实现此目的,因为NO_ORDER_BY会导致USE INDEX被忽略,如下所示:Attempting to combineNO_ORDER_INDEXfor the table as a whole withUSE INDEX FOR ORDER BYdoes not work to do this, becauseNO_ORDER_BYcausesUSE INDEXto be ignored, as shown here:mysql>
EXPLAIN SELECT /*+ NO_ORDER_INDEX(t1) */ a,c FROM t1->USE INDEX FOR ORDER BY (i_a) ORDER BY a\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: t1 partitions: NULL type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 256 filtered: 100.00 Extra: Using filesortUSE INDEX、FORCE INDEX和IGNORE INDEX索引提示的优先级高于INDEX_MERGE和NO_INDEX_MERGE优化器提示。TheUSE INDEX,FORCE INDEX, andIGNORE INDEXindex hints have higher priority than theINDEX_MERGEandNO_INDEX_MERGEoptimizer hints./*+ INDEX_MERGE(t1 i_a, i_b, i_c) */ ... IGNORE INDEX i_a
IGNORE INDEX优先于INDEX_MERGE,因此索引i_a被排除在可能的索引合并范围之外。IGNORE INDEXtakes precedence overINDEX_MERGE, so indexi_ais excluded from the possible ranges for Index Merge./*+ NO_INDEX_MERGE(t1 i_a, i_b) */ ... FORCE INDEX i_a, i_b
由于
FORCE INDEX,i_a, i_b不允许进行索引合并,但优化器被迫在range或ref访问中使用i_a或i_b。没有冲突;两个提示都适用。Index Merge is disallowed fori_a, i_bbecause ofFORCE INDEX, but the optimizer is forced to use eitheri_aori_bforrangeorrefaccess. There are no conflicts; both hints are applicable.如果
IGNORE INDEX提示指定了多个索引,那么这些索引在索引合并中不可用。If anIGNORE INDEXhint names multiple indexes, those indexes are unavailable for Index Merge.FORCE INDEX和USE INDEX提示只使指定的索引可用于索引合并。TheFORCE INDEXandUSE INDEXhints make only the named indexes to be available for Index Merge.SELECT /*+ INDEX_MERGE(t1 i_a, i_b, i_c) */ a FROM t1 FORCE INDEX (i_a, i_b) WHERE c = 'h' AND a = 2 AND b = 'b';
索引合并交叉访问算法用于
(i_a, i_b)。如果将FORCE INDEX改为USE INDEX,情况也是一样的。The Index Merge intersection access algorithm is used for(i_a, i_b). The same is true ifFORCE INDEXis changed toUSE INDEX.
子查询提示会影响是否使用半连接转换以及允许哪些半连接策略;当不使用半连接时,还会影响是否使用子查询物化或 IN-到-EXISTS 转换。有关这些优化的更多信息,请参见 第 10.2.2 节,“优化子查询、派生表、视图引用和公共表表达式”。Subquery hints affect whether to use semijoin transformations
and which semijoin strategies to permit, and, when semijoins
are not used, whether to use subquery materialization or
IN-to-EXISTS
transformations. For more information about these
optimizations, see Section 10.2.2, “Optimizing Subqueries, Derived Tables, View References, and Common Table
Expressions”.
影响半连接策略的提示语法:Syntax of hints that affect semijoin strategies:
hint_name([@query_block_name] [strategy[,strategy] ...])
语法涉及以下术语:The syntax refers to these terms:
hint_name:允许使用的提示名称如下:hint_name: These hint names are permitted:SEMIJOIN,NO_SEMIJOIN:启用或禁用指定的半连接策略。SEMIJOIN,NO_SEMIJOIN: Enable or disable the named semijoin strategies.
strategy:要启用或禁用的半连接策略。允许的策略名称包括:DUPSWEEDOUT,FIRSTMATCH,LOOSESCAN,MATERIALIZATION。strategy: A semijoin strategy to be enabled or disabled. These strategy names are permitted:DUPSWEEDOUT,FIRSTMATCH,LOOSESCAN,MATERIALIZATION.对于
SEMIJOIN提示,如果未指定策略,则在可能的情况下根据optimizer_switch系统变量启用的策略使用半连接。如果指定了策略但不适用于该语句,则使用DUPSWEEDOUT。ForSEMIJOINhints, if no strategies are named, semijoin is used if possible based on the strategies enabled according to theoptimizer_switchsystem variable. If strategies are named but inapplicable for the statement,DUPSWEEDOUTis used.对于
NO_SEMIJOIN提示,如果未指定策略,则不使用半连接。如果指定的策略排除了该语句的所有可用策略,则使用DUPSWEEDOUT。ForNO_SEMIJOINhints, if no strategies are named, semijoin is not used. If strategies are named that rule out all applicable strategies for the statement,DUPSWEEDOUTis used.
如果一个子查询嵌套在另一个子查询中,并且两者都合并到外部查询的半连接中,则对最内层查询的半连接策略的任何指定都会被忽略。SEMIJOIN 和 NO_SEMIJOIN 提示仍然可以用于启用或禁用此类嵌套子查询的半连接转换。If one subquery is nested within another and both are merged
into a semijoin of an outer query, any specification of
semijoin strategies for the innermost query are ignored.
SEMIJOIN and
NO_SEMIJOIN hints can still
be used to enable or disable semijoin transformations for such
nested subqueries.
如果禁用 DUPSWEEDOUT,有时优化器可能生成远非最优的查询计划。这是由于贪婪搜索期间的启发式修剪导致的,可以通过设置 optimizer_prune_level=0 来避免。If DUPSWEEDOUT is disabled, on occasion the
optimizer may generate a query plan that is far from optimal.
This occurs due to heuristic pruning during greedy search,
which can be avoided by setting
optimizer_prune_level=0.
示例:Examples:
SELECT /*+ NO_SEMIJOIN(@subq1 FIRSTMATCH, LOOSESCAN) */ * FROM t2 WHERE t2.a IN (SELECT /*+ QB_NAME(subq1) */ a FROM t3); SELECT /*+ SEMIJOIN(@subq1 MATERIALIZATION, DUPSWEEDOUT) */ * FROM t2 WHERE t2.a IN (SELECT /*+ QB_NAME(subq1) */ a FROM t3);
影响是否使用子查询物化或IN到EXISTS转换的提示语法:Syntax of hints that affect whether to use subquery
materialization or
IN-to-EXISTS
transformations:
SUBQUERY([@query_block_name]strategy)
提示名称始终是SUBQUERY。The hint name is always
SUBQUERY.
对于SUBQUERY提示,允许使用这些strategy值:INTOEXISTS、MATERIALIZATION。For SUBQUERY hints, these
strategy values are permitted:
INTOEXISTS,
MATERIALIZATION.
示例:Examples:
SELECT id, a IN (SELECT /*+ SUBQUERY(MATERIALIZATION) */ a FROM t1) FROM t2; SELECT * FROM t2 WHERE t2.a IN (SELECT /*+ SUBQUERY(INTOEXISTS) */ a FROM t1);
对于半连接和SUBQUERY 提示,前导 @ 指定提示适用的查询块。如果提示不包含前导 query_block_name@,则提示适用于其所在的查询块。要为查询块分配名称,请参见 用于命名查询块的优化提示。For semijoin and query_block_nameSUBQUERY
hints, a leading
@
specifies the query block to which the hint applies. If the
hint includes no leading
query_block_name@,
the hint applies to the query block in which it occurs. To
assign a name to a query block, see
Optimizer Hints for Naming Query Blocks.query_block_name
如果提示注释包含多个子查询提示,则使用第一个。如果之后还有同类型的提示,它们会产生警告。其他类型的后续提示会被静默忽略。If a hint comment contains multiple subquery hints, the first is used. If there are other following hints of that type, they produce a warning. Following hints of other types are silently ignored.
MAX_EXECUTION_TIME 提示仅允许用于 SELECT 语句。它对语句允许执行的最长时间设置限制 N(以毫秒为单位的超时时间),超过该时间服务器将终止该语句:The MAX_EXECUTION_TIME hint
is permitted only for SELECT
statements. It places a limit N (a
timeout value in milliseconds) on how long a statement is
permitted to execute before the server terminates it:
MAX_EXECUTION_TIME(N)
示例,超时时间为 1 秒(1000 毫秒):Example with a timeout of 1 second (1000 milliseconds):
SELECT /*+ MAX_EXECUTION_TIME(1000) */ * FROM t1 INNER JOIN t2 WHERE ...
MAX_EXECUTION_TIME( 提示将语句执行超时设置为 N)N 毫秒。如果该选项不存在或 N 为 0,则适用由 max_execution_time 系统变量设定的语句超时。The
MAX_EXECUTION_TIME(
hint sets a statement execution timeout of
N)N milliseconds. If this option is
absent or N is 0, the statement
timeout established by the
max_execution_time system
variable applies.
MAX_EXECUTION_TIME 提示适用如下:The MAX_EXECUTION_TIME hint
is applicable as follows:
对于包含多个
SELECT关键字的语句,例如联合查询或带有子查询的语句,MAX_EXECUTION_TIME适用于整个语句,并且必须出现在第一个SELECT之后。For statements with multipleSELECTkeywords, such as unions or statements with subqueries,MAX_EXECUTION_TIMEapplies to the entire statement and must appear after the firstSELECT.它适用于只读的
SELECT语句。非只读语句是指那些调用会以副作用修改数据的存储函数的语句。It applies to read-onlySELECTstatements. Statements that are not read only are those that invoke a stored function that modifies data as a side effect.它不适用于存储程序中的
SELECT语句,并将被忽略。It does not apply toSELECTstatements in stored programs and is ignored.
SET_VAR 提示临时设置系统变量的会话值(在单条语句的执行期间)。示例:The SET_VAR hint sets the
session value of a system variable temporarily (for the
duration of a single statement). Examples:
SELECT /*+ SET_VAR(sort_buffer_size = 16M) */ name FROM people ORDER BY name; INSERT /*+ SET_VAR(foreign_key_checks=OFF) */ INTO t2 VALUES(2); SELECT /*+ SET_VAR(optimizer_switch = 'mrr_cost_based=off') */ 1;
SET_VAR 提示的语法:Syntax of the SET_VAR hint:
SET_VAR(var_name=value)
var_name 指定具有会话值的系统变量的名称(尽管并非所有此类变量都可以命名,如后文所述)。value 是要分配给变量的值;该值必须是标量。var_name names a system variable
that has a session value (although not all such variables can
be named, as explained later).
value is the value to assign to the
variable; the value must be a scalar.
SET_VAR 进行临时变量更改,如以下语句所示:SET_VAR makes a temporary
variable change, as demonstrated by these statements:
mysql>SELECT @@unique_checks;+-----------------+ | @@unique_checks | +-----------------+ | 1 | +-----------------+ mysql>SELECT /*+ SET_VAR(unique_checks=OFF) */ @@unique_checks;+-----------------+ | @@unique_checks | +-----------------+ | 0 | +-----------------+ mysql>SELECT @@unique_checks;+-----------------+ | @@unique_checks | +-----------------+ | 1 | +-----------------+
使用 SET_VAR 时,无需保存和恢复变量值。这使您可以用一条语句替换多条语句。请考虑以下语句序列:With SET_VAR, there is no
need to save and restore the variable value. This enables you
to replace multiple statements by a single statement. Consider
this sequence of statements:
SET @saved_val = @@SESSION.var_name; SET @@SESSION.var_name=value; SELECT ... SET @@SESSION.var_name= @saved_val;
这个序列可以被这条语句替代:The sequence can be replaced by this single statement:
SELECT /*+ SET_VAR(var_name=value) ...
独立的 SET 语句允许使用这些语法来命名会话变量:Standalone
SET
statements permit any of these syntaxes for naming session
variables:
SET SESSIONvar_name=value; SET @@SESSION.var_name=value; SET @@.var_name=value;
因为 SET_VAR 提示仅适用于会话变量,会话范围是隐含的,因此 SESSION、@@SESSION. 和 @@ 既不需要也不允许。包括显式的会话指示语法会导致 SET_VAR 提示被忽略并伴随警告。Because the SET_VAR hint
applies only to session variables, session scope is implicit,
and SESSION, @@SESSION.,
and @@ are neither needed nor permitted.
Including explicit session-indicator syntax results in the
SET_VAR hint being ignored
with a warning.
并非所有会话变量都允许与 SET_VAR 一起使用。各个系统变量的描述会指明每个变量是否可作为提示使用;请参阅 第 7.1.8 节,“服务器系统变量”。您也可以在运行时通过尝试将其与 SET_VAR 一起使用来检查系统变量。如果变量不可作为提示使用,将会出现警告:Not all session variables are permitted for use with
SET_VAR. Individual system
variable descriptions indicate whether each variable is
hintable; see Section 7.1.8, “Server System Variables”. You
can also check a system variable at runtime by attempting to
use it with SET_VAR. If the
variable is not hintable, a warning occurs:
mysql>SELECT /*+ SET_VAR(collation_server = 'utf8mb4') */ 1;+---+ | 1 | +---+ | 1 | +---+ 1 row in set, 1 warning (0.00 sec) mysql>SHOW WARNINGS\G*************************** 1. row *************************** Level: Warning Code: 4537 Message: Variable 'collation_server' cannot be set using SET_VAR hint.
SET_VAR 语法只允许设置单个变量,但可以给出多个提示以设置多个变量:SET_VAR syntax permits
setting only a single variable, but multiple hints can be
given to set multiple variables:
SELECT /*+ SET_VAR(optimizer_switch = 'mrr_cost_based=off')
SET_VAR(max_heap_table_size = 1G) */ 1;
如果在同一语句中出现多个具有相同变量名的提示,则应用第一个提示,其他提示将被忽略并发出警告:If several hints with the same variable name appear in the same statement, the first one is applied and the others are ignored with a warning:
SELECT /*+ SET_VAR(max_heap_table_size = 1G)
SET_VAR(max_heap_table_size = 3G) */ 1;
在这种情况下,第二个提示会被忽略,并发出其冲突的警告。In this case, the second hint is ignored with a warning that it is conflicting.
如果没有指定名称的系统变量或变量值不正确,SET_VAR 提示会被忽略并显示警告:A SET_VAR hint is ignored
with a warning if no system variable has the specified name or
the variable value is incorrect:
SELECT /*+ SET_VAR(max_size = 1G) */ 1; SELECT /*+ SET_VAR(optimizer_switch = 'mrr_cost_based=yes') */ 1;
对于第一个语句,没有 max_size 变量。对于第二个语句,mrr_cost_based 的取值为 on 或 off,因此尝试将其设置为 yes 是不正确的。在每种情况下,该提示都会被忽略并显示警告。For the first statement, there is no
max_size variable. For the second
statement, mrr_cost_based
takes values of on or
off, so attempting to set it to
yes is incorrect. In each case, the hint is
ignored with a warning.
SET_VAR 提示仅允许在语句级别使用。如果在子查询中使用该提示,将会被忽略并发出警告。The SET_VAR hint is
permitted only at the statement level. If used in a subquery,
the hint is ignored with a warning.
副本在复制语句中会忽略 SET_VAR 提示,以避免潜在的安全问题。Replicas ignore SET_VAR
hints in replicated statements to avoid the potential for
security issues.
RESOURCE_GROUP 优化器提示用于资源组管理(参见 第 7.1.16 节,“资源组”)。此提示将执行语句的线程临时分配到指定资源组(在语句执行期间)。它需要 RESOURCE_GROUP_ADMIN 或 RESOURCE_GROUP_USER 权限。The RESOURCE_GROUP optimizer
hint is used for resource group management (see
Section 7.1.16, “Resource Groups”). This hint assigns the
thread that executes a statement to the named resource group
temporarily (for the duration of the statement). It requires
the RESOURCE_GROUP_ADMIN or
RESOURCE_GROUP_USER privilege.
示例:Examples:
SELECT /*+ RESOURCE_GROUP(USR_default) */ name FROM people ORDER BY name; INSERT /*+ RESOURCE_GROUP(Batch) */ INTO t2 VALUES(2);
RESOURCE_GROUP 提示的语法:Syntax of the RESOURCE_GROUP
hint:
RESOURCE_GROUP(group_name)
group_name 指示线程在语句执行期间应分配到的资源组。如果该组不存在,将会出现警告并且提示会被忽略。group_name indicates the resource
group to which the thread should be assigned for the duration
of statement execution. If the group is nonexistent, a warning
occurs and the hint is ignored.
RESOURCE_GROUP 提示必须出现在初始语句关键字(SELECT、INSERT、REPLACE、UPDATE 或 DELETE)之后。The RESOURCE_GROUP hint must
appear after the initial statement keyword
(SELECT, INSERT,
REPLACE, UPDATE, or
DELETE).
一个替代 RESOURCE_GROUP 的方法是 SET RESOURCE GROUP 语句,它会将线程非临时地分配到资源组。见 15.7.2.4 节,“SET RESOURCE GROUP 语句”。An alternative to
RESOURCE_GROUP is the
SET RESOURCE GROUP statement,
which nontemporarily assigns threads to a resource group. See
Section 15.7.2.4, “SET RESOURCE GROUP Statement”.
表级、索引级和子查询优化器提示允许将特定查询块命名为其参数语法的一部分。要创建这些名称,请使用 QB_NAME 提示,它会为出现的查询块分配一个名称:Table-level, index-level, and subquery optimizer hints permit
specific query blocks to be named as part of their argument
syntax. To create these names, use the
QB_NAME hint, which assigns
a name to the query block in which it occurs:
QB_NAME(name)
QB_NAME 提示可用于以清晰的方式明确其他提示适用于哪些查询块。它们还允许将所有非查询块名称提示在单个提示注释中指定,以便更容易理解复杂语句。请考虑以下语句:QB_NAME hints can be used to
make explicit in a clear way which query blocks other hints
apply to. They also permit all non-query block name hints to
be specified within a single hint comment for easier
understanding of complex statements. Consider the following
statement:
SELECT ... FROM (SELECT ... FROM (SELECT ... FROM ...)) ...
QB_NAME 提示用于在语句中为查询块分配名称:QB_NAME hints assign names
to query blocks in the statement:
SELECT /*+ QB_NAME(qb1) */ ... FROM (SELECT /*+ QB_NAME(qb2) */ ... FROM (SELECT /*+ QB_NAME(qb3) */ ... FROM ...)) ...
然后其他提示可以使用这些名称来引用相应的查询块:Then other hints can use those names to refer to the appropriate query blocks:
SELECT /*+ QB_NAME(qb1) MRR(@qb1 t1) BKA(@qb2) NO_MRR(@qb3t1 idx1, id2) */ ... FROM (SELECT /*+ QB_NAME(qb2) */ ... FROM (SELECT /*+ QB_NAME(qb3) */ ... FROM ...)) ...
其产生的效果如下:The resulting effect is as follows:
MRR(@qb1 t1)适用于查询块qb1中的表t1。MRR(@qb1 t1)applies to tablet1in query blockqb1.NO_MRR(@qb3 t1 idx1, id2)适用于查询块qb3中表t1的索引idx1和idx2。NO_MRR(@qb3 t1 idx1, id2)applies to indexesidx1andidx2in tablet1in query blockqb3.
查询块名称是标识符,并遵循关于有效名称以及如何引用名称的通常规则(参见 第 11.2 节,“模式对象名称”)。例如,包含空格的查询块名称必须加引号,可以使用反引号进行引用:Query block names are identifiers and follow the usual rules about what names are valid and how to quote them (see Section 11.2, “Schema Object Names”). For example, a query block name that contains spaces must be quoted, which can be done using backticks:
SELECT /*+ BKA(@`my hint name`) */ ... FROM (SELECT /*+ QB_NAME(`my hint name`) */ ...) ...
如果启用了 ANSI_QUOTES SQL 模式,也可以使用双引号引用查询块名称:If the ANSI_QUOTES SQL mode
is enabled, it is also possible to quote query block names
within double quotation marks:
SELECT /*+ BKA(@"my hint name") */ ...
FROM (SELECT /*+ QB_NAME("my hint name") */ ...) ...