注册
达梦数据库hint 优化器提示
专栏/技术分享/ 文章详情 /

达梦数据库hint 优化器提示

祢真伟大 2025/12/05 13 0 0
摘要

达梦数据库hint 优化器提示

1 环境说明

  • dm8-03134284368-20250423-270902-20149

2 达梦数据库HINT说明

  • DBA 对于数据分布很清楚的话,就会知道 SQL 语句按照哪种方法执行会最快。在这种情况下,DBA 可以主动进行人工干预,指示优化器按照指定的方法去选择 SQL 的执行计划。
  • DM 把这种人工干预优化器的方法称为 HINT,它使优化器根据 DBA 的 HINT 提示来生成指定的执行计划。如果优化器无法生成相应的执行计划,该 HINT 将会被忽略。

2.1 HINT 的常见格式如下所示

  • 需要注意的是:如果 HINT 的语法没有写对或指定的值不正确,DM 并不会报错,而是直接忽略 HINT 继续执行。
SELECT /*+ HINT1 [HINT2]*/ 列名 FROM 表名 WHERE_CLAUSE ; UPDATE 表名 /*+ HINT1 [HINT2]*/ SET 列名 =变量 WHERE_CLAUSE ; DELETE FROM 表名 /*+ HINT1 [HINT2]*/ WHERE_CLAUSE ;
  • 支持使用 HINT 的 INI 参数可通过 V$HINT_INI_INFO 动态视图查询。
SELECT * FROM V$HINT_INI_INFO;
  • 支持 HINT 的 INI 参数分为两类:一是HINT_TYPE为“OPT”,表示分析阶段使用的参数;二是HINT_TYPE为“EXEC”,表示运行阶段使用的参数,运行阶段使用的参数对于视图无效。
  • 下面的语句中使用了 HINT,指明在执行此 SQL 时,参数 ENABLE_HASH_JOIN 被置为 1。
SELECT /*+ENABLE_HASH_JOIN(1)*/ * FROM T1,T2 WHERE C1=D1;

2.1 HINT使用索引

  • 可以指定多个索引,一个语句中最多指定 8 个索引。
/*+ INDEX (表名[,] 索引名) {INDEX (表名[,] 索引名)} */ SELECT /*+INDEX(T1, IDX_T1_ID) */ * FROM T1 WHERE ID > 2011 AND NAME < 'XXX'; SELECT * FROM T1 INDEX IDX_T1_ID WHERE ID > 2011 AND NAME < 'XXX'; 不使用索引 /*+ NO_INDEX (表名[,] 索引名) { NO_INDEX (表名[,] 索引名)} */

2.2 连接方法提示

  • DBA 可以通过指定两个表间的连接方法来检测不同连接方式的查询效率,指定的连接可能由于无法实现或代价过高而被忽略。如果连接方法提示中的表名(别名)或索引名无效也会被自动忽略。

2.2.1 USE_HASH 强制两个表间使用指定顺序的哈希连接

EXPLAIN SELECT /*+ USE_HASH(T1, T2) */ * FROM T1, T2 WHERE T1.ID = T2.ID;

2.2.2 NO_USE_HASH 强制两个表间不能使用指定顺序的哈希连接

  • NO_USE_HASH(T1, T2)表示不允许 T1 作为左表,T2 作为右表的哈希连接,但 T1 作为右表的哈希连接还是允许的。
EXPLAIN SELECT /*+ NO_USE_HASH(T1, T2) */ * FROM T1, T2 WHERE T1.ID = T2.ID;

2.2.3 USE_NL 强制两个表间使用嵌套循环连接

EXPLAIN SELECT /*+ USE_NL(A, B) */ * FROM T1 A, T2 B WHERE A.ID = B.ID; #NEST LOOP INNER JOIN2

2.2.4 NO_USE_NL 强制两个表间不能使用嵌套循环连接

