Hint能够影响优化器对于执行计划的选择,但这种影响不是强制性的,优化器在某些状况下可能会忽略目标SQL中的Hint。因为各类缘由致使Hint被Oracle忽略后,Oracle并不会给出任何提示或者警告,更不会报错,目标SQL依然能够正常运行,这也符合Hint其实是一种特殊注释的身份。注释原本就是无关紧要的东西,不该该由于它的存在而而致使原先在没有Hint时能够正常执行的SQL由于加了Hint后而变得不能正常执行。sql
下面来看几种Hint被Oracle忽略的常见情形。ide
1 使用的Hint有语法或者拼写错误测试
一旦使用的Hint中有语法或者拼写错误,Oracle就会忽略该Hint,看几个示例SQL:优化
select /*+ ind(emp pk_emp) */* from emp;this
select /*+ index(emp pk_emp */* from emp;索引
select /* + index(emp pk_emp) */* from emp;ci
select */*+ index(emp pk_emp) */ from emp;hash
select /*+ index(scott.emp pk_emp) */* from emp;it
select /*+ index(emp pk_emp) */* from emp e;io
select /*+ index(emp emp_pk) */* from emp;
select /*+ full(t2) */ t1.ename,t1.deptno from emp t1 where t1.deptno in (select t2.deptno from detp t where t2.loc='CHICAGO');
实际上,上述8条SQL中的Hint都是无效的,它们都会被Oracle忽略。
1是由于关键字应该是"index"而不是"ind"
2是由于漏掉了一个右括号
3是由于Hint中第一个*和+之间出现了空格
4是由于Hint出现的位置不对,它应该出如今*前面
5是由于emp表前面带上了SCHEME名称
6是由于没有emp表的别名
7是由于索引名称写错了
8是由于Hint跨了Query Block。Hint生效的范围公限于它自己所在的Query Block,若是将某个Hint生将范围扩展到它所在的Query Block以外而又没在该Hint中指定其生效的Query Block名称的话,Oracle就会忽略该Hint。
2 使用的Hint无效
即便语法是正确的,但若是因为某种缘由致使Oracle认为这个Hint无效,则Oracle仍是会忽略该Hint。
看几个实例
scott@TEST>set autotrace traceonly scott@TEST>select /*+ index(dept idx_dept_loc) */ deptno,dname from dept where loc='CHICAGO'; Execution Plan ---------------------------------------------------------- Plan hash value: 492093765 -------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 10 | 300 | 2 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| DEPT | 10 | 300 | 2 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | IDX_DEPT_LOC | 4 | | 1 (0)| 00:00:01 | -------------------------------------------------------------------------------------------- ......
从上面的输出能够看出,上面的SQL的执行计划走的是对索引IDX_DEPT_LOC的索引范围扫描,说明Hint生效了,可是若是把where条件替换为与索引IDX_DEPT_LOC绝不相关的deptno=30,再来看执行状况
scott@TEST>select /*+ index(dept idx_dept_loc) */ deptno,dname from dept where deptno=30; Execution Plan ---------------------------------------------------------- Plan hash value: 2852011669 --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 22 | 2 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 22 | 2 (0)| 00:00:01 | |* 2 | INDEX UNIQUE SCAN | PK_DEPT | 1 | | 1 (0)| 00:00:01 | --------------------------------------------------------------------------------------- ......
从上面的输出能够看出,执行计划走的是对主键PK_DEPT的INDEX UNIQUE SCAN,面不是Hint里的IDX_DEPT_LOC。这就说明Hint在这个SQL失效了。
即便不改where条件,若是把索引IDX_DEPT_LOC删除,这个Hint也会失效:
scott@TEST>drop index idx_dept_loc; Index dropped. scott@TEST>select /*+ index(dept idx_dept_loc) */ deptno,dname from dept where loc='CHICAGO'; Execution Plan ---------------------------------------------------------- Plan hash value: 3383998547 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 10 | 300 | 29 (0)| 00:00:01 | |* 1 | TABLE ACCESS FULL| DEPT | 10 | 300 | 29 (0)| 00:00:01 | --------------------------------------------------------------------------
从上面的执行计划能够看出走的是对表DEPT的TABLE ACCESS FULL,Hint也是失效的。
再来看一个使用组合Hint的例子,先看以下SQL的执行计划
scott@TEST>select /*+ full(dept) parallel(dept 2) */ deptno from dept; Execution Plan ---------------------------------------------------------- Plan hash value: 587379989 -------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib | -------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1000 | 13000 | 16 (0)| 00:00:01 | | | | | 1 | PX COORDINATOR | | | | | | | | | | 2 | PX SEND QC (RANDOM)| :TQ10000 | 1000 | 13000 | 16 (0)| 00:00:01 | Q1,00 | P->S | QC (RAND) | | 3 | PX BLOCK ITERATOR | | 1000 | 13000 | 16 (0)| 00:00:01 | Q1,00 | PCWC | | | 4 | TABLE ACCESS FULL| DEPT | 1000 | 13000 | 16 (0)| 00:00:01 | Q1,00 | PCWP | | -------------------------------------------------------------------------------------------------------------- ......
从上面输出内容能够看出,如今是对表DEPT作的并行全表扫描,说明组合Hint中的两个都生效了,这个Hint的含义是既要全表扫描又要并行访问表DEPT,二者不矛盾,由于全表扫描能够并行执行。再看以下的SQL:
scott@TEST>select /*+ index(dept pk_dept) parallel(dept 2) */ deptno from dept; 4 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 2913917002 ---------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1000 | 13000 | 26 (0)| 00:00:01 | | 1 | INDEX FULL SCAN | PK_DEPT | 1000 | 13000 | 26 (0)| 00:00:01 | ---------------------------------------------------------------------------- ......
如今SQL走的是对索引PK_DEPT的索引全扫描,可是串行的,说明Hint中的parallel(dept 2)失效了,由于表DEPT上的主键索引PK_DEPT不是分区索引,而对于非分区索引而言,索引范围扫描或索引全扫描并不能并行执行,因此上述组合Hint中忽略了parallel(dept 2)。
再看一个HASH JOIN的例子:
下面的SQL中use_hash的Hint是生效的:
scott@TEST>select /*+ use_hash(t1) */ t1.empno,t1.empno,t2.loc from emp t1,dept t2 where t1.deptno=t2.deptno and t2.loc='CHICAGO'; 6 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 615168685 --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 5 | 185 | 7 (15)| 00:00:01 | |* 1 | HASH JOIN | | 5 | 185 | 7 (15)| 00:00:01 | |* 2 | TABLE ACCESS FULL| DEPT | 1 | 11 | 3 (0)| 00:00:01 | | 3 | TABLE ACCESS FULL| EMP | 14 | 364 | 3 (0)| 00:00:01 | -------------------------------------------------------------------------- -
可是若是把SQL修改成以下则use_hash的Hint就会被忽略
scott@TEST>select /*+ use_hash(t1) */ t1.empno,t1.empno,t2.loc from emp t1,dept t2 where t1.deptno>t2.deptno and t2.loc='CHICAGO'; no rows selected Execution Plan ---------------------------------------------------------- Plan hash value: 4192419542 --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 37 | 6 (0)| 00:00:01 | | 1 | NESTED LOOPS | | 1 | 37 | 6 (0)| 00:00:01 | |* 2 | TABLE ACCESS FULL| DEPT | 1 | 11 | 3 (0)| 00:00:01 | |* 3 | TABLE ACCESS FULL| EMP | 1 | 26 | 3 (0)| 00:00:01 | ---------------------------------------------------------------------------
从上面的执行计划中看出use_hash确实是被Oracle忽略了,这是由于哈希链接只适用于等值链接条件,不等值的链接条件对哈希链接而言是没有意义的,因此上述Hint就被Oracle忽略了。
3 使用的Hint自相矛盾
若是使用的组合Hint是自相矛盾的,则这些自相矛盾的Hint都会被Oracle忽略。但Oracle只会将自相矛盾的Hint所有忽略掉,但若是使用的组合Hint中还有其余有效的Hint,则这些有效Hint不受影响。
看一个使用自相矛盾Hint的实例,先执行单个Hint的SQL
scott@TEST>select /*+ index_ffs(dept pk_dept)*/ deptno from dept; 4 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 2578398298 -------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 4 | 12 | 2 (0)| 00:00:01 | | 1 | INDEX FAST FULL SCAN| PK_DEPT | 4 | 12 | 2 (0)| 00:00:01 | -------------------------------------------------------------------------------- ...... scott@TEST>select /*+ full(dept)*/ deptno from dept; 4 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 3383998547 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 4 | 12 | 3 (0)| 00:00:01 | | 1 | TABLE ACCESS FULL| DEPT | 4 | 12 | 3 (0)| 00:00:01 | --------------------------------------------------------------------------
从上面的输出能够看出单独使用上面的两个Hint都能被Oracle生效,但若是这两个Hint合并到一块儿使用就不是那么回事了:
scott@TEST>select /*+ index_ffs(dept pk_dept) full(dept)*/ deptno from dept; 4 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 2913917002 ---------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 4 | 12 | 1 (0)| 00:00:01 | | 1 | INDEX FULL SCAN | PK_DEPT | 4 | 12 | 1 (0)| 00:00:01 | ----------------------------------------------------------------------------
从上面的输出能够看出执行计划没有走Hint中指定的执行计划,而是对主键索引PK_DEPT作的是INDEX FULL SCAN这说明Hint中的两个都失效了。
再来看下面的例子:
scott@TEST>select /*+ index_ffs(dept pk_dept) full(dept) cardinality(dept 1000) */ deptno from dept; 4 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 2913917002 ---------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1000 | 3000 | 1 (0)| 00:00:01 | | 1 | INDEX FULL SCAN | PK_DEPT | 1000 | 3000 | 1 (0)| 00:00:01 | ----------------------------------------------------------------------------
从上面的输出能够看出执行计划走的仍然是对主键索引PK_DEPT作的是INDEX FULL SCAN,可是作INDEX FULL SCAN反回结果集的cardinality从原来的4变为了1000,说明cardinality(dept 1000)生效了,也验证了若是使用的组合Hint中还有其余有效的Hint,则这些有效Hint不受影响。
4 使用的Hint受到了查询转换的干扰
有时候,查询转换也会致使相关的Hint失效,即Hint被Oracle忽略还多是由于受到了查询转换的干扰。
下面来看一个由于使用了查询转换而致使相关Hint被Oracle忽略掉的实例。
建立一个测试表jobs
scott@TEST>create table jobs as select empno,job from emp; Table created.
构造一个SQL
select /*+ ordered cardinality(e 100) */ e.ename, j.job, e.sal, v.avg_sal from emp e, jobs j, (select /*+ merge */ e.deptno, avg(e.sal) avg_sal from emp e, dept d where d.loc = 'chicago' and d.deptno = e.deptno group by e.deptno) v where e.empno = j.empno and e.deptno = v.deptno and e.sal > v.avg_sal order by e.ename;
上面的SQL是两个表(EMP和JOBS)和内嵌视图V关联的SQL,其中内嵌视图V又是由表EMP和DEPT关联后获得的。在此SQL中使用了三个Hint,其中merge用于让内嵌视图V作视图合并,ordered表示上述SQL在执行时表EMP、JOBS和内嵌视图V的链接顺序应该和它们在该SQL的SQL文本中出现的顺序一致,即它们应该是按照从左至右的顺序依次作表链接。
若是上述三个Hint都生效的话,那目标SQL的执行计划中应该不会出现关键字“VIEW”(表示作了视图合并,体现了Merge Hint的做用),表EMP、JOBS和内嵌视图V的链接应该会变成表EMP、JOBS和内嵌视图V所对应的基表EMP和DEPT的链接,且链接的前后顺序应该是EMP->JOBS->内嵌视图V所对应的基表EMP和DEPT(体现了Ordered Hint的做用),外围查询中表EMP的扫描结果所对应的Cardinality的值应该是100(体现了Cardinality Hint的做用)。
如今看一下实际状况,执行上面的SQL:
scott@TEST>select /*+ ordered cardinality(e 100) */ 2 e.ename, j.job, e.sal, v.avg_sal 3 from emp e, 4 jobs j, 5 (select /*+ merge */ 6 e.deptno, avg(e.sal) avg_sal 7 from emp e, dept d 8 where d.loc = 'chicago' 9 and d.deptno = e.deptno 10 group by e.deptno) v 11 where e.empno = j.empno 12 and e.deptno = v.deptno 13 and e.sal > v.avg_sal 14 order by e.ename; no rows selected Execution Plan ---------------------------------------------------------- Plan hash value: 930847561 ------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 156 | 19656 | 15 (20)| 00:00:01 | |* 1 | FILTER | | | | | | | 2 | SORT GROUP BY | | 156 | 19656 | 15 (20)| 00:00:01 | |* 3 | HASH JOIN | | 156 | 19656 | 14 (15)| 00:00:01 | |* 4 | TABLE ACCESS FULL | DEPT | 1 | 11 | 3 (0)| 00:00:01 | |* 5 | HASH JOIN | | 467 | 53705 | 10 (10)| 00:00:01 | | 6 | TABLE ACCESS FULL | EMP | 14 | 364 | 3 (0)| 00:00:01 | |* 7 | HASH JOIN | | 100 | 8900 | 7 (15)| 00:00:01 | | 8 | TABLE ACCESS FULL| EMP | 100 | 5800 | 3 (0)| 00:00:01 | | 9 | TABLE ACCESS FULL| JOBS | 14 | 434 | 3 (0)| 00:00:01 | -------------------------------------------------------------------------------
从上面的执行计划能够看出,确实没有出现关键字“VIEW”,表EMP的扫描结果所对应的Cardinality的值确实是100,但链接顺序不是上面提到的顺序,而是先选择的表DEPT。这说明上述三个Hint中的Merge Hint和Cardinality Hint生效了,但Ordered Hint被Oracle忽略了。这是由于受到了查询转换的干扰(对内嵌视图V作视图合并是一种查询转换)。
为了证实上述SQL的Ordered Hint被Oracle忽略是由于受到了查询转换的干扰,如今将内嵌视图V中的merge替换为no_merge(不让内嵌视图作视图合并),再次执行该SQL:
scott@TEST>select /*+ ordered cardinality(e 100) */ 2 e.ename, j.job, e.sal, v.avg_sal 3 from emp e, 4 jobs j, 5 (select /*+ no_merge */ 6 e.deptno, avg(e.sal) avg_sal 7 from emp e, dept d 8 where d.loc = 'chicago' 9 and d.deptno = e.deptno 10 group by e.deptno) v 11 where e.empno = j.empno 12 and e.deptno = v.deptno 13 and e.sal > v.avg_sal 14 order by e.ename; no rows selected Execution Plan ---------------------------------------------------------- Plan hash value: 2898000699 -------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 8 | 728 | 14 (22)| 00:00:01 | | 1 | SORT ORDER BY | | 8 | 728 | 14 (22)| 00:00:01 | |* 2 | HASH JOIN | | 8 | 728 | 13 (16)| 00:00:01 | |* 3 | HASH JOIN | | 100 | 6500 | 7 (15)| 00:00:01 | | 4 | TABLE ACCESS FULL | EMP | 100 | 4600 | 3 (0)| 00:00:01 | | 5 | TABLE ACCESS FULL | JOBS | 14 | 266 | 3 (0)| 00:00:01 | | 6 | VIEW | | 5 | 130 | 6 (17)| 00:00:01 | | 7 | HASH GROUP BY | | 5 | 185 | 6 (17)| 00:00:01 | | 8 | MERGE JOIN | | 5 | 185 | 6 (17)| 00:00:01 | |* 9 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 11 | 2 (0)| 00:00:01 | | 10 | INDEX FULL SCAN | PK_DEPT | 4 | | 1 (0)| 00:00:01 | |* 11 | SORT JOIN | | 14 | 364 | 4 (25)| 00:00:01 | | 12 | TABLE ACCESS FULL | EMP | 14 | 364 | 3 (0)| 00:00:01 | --------------------------------------------------------------------------------------------
从上面的执行计划中能够看出,出现了“VIEW”关键字,说明没有作视图合并,表EMP对就的Cardinality为100,链接顺序与前面预想的一致,这说明在禁掉了查询转换后以前被忽略的Ordered Hint又生效了。
5 使用的Hint受到了保留关键字的干扰
Oracle在解析Hint时,是按照从左到右的顺序进行的,若是遇到的词是Oracle的保留关键字,则Oracle将忽略这个词以及以后的全部词;若是遇到词既不是关键字也不是Hint,就忽略该词;若是遇到的词是有效的Hint,那么Oracle就会保留该Hing。
正是因为上述Oracle解析Hint的原则,保留关键字也可能致使相关的Hint失效。
Oracle的保留关键字能够从视图V$RESERVED_WORDS中查到,从下面的查询结果能够看到','、'COMMENT'、'IS'都是保留关键字,但“THIS”不是
scott@TEST>select keyword,length from v$reserved_words where keyword in (',','THIS','IS','COMMENT'); KEYWORD LENGTH ---------- ---------- , 1 COMMENT 7 IS 2
下面来看一个保留关键字致使Hint失效的实例,执行下面的SQL
scott@TEST>select t1.empno,t1.empno,t2.loc from emp t1,dept t2 where t1.deptno=t2.deptno; 14 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 844388907 ---------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 14 | 518 | 6 (17)| 00:00:01 | | 1 | MERGE JOIN | | 14 | 518 | 6 (17)| 00:00:01 | | 2 | TABLE ACCESS BY INDEX ROWID| DEPT | 4 | 44 | 2 (0)| 00:00:01 | | 3 | INDEX FULL SCAN | PK_DEPT | 4 | | 1 (0)| 00:00:01 | |* 4 | SORT JOIN | | 14 | 364 | 4 (25)| 00:00:01 | | 5 | TABLE ACCESS FULL | EMP | 14 | 364 | 3 (0)| 00:00:01 | ----------------------------------------------------------------------------------------
从执行计划上看走的是MERGE SORT JOIN,对SQL加入以下Hint并执行:
scott@TEST>select /*+ use_hash(t1) index(t2 pk_dept) */ t1.empno,t1.empno,t2.loc from emp t1,dept t2 where t1.deptno=t2.deptno; 14 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 2622742753 ---------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 14 | 518 | 6 (17)| 00:00:01 | |* 1 | HASH JOIN | | 14 | 518 | 6 (17)| 00:00:01 | | 2 | TABLE ACCESS BY INDEX ROWID| DEPT | 4 | 44 | 2 (0)| 00:00:01 | | 3 | INDEX FULL SCAN | PK_DEPT | 4 | | 1 (0)| 00:00:01 | | 4 | TABLE ACCESS FULL | EMP | 14 | 364 | 3 (0)| 00:00:01 | ----------------------------------------------------------------------------------------
从上面的执行计划中能够看出Hint中的两个都生效了,emp作HASH JOIN的被驱动表,对DEPT表作使用索引PK_DEPT。如今对Hint加入',',查看执行状况:
scott@TEST>select /*+ use_hash(t1) , index(t2 pk_dept) */ t1.empno,t1.empno,t2.loc from emp t1,dept t2 where t1.deptno=t2.deptno; 14 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 615168685 --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 14 | 518 | 7 (15)| 00:00:01 | |* 1 | HASH JOIN | | 14 | 518 | 7 (15)| 00:00:01 | | 2 | TABLE ACCESS FULL| DEPT | 4 | 44 | 3 (0)| 00:00:01 | | 3 | TABLE ACCESS FULL| EMP | 14 | 364 | 3 (0)| 00:00:01 | ---------------------------------------------------------------------------
从执行计划中能够看出,仍然走的是HASH JOIN可是index(t2 pk_dept)失效了。由于','是Oracle的保留关键字,因此','后面的index(t2 pk_dept)失效了,再修改Hint以下并执行SQL:
scott@TEST>select /*+ comment use_hash(t1) index(t2 pk_dept) */ t1.empno,t1.empno,t2.loc from emp t1,dept t2 where t1.deptno=t2.deptno; 14 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 844388907 ---------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 14 | 518 | 6 (17)| 00:00:01 | | 1 | MERGE JOIN | | 14 | 518 | 6 (17)| 00:00:01 | | 2 | TABLE ACCESS BY INDEX ROWID| DEPT | 4 | 44 | 2 (0)| 00:00:01 | | 3 | INDEX FULL SCAN | PK_DEPT | 4 | | 1 (0)| 00:00:01 | |* 4 | SORT JOIN | | 14 | 364 | 4 (25)| 00:00:01 | | 5 | TABLE ACCESS FULL | EMP | 14 | 364 | 3 (0)| 00:00:01 | ----------------------------------------------------------------------------------------
从执行计划中看出,如今走的是跟一开始的执行计划同样,说明Hint中的两个都失效了,由于这两个都在Oracle保留关键字comment后面。再修改Hint以下再次执行SQL:
scott@TEST>select /*+ this use_hash(t1) index(t2 pk_dept) */ t1.empno,t1.empno,t2.loc from emp t1,dept t2 where t1.deptno=t2.deptno; 14 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 2622742753 ---------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 14 | 518 | 6 (17)| 00:00:01 | |* 1 | HASH JOIN | | 14 | 518 | 6 (17)| 00:00:01 | | 2 | TABLE ACCESS BY INDEX ROWID| DEPT | 4 | 44 | 2 (0)| 00:00:01 | | 3 | INDEX FULL SCAN | PK_DEPT | 4 | | 1 (0)| 00:00:01 | | 4 | TABLE ACCESS FULL | EMP | 14 | 364 | 3 (0)| 00:00:01 | ----------------------------------------------------------------------------------------
如今执行计划又走出了Hint指定的样子,说明两个都生效了,这是由于this不是Oracle保留关键字。
以上介绍了5种Hint被Oracle忽略的状况,在实例使用过程当中必定要注意使用方法,使用正确有效的Hint来提高SQL执行效率,避免Hint被Oracle忽略。
参考《基于Oracle的SQL优化》