目录
使用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*/