EXPLAIN SELECT /*+ NO_USE_NL(A, B) */ * FROM T1 A, T2 B WHERE A.ID = B.ID;

2.2.5 USE_NL_WITH_INDEX 当连接情况为左表+右表索引时,强制两个表间使用索引连接

EXPLAIN SELECT /*+ USE_NL_WITH_INDEX(T1, IDX_T2_ID) */ * FROM T1, T2 WHERE T1.ID = T2.ID; #NEST LOOP IN DEX JOIN2:

2.2.6 NO_USE_NL_WITH_INDEX 当连接情况为左表+右表索引时,强制两个表间不能使用索引连接

EXPLAIN SELECT /*+ NO_USE_NL_WITH_INDEX(T1, IDX_T2_ID) */ * FROM T1, T2 WHERE T1.ID = T2.ID;

2.2.7 USE_MERGE 强制两个表间使用归并连接。归并连接所用的两个列都必须是索引列

/*+ USE_MERGE(T1,T2) */ #MERGE INNER JOIN3

2.2.8 NO_USE_MERGE 强制两个表间不能使用归并连接

/*+ NO_USE_MERGE(T1,T2) */

2.2.9 SEMI_GEN_CROSS 优先采用半连接转换为等价的内连接,仅 OPTIMIZER_MODE=1 有效

/*+ SEMI_GEN_CROSS OPTIMIZER_MODE(1) */

2.2.10 NO_SEMI_GEN_CROSS 不采用半连接转换为等价的内连接,仅 OPTIMIZER_MODE=1 有效

/*+ NO_SEMI_GEN_CROSS OPTIMIZER_MODE(1) */

2.2.11 USE_CVT_VAR 优先采用变量改写方式实现连接,仅 OPTIMIZER_MODE=1 有效

  • 适合驱动表数据量少而另一侧计划较复杂的场景,目前支持变量改写的连接方式有
  • NEST LOOP INNER JOIN2、
  • NEST LOOP LEFT JOIN2、
  • NEST LOOP SEMI JOIN2,
/*+ USE_CVT_VAR OPTIMIZER_MODE(1) */

2.2.12 NO_USE_CVT_VAR 不考虑变量改写方式实现连接,仅 OPTIMIZER_MODE=1 有效

/*+ NO_USE_CVT_VAR OPTIMIZER_MODE(1) */
  • ENHANCED_MERGE_JOIN 一般情况下,归并连接需要左右孩子的数据按照连接列有序,使用此优化器提示时,优化器将考虑通过插入排序操作符的方式实现归并连接,仅 OPTIMIZER_MODE=1 有效
/*+ stat(T1 1M) stat(T2 1M) */
  • HASH2 INNER JOIN
/*+ENHANCED_MERGE_JOIN OPTIMIZER_MODE(1) stat(T1 1M) stat(T2 1M)*/
  • MERGE INNER JOIN3

2.3 连接顺序提示

  • 多表连接时优化器会考虑各种可能的排列组合顺序。使用 ORDER HINT 指定连接顺序提示可以缩小优化器试探的排列空间,进而得到接近 DBA 所期望的查询计划。如果连接顺序和连接方法提示同时指定且二者间存在自相矛盾,优化器会以连接顺序提示为准。
/*+ ORDER (T1, T2 , T3, … tn ) */

举例

SELECT /*+ ORDER(T1, T2, T3 )*/* FROM T1, T2 , T3, T4 WHERE
  • 在指定上述连接顺序后,T4,T1,T2,T3 或 T1,T2,T4,T3 会被考虑;T3,T1,T2 或 T1,T3,T2 不被考虑。

  • 连接顺序也可以和连接方法同时指定用于得到更特定的执行计划

/*+ OPTIMIZER_MODE(1), ORDER(T1,T2,T3,T4) ,USE_HASH(T1,T2), USE_HASH(T2,T3),USE_HASH(T3,T4)*/

