Bootstrap

达梦数据库系列—43.HINT

目录

使用HINT

INDEX

USE_HASH

USE_NL

USE_NL_WITH_INDEX

USE_MERGE

SEMI_GEN_CROSS

USE_CVT_VAR

连接顺序

忽略重复键值

禁用计划缓存


使用HINT

数据准备

    //数据准备

    DROP TABLE T1 CASCADE;

    CREATE TABLE T1 (ID INTEGER,NAME VARCHAR(128));

    CREATE INDEX IDX_T1_ID ON T1(ID);

    CREATE INDEX IDX_T1_NAME ON T1(NAME);

INDEX

/*+ INDEX (表名[,] 索引名) {INDEX (表名[,] 索引名)} */

注:如果查询中给出了表的别名那么必须使用别名/*+不能有空格,否则hint无效

explain select /*+ INDEX(T1,IDX_T1_ID) */ * from t1 where id > 2011 AND name < 'xxx';

explain select /*+ INDEX(a,IDX_T1_ID) */ * from t1 a where id > 2011 AND name < 'xxx';

数据准备

    //数据准备

    DROP TABLE T1 CASCADE;

    DROP TABLE T2 CASCADE;

    CREATE TABLE T1 (ID INTEGER,NAME VARCHAR(128));

    CREATE TABLE T2 (ID INTEGER,NAME VARCHAR(128));

    begin

    for i in 1..1000 loop

    insert into T1 values(i,'dameng'||i);

    insert into T2 values(i+500,'damengsh'||i);

    end loop;

    end;

USE_HASH

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

EXPLAIN SELECT /*+ USE_HASH(T1, T2) */ * FROM T1, T2 WHERE T1.id > T2.id;

USE_NL

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

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

explain select /*+ use_nl(t2,t1) */ * from T1, T2 WHERE T1.id = T2.id;

USE_NL_WITH_INDEX

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

CREATE INDEX IDX_T2_ID ON T2(ID);

//执行EXPLAIN

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

USE_MERGE

CREATE INDEX IDX_T1_ID ON T1(ID);

//执行EXPLAIN

explain select /*+ use_merge(t1,t2)*/ * from t1,t2 where t1.id=t2.id and t1.id <1;

SEMI_GEN_CROSS

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

EXPLAIN

SELECT

       /*+ SEMI_GEN_CROSS  OPTIMIZER_MODE(1) */

       COUNT(*)

  FROM T1 A

 WHERE A.ID IN (SELECT B.ID FROM T1 B);

USE_CVT_VAR

优先采用变量改写方式实现连接,适合驱动表数据量少而另一侧计划较复杂的场景,仅 OPTIMIZER_MODE=1 有效。

EXPLAIN

SELECT

       /*+ USE_CVT_VAR OPTIMIZER_MODE(1) */

       COUNT(*)

  FROM T1 A

 WHERE A.id = 1001

   AND EXISTS (SELECT 1 FROM T1 B, T1 C WHERE B.id = C.id AND A.name= B.name);

连接顺序

/*+ 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 不被考虑。

统计信息

优化器在计划优化阶段会自动获取基表的行数。但是一些特殊类型的表行数估算并不准确,或者 DBA 希望了解表大小对计划影响的时候,需要手动设置表的行数。

/*+ STAT (表名, 行数) */

统计信息提示只能针对基表设置,视图和派生表等对象设置无效。如果表对象存在别名则必须使用别名。行数只能使用整数,或者整数 +K(千),整数 +M(百万),整数 +G(十亿)。行数提示设置后,统计信息的其它内容也会做相应的调整。

例:

CREATE TABLE T_S(C1 INT);

INSERT INTO T_S SELECT LEVEL FROM DUAL CONNECT BY LEVEL<= 100;

COMMIT;

STAT 100 ON T_S(C1);

EXPLAIN SELECT /*+ STAT(T_S,1M) */ * FROM T_S WHERE C1 <= 10;

不适用HINT的计划:

explain select * from t_s where c1<=10;

忽略重复键值

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

/*+IGNORE_ROW_ON_DUPKEY_INDEX(<表名> [(<列名>{,<列名>})])*/

insert  /*+IGNORE_ROW_ON_DUPKEY_INDEX(t1(c1,c2,c3))*/ into t1 values (1,2,1,1); //不报错

insert  /*+IGNORE_ROW_ON_DUPKEY_INDEX(t1)*/ into t1 values (1,2,1,1);  //不报错

禁用计划缓存

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

/*+PLAN_NO_CACHE*/

达梦技术社区:达梦数据库 - 新一代大型通用关系型数据库 | 达梦在线服务平台

;