ITPub博客

首页 > 数据库 > 国内数据库 > tidb hints

tidb hints

原创 国内数据库 作者:水逸冰 时间:2021-04-11 16:32:13 0 删除 编辑

    tidb支持Optimizer Hints 语法,用法与oracle的Hints语法类似,/*+ HINT_NAME(t1, t2) */,在SELECT、UPDATE 或 DELETE 的后面。INSERT 关键字后不支持 Optimizer Hints。

    如果 Optimizer Hints 包含语法错误或不完整,查询语句不会报错,而是按照没有 Optimizer Hints 的情况执行。如果 Hint 不适用于当前语句,TiDB 会返回 Warning,可以在查询结束后通过 Show Warnings命令查看具体信息。如果注释不是跟在指定的关键字后,会被当作是普通的 MySQL comment,注释不会生效,且不会上报 warning。

    下面这类 Hint 可以跟在查询语句中任意 SELECT、UPDATE 或 DELETE 关键字的后面。

1、merge_join

    MERGE_JOIN(t1_name [, tl_name ...]) 提示优化器对指定表使用 Sort Merge Join 算法。该算法优点是会占用更少的内存,但是执行时间会比较久。

SELECT /*+ MERGE_JOIN(t1, t2) */ * FROM t1,t2 WHERE t1.id = t2.id;

2、inl_join

    INL_JOIN(t1_name [, tl_name ...]) 提示优化器对指定表使用 Index Nested Loop Join 算法。

SELECT /*+ INL_JOIN(t1, t2) */ * FROM t1,t2 WHERE t1.id = t2.id;

    INL_JOIN() 中的参数是建立查询计划时内表的候选表,比如 INL_JOIN(t1) 只会考虑使用 t1 作为内表构建查询计划。表如果指定了别名,就只能使用表的别名作为 INL_JOIN() 的参数;如果没有指定别名,则用表的本名作为其参数。比如在 SELECT /*+ INL_JOIN(t1) */ * FROM t t1, t t2 WHERE t1.a = t2.b; 中,INL_JOIN() 的参数只能使用 t 的别名 t1 或 t2,不能用 t。

3、inl_hash_join

    INL_HASH_JOIN(t1_name [, tl_name]) 提示优化器使用 Index Nested Loop Hash Join 算法。该算法与 Index Nested Loop Join 使用条件完全一样,两者的区别是 INL_JOIN 会在连接的内表上建哈希表,而 INL_HASH_JOIN 会在连接的外表上建哈希表,后者对于内存的使用是有固定上限的,而前者使用的内存使用取决于内表匹配到的行数。

4、hash_join

    HASH_JOIN(t1_name [, tl_name ...]) 提示优化器对指定表使用 Hash Join 算法。这个算法多线程并发执行,执行速度较快,但会消耗较多内存

SELECT /*+ HASH_JOIN(t1, t2) */ * FROM t1,t2 WHERE t1.id = t2.id;

5、hash_agg()

    HASH_AGG() 提示优化器对指定查询块中所有聚合函数使用 Hash Aggregation 算法。这个算法多线程并发执行,执行速度较快,但会消耗较多内存。

SELECT /*+ HASH_AGG() / count() FROM t1,t2 WHERE t1.a > 10 GROUP BY t1.id;

6、stream_agg()

    STREAM_AGG() 提示优化器对指定查询块中所有聚合函数使用 Stream Aggregation 算法。这个算法通常会占用更少的内存,但执行时间会更久。数据量太大,或系统内存不足时,建议尝试使用。

SELECT /*+ STREAM_AGG() / count() FROM t1,t2 WHERE t1.a > 10 GROUP BY t1.id;

7、use_index()/ignore_index()

    USE_INDEX(t1_name, idx1_name [, idx2_name ...]) 提示优化器对指定表仅使用给出的索引。

    IGNORE_INDEX(t1_name, idx1_name [, idx2_name ...]) 提示优化器对指定表忽略给出的索引。

第一个参数注意添加表名。

8、agg_to_cop()

    AGG_TO_COP() 提示优化器将指定查询块中的聚合函数下推到 coprocessor。如果优化器没有下推某些适合下推的聚合函数,建议尝试使用。

SELECT /*+ AGG_TO_COP() */ sum(t1.a) FROM t t1;

9、read_from_storage()

    READ_FROM_STORAGE(TIFLASH[t1_name [, tl_name ...]], TIKV[t2_name [, tl_name ...]]) 提示优化器从指定的存储引擎来读取指定的表,目前支持的存储引擎参数有 TIKV 和 TIFLASH。