2.4 统计信息提示

  • 优化器在计划优化阶段会自动获取基表的行数。但是一些特殊类型的表行数估算并不准确,或者 DBA 希望了解表大小对计划影响的时候,需要手动设置表的行数。
/*+ STAT (表名, 行数) */
  • 统计信息提示只能针对基表设置,视图和派生表等对象设置无效。如果表对象存在别名则必须使用别名。行数只能使用整数,或者整数+K(千),整数+M(百万),整数+G(十亿)。行数提示设置后,统计信息的其它内容也会做相应的调整。

2.5 MPP 本地对象提示

  • MPP 环境下,提供一种将用户表或动态视图作为本地对象处理的方法,通过指示符LOCAL_OBJECT(对象名/别名) 进行处理
/*+LOCAL_OBJECT(对象名/别名)*/ /*+local_object(t1)*/

2.6 忽略重复键值提示

  • 当执行 INSERT 操作时,如果存在 UNIQUE 索引,那么发生了重复键值冲突。使用 HINTIGNORE_ROW_ON_DUPKEY_INDEX 则可以忽略该冲突,冲突数据既不进行插入也不会报错,其他非冲突插入正常进行。

  • 每一个该 HINT 仅对应一个索引,如需忽略多个索引上的重复键值冲突,请指定多个HINT。

/*+IGNORE_ROW_ON_DUPKEY_INDEX(<表名>[(<列名>{,<列名>})])*/
  • 若 INSERT 的目标表具有别名,则只有<表名>与别名一致时 HINT 才生效。

  • 支持使用该 HINT 时不指定<列名>,此时忽略表上除函数索引外的所有 UNIQUE 索引的报错。当指定<列名>时,该 HINT 指定的<列名>必须是某个 UNIQUE 索引的前导列或者全部列,否则报错;当作为前导列时,不能出现其它也将这些列作为前导列的 UNIQUE 索引,否则报错。指定该 HINT 时,不支持 insert 操作的批量优化处理。

/*+IGNORE_ROW_ON_DUPKEY_INDEX(t1(c1,c2,c3))*/ /*+IGNORE_ROW_ON_DUPKEY_INDEX(t1)*/

2.7 禁用计划缓存提示

使用 HINT PLAN_NO_CACHE 禁用计划缓存,当前语句的执行计划将不会被缓存

/*+PLAN_NO_CACHE*/

2.8 并行

  • 不支持 HINT 方式指定该参数 PARALLEL_POLICY 动态,会话级 默认 0 不开启并行
    HINT 语法格式如下:
/*+ PARALLEL([<表名>] <并行任务个数>) */

例 下面的例子中,即使已经设置了 MAX_PARALLEL_DEGREE 默认值 3,但实际使用为 PARALLEL 指定的任务个数 4

SELECT /*+ PARALLEL(4) */ * FROM SYSOBJECTS; SELECT /*+ PARALLEL(SYSOBJECTS 4) */ * FROM SYSOBJECTS;
  • 另外,每个语句中仅能设置一次并行任务个数,如果设置了多次,则以第一次设置为准,而且任务个数在全语句中生效。
    例 下面的例子中,使用的并行任务个数为 1
SELECT /*+ PARALLEL(1) *//*+ PARALLEL(2) */ * FROM SYSOBJECTS;
  • 这种方式能够为单条查询语句设置额外的并行任务个数,以此来提高某些特殊查询任务的性能

  • 大型表的连接查询、大量数据的聚合和大型结果集的排序等都很适合采用并行查询

2.9 缓存

  • DBA 可以通过在 SQL 语句中设置 “RESULT_CACHE”或“NO_RESULT_CACHE” HINT 手动指示查询的结果集是否缓存。如:
select /*+ RESULT_CACHE */ id, name from sysobjects; select /*+ NO_RESULT_CACHE */ id, name from sysobjects;

3 更多达梦数据库全方位指南:安装 优化 与实战教程

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服