TiDB 支持 Optimizer Hints 语法,它基于 MySQL 5.7 中介绍的类似 comment 的语法,例如 /*+ HINT_NAME(t1, t2) */。当 TiDB 优化器选择的不是最优查询计划时,建议使用 Optimizer Hints。
语法
Optimizer Hints 不区分大小写,通过 /*+ ... */ 注释的形式跟在 SELECT、UPDATE 或 DELETE 关键字的后面。INSERT 关键字后不支持 Optimizer Hints。
多个不同的 Hint 之间需用逗号隔开,例如:
SELECT /*+ USE_INDEX(t1, idx1), HASH_AGG(), HASH_JOIN(t1) */ count(*) FROM t t1, t t2 WHERE t1.a = t2.b;
MERGE_JOIN(t1_name [, tl_name ...]) 提示优化器对指定表使用 Sort Merge Join 算法。这个算法通常会占用更少的内存,但执行时间会更久。当数据量太大,或系统内存不足时,建议尝试使用。
INL_JOIN(t1_name [, tl_name ...]) 提示优化器对指定表使用 Index Nested Loop Join 算法。这个算法可能会在某些场景更快,消耗更少系统资源,有的场景会更慢,消耗更多系统资源。对于外表经过 WHERE 条件过滤后结果集较小(小于 1 万行)的场景,可以尝试使用。
INL_HASH_JOIN(t1_name [, tl_name]) 提示优化器使用 Index Nested Loop Hash Join 算法。该算法与 Index Nested Loop Join 使用条件完全一样,两者的区别是 INL_JOIN 会在连接的内表上建哈希表,而 INL_HASH_JOIN 会在连接的外表上建哈希表,后者对于内存的使用是有固定上限的,而前者使用的内存使用取决于内表匹配到的行数。
HASH_JOIN(t1_name [, tl_name ...]) 提示优化器对指定表使用 Hash Join 算法。这个算法多线程并发执行,执行速度较快,但会消耗较多内存。
HASH_JOIN_BUILD(t1_name [, tl_name ...]) 提示优化器对指定表使用 Hash Join 算法,同时将指定表作为 Hash Join 算法的 Build 端,即用指定表来构建哈希表。
HASH_JOIN_PROBE(t1_name [, tl_name ...]) 提示优化器对指定表使用 Hash Join 算法,同时将指定表作为 Hash Join 算法的探测(Probe)端,即用指定表作为探测端来执行 Hash Join 算法。
SEMI_JOIN_REWRITE() 提示优化器将查询语句中的半连接 (Semi Join) 改写为普通的内连接。目前该 Hint 只作用于 EXISTS 子查询。如果不使用该 Hint 进行改写,Semi Join 在选择 Hash Join 的执行方式时,只能够使用子查询构建哈希表,因此在子查询比外查询结果集大时,执行速度可能会不及预期。Semi Join 在选择 Index Join 的执行方式时,只能够使用外查询作为驱动表,因此在子查询比外查询结果集小时,执行速度可能会不及预期。
在使用了 SEMI_JOIN_REWRITE() 进行改写后,优化器便可以扩大选择范围,选择更好的执行方式。
SHUFFLE_JOIN(t1_name [, tl_name ...]) 提示优化器对指定表使用 Shuffle Join 算法,该 Hint 只在 MPP 模式下生效。
BROADCAST_JOIN(t1_name [, tl_name ...]) 提示优化器对指定表使用 Broadcast Join 算法,该 Hint 只在 MPP 模式下生效。
NO_DECORRELATE() 提示优化器不要尝试解除指定查询块中对应子查询的关联。该 Hint 适用于包含关联列的 EXISTS、IN、ANY、ALL、SOME 和标量子查询,即关联子查询。将该 Hint 写在一个查询块中后,对于该子查询和其外部查询块之间的关联列,优化器将不再尝试解除关联,而是始终使用 Apply 算子来执行查询。默认情况下,TiDB 会尝试对关联子查询解除关联,以达到更高的执行效率。但是在一部分场景下,解除关联反而会降低执行效率。这种情况下,可以使用该 Hint 来人工提示优化器不要进行解除关联操作。
HASH_AGG() 提示优化器对指定查询块中所有聚合函数使用 Hash Aggregation 算法。这个算法多线程并发执行,执行速度较快,但会消耗较多内存。
STREAM_AGG() 提示优化器对指定查询块中所有聚合函数使用 Stream Aggregation 算法。这个算法通常会占用更少的内存,但执行时间会更久。数据量太大,或系统内存不足时,建议尝试使用。
MPP_1PHASE_AGG() 提示优化器对指定查询块中所有聚合函数使用一阶段聚合算法,该 Hint 只在 MPP 模式下生效。
MPP_2PHASE_AGG() 提示优化器对指定查询块中所有聚合函数使用二阶段聚合算法,该 Hint 只在 MPP 模式下生效。
USE_INDEX(t1_name, idx1_name [, idx2_name ...]) 提示优化器对指定表仅使用给出的索引。
FORCE_INDEX(t1_name, idx1_name [, idx2_name ...]) 提示优化器对指定表仅使用给出的索引。
FORCE_INDEX(t1_name, idx1_name [, idx2_name ...]) 的使用方法、作用和 USE_INDEX(t1_name, idx1_name [, idx2_name ...]) 相同。
IGNORE_INDEX(t1_name, idx1_name [, idx2_name ...]) 提示优化器对指定表忽略给出的索引。
ORDER_INDEX(t1_name, idx1_name [, idx2_name ...]) 提示优化器对指定表仅使用给出的索引,并且按顺序读取指定的索引。
NO_ORDER_INDEX(t1_name, idx1_name [, idx2_name ...]) 提示优化器对指定表仅使用给出的索引,并且不按顺序读取指定的索引。
AGG_TO_COP() 提示优化器将指定查询块中的聚合函数下推到 coprocessor。如果优化器没有下推某些适合下推的聚合函数,建议尝试使用。
LIMIT_TO_COP() 提示优化器将指定查询块中的 Limit 和 TopN 算子下推到 coprocessor。优化器没有下推 Limit 或者 TopN 算子时建议尝试使用该提示。
READ_FROM_STORAGE(TIFLASH[t1_name [, tl_name ...]], TIKV[t2_name [, tl_name ...]]) 提示优化器从指定的存储引擎来读取指定的表,目前支持的存储引擎参数有 TIKV 和 TIFLASH。如果为表指定了别名,就只能使用表的别名作为 READ_FROM_STORAGE() 的参数;如果没有指定别名,则用表的本名作为其参数。
USE_INDEX_MERGE(t1_name, idx1_name [, idx2_name ...]) 提示优化器通过索引合并的方式来访问指定的表。索引合并分为并集型和交集型两种类型,详情参见《用 EXPLAIN 查看索引合并的 SQL 执行计划》。若显式地指定索引列表,优化器会尝试在索引列表中选取索引来构建索引合并。若不指定索引列表,优化器会尝试在所有可用的索引中选取索引来构建索引合并。对于交集型索引合并,索引列表是必选参数。对于并集型索引合并,Hint 中的索引列表为可选参数。
LEADING(t1_name [, tl_name ...]) 提示优化器在生成多表连接的执行计划时,按照 hint 中表名出现的顺序来确定多表连接的顺序。
在含有公共表表达式的查询中使用 MERGE() hint,可关闭对当前子查询的物化过程,并将内部查询的内联展开到外部查询。该 hint 适用于非递归的公共表表达式查询,在某些场景下,使用该 hint 会比默认分配一块临时空间的语句执行效率更高。