SELECT /*+ READ_FROM_STORAGE(TIFLASH[t1], TIKV[t2]) */ t1.a FROM t t1, t t2 WHERE t1.a = t2.a;

    如果需要提示优化器使用的表不在同一个数据库内,需要显式指定数据库名。例如 SELECT /*+ READ_FROM_STORAGE(TIFLASH[test1.t1,test2.t2]) */ t1.a FROM test1.t t1, test2.t t2 WHERE t1.a = t2.a;。

10、use_index_merge()

    USE_INDEX_MERGE(t1_name, idx1_name [, idx2_name ...]) 提示优化器通过 index merge 的方式来访问指定的表,其中索引列表为可选参数。若显式地指出索引列表,会尝试在索引列表中选取索引来构建 index merge。若不给出索引列表,会尝试在所有可用的索引中选取索引来构建 index merge。

    当对同一张表有多个 USE_INDEX_MERGE Hint 时,优化器会从这些 Hint 指定的索引列表的并集中尝试选取索引。

SELECT /*+ USE_INDEX_MERGE(t1, idx_a, idx_b, idx_c) */ * FROM t1 WHERE t1.a > 10 OR t1.b > 10;

    对于主键索引,索引名为 primary。

目前该 Hint 生效的条件较为苛刻,包括:

  • 如果查询有除了全表扫以外的单索引扫描方式可以选择,优化器不会选择 index merge;

  • 如果查询在显式事务里,且该条查询之前的语句已经涉及写入,优化器不会选择 index merge;

    下面这类 Hint 只能跟在语句中第一个 SELECT、UPDATE 或 DELETE 关键字的后面,等同于在当前这条查询运行时对指定的系统变量进行修改,其优先级高于现有系统变量的值。

1、NO_INDEX_MERGE() 会关闭优化器的 index merge 功能。

SELECT /*+ NO_INDEX_MERGE() */ * FROM t WHERE t.a > 0 or t.b > 0;

    除了 Hint 外,系统变量 tidb_enable_index_merge 也能决定是否开启该功能。

    NO_INDEX_MERGE 优先级高于 USE_INDEX_MERGE,当这两类 Hint 同时存在时,USE_INDEX_MERGE 不会生效。

2、use_toja(bool)

    参数 boolean_value 可以是 TRUE 或者 FALSE。USE_TOJA(TRUE) 会开启优化器尝试将 in (subquery) 条件转换为 join 和 aggregation 的功能。相对地,USE_TOJA(FALSE) 会关闭该功能。

    下面的例子会将 in (SELECT t2.a FROM t2) subq 转换为等价的 join 和 aggregation:

SELECT /*+ USE_TOJA(TRUE) */ t1.a, t1.b FROM t1 WHERE t1.a in (SELECT t2.a FROM t2) subq;

    除了 Hint 外,系统变量 tidb_opt_insubq_to_join_and_agg 也能决定是否开启该功能。

3、max_execution_time(N)

    MAX_EXECUTION_TIME(N) 把语句的执行时间限制在 N 毫秒以内,超时后服务器会终止这条语句的执行。

    下面的 Hint 设置了 1000 毫秒(即 1 秒)超时:

SELECT /*+ MAX_EXECUTION_TIME(1000) */ * FROM t1 inner join t2 WHERE t1.id = t2.id;

    除了 Hint 之外,系统变量 global.max_execution_time 也能对语句执行时间进行限制。

4、memory_quota(N)

    MEMORY_QUOTA(N) 用于限制语句执行时的内存使用。该 Hint 支持 MB 和 GB 两种单位。内存使用超过该限制时会根据当前设置的内存超限行为来打出一条 log 或者终止语句的执行。

    下面的 Hint 设置了 1024 MB 的内存限制:

SELECT /*+ MEMORY_QUOTA(1024 MB) */ * FROM t;

    除了 Hint 外,系统变量 tidb_mem_quota_query 也能限制语句执行的内存使用。

5、read_consistent_replica()

    READ_CONSISTENT_REPLICA() 会开启从数据一致的 TiKV follower 节点读取数据的特性。

    下面的例子会从 follower 节点读取数据:

SELECT /*+ READ_CONSISTENT_REPLICA() */ * FROM t;

    除了 Hint 外,环境变量 tidb_replica_read 设为 'follower' 或者 'leader' 也能决定是否开启该特性。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31480688/viewspace-2767460/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
精通oracle,mysql和linux,热衷于研究数据库,擅长shell和Python自动化运维。VX:18302174682

注册时间:2017-08-05

  • 博文量
    117
  • 访问量
    188638