Oracle中常见的Hint(一)

2019年12月07日 阅读数:76
这篇文章主要向大家介绍Oracle中常见的Hint(一),主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

Oracle中的Hint能够用来调整SQL的执行计划,提升SQL执行效率。下面分类介绍Oracle数据库中常见的Hint。这里描述的是Oracle11gR2中的常见Hint,Oracle数据库中各个版本中的Hint都不尽相同,因此这里讲述的的Hint可能并不适用于Oracle早期的版本。sql

1、与优化器模式相关的Hint数据库

一、ALL_ROWS缓存

ALL_ROWS是针对整个目标SQL的Hint,它的含义是让优化器启用CBO,并且在获得目标SQL的执行计划时会选择那些吞吐量最佳的执行路径。这里的“吞吐量最佳”是指资源消耗量(即对I/O、CPU等硬件资源的消耗量)最小,也就是说在ALL_ROWS Hint生效的状况下,优化器会启用CBO并且会依据各个执行路径的资源消耗量来计算它们各自的成本。session

ALL_ROWS Hint的格式以下:app

/*+ ALL_ROWS */函数

使用范例:优化

1
2
3
select  /*+ all_rows */ empno,ename,sal,job
   from  emp
  where  empno=7396;

从Oracle10g开始,ALL_ROWS就是默认的优化器模式,启用的就是CBO。spa

1
2
3
4
5
scott@TEST>show parameter optimizer_mode
 
NAME                      TYPE                 VALUE
------------------------------------ --------------------------------- ------------------------------
optimizer_mode               string                   ALL_ROWS

若是目标SQL中除了ALL_ROWS以外还使用了其余与执行路径、表链接相关的Hint,优化器会优先考虑ALL_ROWS。code

二、FIRST_ROWS(n)orm

FIRST_ROWS(n)是针对整个目标SQL的Hint,它的含义是让优化器启用CBO模式,并且在获得目标SQL的执行计划时会选择那些能以最快的响应时间返回头n条记录的执行路径,也就是说在FIRST_ROWS(n) Hint生效的状况下,优化器会启用CBO,并且会依据返回头n条记录的响应时间来决定目标SQL的执行计划。

FIRST_ROWS(n)格式以下:

/*+ FIRST_ROWS(n) */

使用范例

1
2
3
select  /*+ first_rows(10) */ empno,ename,sal,job
   from  emp
  where  deptno=30;

上述SQL中使用了/*+ first_rows(10) */,其含义是告诉优化器咱们想以最短的响应时间返回知足条件"deptno=30"的前10条记录。

注意,FIRST_ROWS(n) Hint和优化器模式FIRST_ROWS_n不是一一对应的。优化器模式FIRST_ROWS_n中的n只能是一、十、100、1000。但FIRST_ROWS(n) Hint中的n还能够是其余值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
scott@TEST> alter  session  set  optimizer_mode=first_rows_9;
ERROR:
ORA-00096: invalid value FIRST_ROWS_9  for  parameter optimizer_mode, must be  from  among first_rows_1000, first_rows_100, first_rows_10, first_rows_1, first_rows, all_rows, choose, rule
 
scott@TEST> set  autotrace traceonly
scott@TEST> select  /*+ first_rows(9) */ empno  from  emp;
 
14  rows  selected.
 
 
Execution Plan
----------------------------------------------------------
Plan hash value: 179099197
 
---------------------------------------------------------------------------
| Id  | Operation    |  Name    Rows   | Bytes | Cost (%CPU)|  Time     |
---------------------------------------------------------------------------
|   0 |  SELECT  STATEMENT |     |   9 |    36 |   1   (0)| 00:00:01 |
|   1 |   INDEX  FULL  SCAN | PK_EMP |  9 |    36 |   1   (0)| 00:00:01 |
---------------------------------------------------------------------------

若是在UPDATE、DELETE或者含以下内容的查询语句中使用了FIRST_ROWS(n) Hint,则该Hint会被忽略:

  • 集合运算(如UNION,INTERSACT,MINUS,UNION ALL等)

  • GROUP BY 

  • FOR UPDATE

  • 聚合函数(好比SUM等)

  • DISTINCT

  • ORDER BY(对应的排序列上没有索引)

这里优化器会忽略FIRST_ROWS(n) Hint是由于对于上述类型的SQL而言,Oracle必须访问全部的行记录后才能返回知足条件的头n行记录,即在上述状况下,使用该Hint是没有意义的。

三、RULE

RULE是针对整个目标SQL的Hint,它表示对目标SQL启用RBO。

格式以下:

/*+ RULE */

使用范例:

1
2
3
select  /*+  rule  */ empno,ename,sal,job
   from  emp
  where  deptno=30;

RULE不能与除DRIVING_SITE之外的Hint联用,当RULE与除DRIVING_SITE之外的Hint联用时,其余Hint可能会失效;当RULE与DRIVING_SITE联用时,它自身可能会失效,因此RULE Hint最好是单独使用。

通常状况下,并不推荐使用RULE Hint。一来是由于Oracle早就不支持RBO了,二来启用RBO后优化器在执行目标SQL时可选择的执行路径将大大减小,不少执行路径RBO根本就不支持(好比哈希链接),就也就意味着启用RBO后目标SQL跑出正确执行计划的几率将大大下降。

由于不少执行路径RBO根本就不支持,因此即便在目标SQL中使用了RULE Hint,若是出现了以下这些状况(包括但不限于),RULE Hint依然会被Oracle忽略。

  • 目标SQL除RULE以外还联合使用了其余Hint(如DRIVING_SITE)。

  • 目标SQL使用了并行执行

  • 目标SQL所涉及的对象有IOT

  • 目标SQL所涉及的对象有分区表

......

2、与表访问相关的Hint

一、FULL 

FULL是针对单个目标表的Hint,它的含义是让优化器对目标表执行全表扫描。

格式以下:

/*+ FULL(目标表) */

使用范例:

1
2
3
select  /*+  full (emp) */ empno,ename,sal,job
   from  emp
  where  deptno=30;

上述SQL中Hint的含义是让优化器对目标表EMP执行全表扫描操做,而不考虑走表EMP上的任何索引(即便列EMPNO上有主键索引)。

二、ROIWD

ROIWD是针对单个目标表的Hint,它的含义是让优化器对目标表执行RWOID扫描。只有目标SQL中使用了含ROWID的where条件时ROWID Hint才有意义。

格式以下:

/*+ ROWID(目标表) */

使用范例:

1
2
3
select  /*+ rowid(emp) */ empno,ename,sal,job
   from  emp
  where  rowid= 'AAAR3xAAEAAAACXAAA' ;

Oracle 11gR2中即便使用了ROWID Hint,Oracle仍是会将读到的块缓存在Buffer Cache中。

3、与索引访问相关的Hint

一、INDEX

INDEX是针对单个目标表的Hint,它的含义是让优化器对目标表的的目标索引执行索引扫描操做。

INDEX Hint中的目标索引几乎能够是Oracle数据库中全部类型的索引(包括B树索引、位图索引、函数索引等)。

INDEX Hint的模式有四种:

格式1 /*+ INDEX(目标表 目标索引) */

格式2 /*+ INDEX(目标表 目标索引1 目标索引2 …… 目标索引n) */

格式3 /*+ INDEX(目标表 (目标索引1的索引列名) (目标索引2的索引列名) …… (目标索引n的索引列名)) */

格式4 /*+ INDEX(目标表) */

格式1表示仅指定了目标表上的一个目标索引,此时优化器只会考虑对这个目标索引执行索引扫描操做,而不会去考虑全表扫描或者对该目标表上的其余索引执行索引扫描操做。

格式2表示指定了目标表上的n个目标索引,此时优化器只会考虑对这n个目标索引执行索引扫描操做,而不会去考虑全表扫描或者对该目标表上的其余索引执行索引扫描操做。注意,优化器在考虑这n个目标索引时,多是分别计算出单独扫描各个目标索引的成本后,再选择其中成本值最低的索引;也多是先分别扫描目标索引中的两个或多个索引,而后再对扫描结果执行合并操做。固然,后面这种可能性的前提条件是优化器计算出来这样作的成本值是最低的。

格式三也是表是指定了目标表上的n个目标索引,只不过此时是用指定目标索引的索引列名来代替对应的目标索引名。若是目标索引是复合索引,则在用于指定该索引列名的括号内也能够指定该目标索引的多个索引列,各个索引列之间用空格分隔就能够了。

格式的表示指定了目标表上全部已存在的索引,此时优化器只会考虑对该目标表上全部已存在的索引执行索引扫描操做,而不会去考虑全表扫描操做。注意,这里优化器在考虑该目标表上全部已存在的索引时,多是分别计算出单独扫描这些索引的成本后再选择其中成本值最低的索引;也多是先分别扫描这些索引中的两个或多个索引,而后再对扫描结果执行合并操做。固然,后面这种可能性的前提条件是优化器计算出来这样作的成本值是最低的。

使用范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
select  /*+  index (emp pk_emp) */ empno,ename,sal,job
   from  emp
  where  empno=7369  and  mgr=7902  and  deptno=20;
  
select  /*+  index (emp pk_emp idx_emp_mgr idx_emp_dept) */ empno,ename,sal,job
   from  emp
  where  empno=7369  and  mgr=7902  and  deptno=20;
  
select  /*+  index (emp (empno) (mgr) (deptno)) */ empno,ename,sal,job
   from  emp
  where  empno=7369  and  mgr=7902  and  deptno=20;
  
select  /*+  index  */ empno,ename,sal,job
   from  emp
  where  empno=7369  and  mgr=7902  and  deptno=20;

二、NO_INDEX

NO_INDEX是针对单个目标表的Hint,它是INDEX的反义Hint,其含义是让优化器不对目标表上的目标索引执行扫描操做。

INDEX Hint中的目标索引也几乎能够是Oracle数据库中全部类型的索引(包括B树索引、位图索引、函数索引等)。

格式有以下三种:

格式1 /*+ NO_INDEX(目标表 目标索引) */

格式2 /*+ NO_INDEX(目标表 目标索引1 目标索引2 …… 目标索引n) */

格式3 /*+ NO_INDEX(目标表) */

格式1表示仅指定了目标表上的一个目标索引,此时优化器只是不会考虑对这个目标索引执行索引扫描操做,但仍是会考虑全表扫描或者对该目标表上的其余索引执行索引扫描操做。

格式2表示指定了目标表上的n个目标索引,此时优化器只是不会考虑对这n个目标索引执行索引扫描操做,但仍是会考虑全表扫描或者对该目标表上的其余索引执行索引扫描操做。

格式3表示指定了目标表上的全部已存在的索引,即此时优化器不会考虑对该目标表上全部已存在的索引执行索引扫描操做,这至关于对目标表指定了全表扫描。

使用范例:

1
2
3
4
5
6
7
8
9
10
11
select  /*+ no_index(emp pk_emp) */ empno,ename,sal,job
   from  emp
where  empno=7369  and  mgr=7902  and  deptno=20;
  
select  /*+ no_index(emp pk_emp idx_emp_mgr idx_emp_dept) */ empno,ename,sal,job
   from  emp
  where  empno=7369  and  mgr=7902  and  deptno=20;
  
select  /*+ no_index */ empno,ename,sal,job
   from  emp
  where  empno=7369  and  mgr=7902  and  deptno=20;

三、INDEX_DESC

INDEX_DESC是针对单个目标表的Hint,它的含义是让优化器对目标表上的目标索引执行索引降序扫描操做。若是目标索引是升序的,则INDEX_DESC Hint会使Oracle以降序的方式扫描该索引;若是目标索引是降序的,则INDEX_DESC Hint会使Oracle以升序的方式扫描该索引。

格式有三种:

格式1 /*+ INDEX_DESC(目标表 目标索引) */

格式2 /*+ INDEX_DESC(目标表 目标索引1 目标索引2 …… 目标索引n) */

格式3 /*+ INDEX_DESC(目标表) */

上述3种格式的含义和INDEX中对应格式的含义相同。

使用范例:

1
2
3
4
5
6
7
8
9
10
11
select  /*+ index_desc(emp pk_emp) */ empno,ename,sal,job
   from  emp
  where  empno=7369  and  mgr=7902  and  deptno=20;
  
select  /*+ index_desc(emp pk_emp idx_emp_mgr idx_emp_dept) */ empno,ename,sal,job
   from  emp
  where  empno=7369  and  mgr=7902  and  deptno=20;
  
select  /*+ index_desc */ empno,ename,sal,job
   from  emp
  where  empno=7369  and  mgr=7902  and  deptno=20;

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
scott@TEST> select  /*+ index_desc(emp,pk_emp) */ empno  from  emp;
 
      EMPNO
----------
       7934
       7902
       7900
       7876
       7844
       7839
       7788
       7782
       7698
       7654
       7566
       7521
       7499
       7369
 
14  rows  selected.
 
 
Execution Plan
----------------------------------------------------------
Plan hash value: 1838043032
 
-------------------------------------------------------------------------------------
| Id  | Operation          |  Name    Rows   | Bytes | Cost (%CPU)|  Time      |
-------------------------------------------------------------------------------------
|   0 |  SELECT  STATEMENT     |     |    10 |  40 |   1   (0)| 00:00:01 |
|   1 |   INDEX  FULL  SCAN DESCENDING| PK_EMP |     10 |  40 |   1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------
......

四、INDEX_COMBINE

INDEX_COMBINE是针对单个目标表的Hint,它的含义是让优化器对目标表上的多个目标索引执行位图布尔运算。Oracle数据库里有一个映射函数(Mapping Function),它能够实例B*Tree索引中的ROWID和对应位图索引中的位图之间的互相转换,因此INDEX_COMBINE Hint并不局限于位图索引,它的做用对象也能够是B*Tree索引。

格式有以下两种

格式1 /*+ INDEX_COMBINE(目标表 目标索引1 目标索引2 …… 目标索引n) */

格式2 /*+ INDEX_COMBINE(目标表) */

格式1表示指定了目标表上的n个目标索引,此时优化器会考虑对这n个目标索引中的两个或多个执行位图布尔运算。

格式2表示指定了目标表上全部已存在的索引,此时优化器会考虑对该表上已存在的全部索引中的两个或多个执行位图布尔运算。

使用范例:

1
2
3
4
5
6
7
8
9
10
11
select  /*+ index_combine(emp pk_emp idx_emp_mgr) */ empno,ename,sal,job
   from  emp
  where  empno=7369  and  mgr=7902 ;
  
select  /*+ index_combine(emp pk_emp idx_emp_mgr idx_emp_deptno) */ empno,ename,sal,job
   from  emp
  where  empno=7369  and  mgr=7902  and  deptno=20;
  
select  /*+ index_combine(emp) */ empno,ename,sal,job
   from  emp
  where  empno=7369  and  mgr=7902  and  deptno=20;

下面看一个实例,在表EMP上建立两个索引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
scott@TEST> create  index  idx_emp_mgr  on  emp(mgr);
 
Index  created.
 
scott@TEST> create  index  idx_emp_dept  on  emp(deptno);
 
Index  created.
 
scott@TEST> select  /*+ index_combine(emp pk_emp idx_emp_mgr idx_emp_deptno) */ empno,ename,sal,job
   2    from  emp
   3    where  empno=7369  and  mgr=7902  and  deptno=20;
 
      EMPNO ENAME               SAL JOB
---------- ------------------------------ ---------- ---------------------------
       7369 SMITH              800 CLERK
 
 
Execution Plan
----------------------------------------------------------
Plan hash value: 1816402415
 
-------------------------------------------------------------------------------------------------
| Id  | Operation            |  Name   Rows  | Bytes | Cost (%CPU)|  Time     |
-------------------------------------------------------------------------------------------------
|   0 |  SELECT  STATEMENT       |     |     1 |    29 |     2   (0)| 00:00:01 |
|   1 |   TABLE  ACCESS  BY  INDEX  ROWID   | EMP        |     1 |    29 |     2   (0)| 00:00:01 |
|   2 |   BITMAP CONVERSION  TO  ROWIDS  |     |   |   |        |     |
|   3 |    BITMAP  AND            |     |   |   |        |     |
|   4 |     BITMAP CONVERSION  FROM  ROWIDS|      |   |   |        |     |
|*  5 |       INDEX  RANGE SCAN         | PK_EMP |   |   |     0   (0)| 00:00:01 |
|   6 |     BITMAP CONVERSION  FROM  ROWIDS|      |   |   |        |     |
|*  7 |       INDEX  RANGE SCAN         | IDX_EMP_MGR    |   |   |     1   (0)| 00:00:01 |
|   8 |     BITMAP CONVERSION  FROM  ROWIDS|      |   |   |        |     |
|*  9 |       INDEX  RANGE SCAN         | IDX_EMP_DEPT |    |   |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------
......

从上面的执行计划中能够看到关键字“BITMAP CONVERSION FROM ROWIDS”、“BITMAP AND”和“BITMAP CONVERSION TO ROWIDS”,这说明Oracle先分别对上述三个单键值的B*Tree索引IDX_EMP_MGR、IDX_EMP_DEPT和PK_EMP用映射函数将其中的ROWID转换成了位图,而后对转换后的位图执行了BITMAP AND(位图按位与)布尔运算,最后将布尔运算的结果再次用映射函数转换成了ROWID并回表获得最终的执行结果。能走出这样的执行计划显然是由于INDEX_COMBINE Hint生效了。

用映射函数将ROWID转换成了位图,而后再执行布尔运算,最后将布尔运算的结果再次用映射函数转换成了ROWID并回表获得最终的执行结果,这个过程在实际生产环境中的执行效率多是有问题的,可使用隐含参数_B_TREE_BITMAP_PLANS禁掉该过程当中的ROWID到位图的转换:

alter session set "_b_tree_bitmap_plans"=false;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
scott@TEST> alter  session  set  "_b_tree_bitmap_plans" = false ;
 
Session altered.
 
scott@TEST> select  /*+ index_combine(emp pk_emp idx_emp_mgr idx_emp_deptno) */ empno,ename,sal,job
   2     from  emp
   3    where  empno=7369  and  mgr=7902  and  deptno=20;
 
      EMPNO ENAME               SAL JOB
---------- ------------------------------ ---------- ---------------------------
       7369 SMITH              800 CLERK
 
 
Execution Plan
----------------------------------------------------------
Plan hash value: 2949544139
 
--------------------------------------------------------------------------------------
| Id  | Operation           |  Name    Rows   | Bytes | Cost (%CPU)|  Time      |
--------------------------------------------------------------------------------------
|   0 |  SELECT  STATEMENT      |        |    1 |    29 |      1   (0)| 00:00:01 |
|*  1 |   TABLE  ACCESS  BY  INDEX  ROWID| EMP    |       1 |    29 |      1   (0)| 00:00:01 |
|*  2 |    INDEX  UNIQUE  SCAN     | PK_EMP |       1 |       |    0   (0)| 00:00:01 |
--------------------------------------------------------------------------------------
......

从上面的执行计划中能够看出没有出现BITMAP相关的关键字,即INDEX_COMBINE Hint被Oracle忽略了。

五、INDEX_FFS

INDEX_FFS是针对单个目标表的Hint,它的含义是让优化器对目标表上的目标索引执行索引快速全扫描操做。注意,索引快速全扫描能成立的前提条件是SELECT语句中全部的查询列都存在于目标索引中,即经过扫描目标索引就能够获得全部的查询列而不用回表。

格式有以下三种:

格式1 /*+ INDEX_FFS(目标表 目标索引) */

格式2 /*+ INDEX_FFS(目标表 目标索引1 目标索引2 …… 目标索引n) */

格式3 /*+ INDEX_FFS(目标表) */

上述3种格式的含义和INDEX中对应格式的含义相同。

使用范例:

1
2
3
4
5
6
7
8
9
10
11
select  /*+ index_ffs(emp pk_emp) */ empno
   from  emp;
 
select  /*+ index_ffs(emp idx_emp_1 idx_emp_2) */ empno
   from  emp
  where  mgr=7902  and  deptno=20;
--create index idx_emp_1 on emp(mgr,deptno,1);
--create index idx_emp_2 on emp(mgr,deptno,2);
 
select  /*+ index_ffs(emp) */ empno
   from  emp;

看下面的实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
scott@TEST> select  empno  from  emp;
 
14  rows  selected.
 
 
Execution Plan
----------------------------------------------------------
Plan hash value: 179099197
 
---------------------------------------------------------------------------
| Id  | Operation    |  Name    Rows   | Bytes | Cost (%CPU)|  Time     |
---------------------------------------------------------------------------
|   0 |  SELECT  STATEMENT |     |    10 |    40 | 1   (0)| 00:00:01 |
|   1 |   INDEX  FULL  SCAN | PK_EMP |    10 |    40 |    1   (0)| 00:00:01 |
---------------------------------------------------------------------------
......
scott@TEST> select  /*+ index_ffs(emp) */empno  from  emp;
 
14  rows  selected.
 
 
Execution Plan
----------------------------------------------------------
Plan hash value: 366039554
 
-------------------------------------------------------------------------------
| Id  | Operation        |  Name    Rows   | Bytes | Cost (%CPU)|  Time      |
-------------------------------------------------------------------------------
|   0 |  SELECT  STATEMENT     |         |    10 |    40 |     2  (0)| 00:00:01 |
|   1 |   INDEX  FAST  FULL  SCAN| PK_EMP |    10 |    40 |     2 (0)| 00:00:01 |
-------------------------------------------------------------------------------
......

六、INDEX_JOIN

INDEX_JOIN是针对单个目标表的Hint,它的含义是让优化器对目标表上的多个目标索引执行INDEX JOIN操做。INDEX JOIN能成立的前提条件是SELECT语句中全部的查询列都存在于目标表上的多个目标索引中,即经过扫描这些索引就能够获得全部的查询列而不用回表。

格式以下:

格式1 /*+ INDEX_JOIN(目标表 目标索引1 目标索引2 …… 目标索引n) */

格式2 /*+ INDEX_JOIN */

上述两种格式的含义与INDEX_COMBINE Hint中对应格式的含义相同。

使用范例:

1
2
3
4
5
6
7
select  /*+ index_join(emp pk_emp idx_emp_mgr) */ empno,mgr
   from  emp
  where  empno>7369  and  mgr<7902;
  
select  /*+ index_join(emp) */ empno,mgr
   from  emp
  where  empno>7369  and  mgr<7902;

来看下面的实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
scott@TEST> select  empno,mgr
   2     from  emp
   3    where  empno>7369  and  mgr<7902;
 
12  rows  selected.
 
 
Execution Plan
----------------------------------------------------------
Plan hash value: 2059184959
 
-------------------------------------------------------------------------------------------
| Id  | Operation           |  Name    Rows   | Bytes | Cost (%CPU)|  Time    |
-------------------------------------------------------------------------------------------
|   0 |  SELECT  STATEMENT      |         |    10 |    80 | 2   (0)| 00:00:01 |
|*  1 |   TABLE  ACCESS  BY  INDEX  ROWID| EMP   |    10 |    80 | 2   (0)| 00:00:01 |
|*  2 |    INDEX  RANGE SCAN      | IDX_EMP_MGR |    11 |    |   1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
......
scott@TEST> select  /*+ index_join(emp) */ empno,mgr
   2     from  emp
   3    where  empno>7369  and  mgr<7902;
 
12  rows  selected.
 
 
Execution Plan
----------------------------------------------------------
Plan hash value: 3030719951
 
---------------------------------------------------------------------------------------
| Id  | Operation      |  Name          Rows   | Bytes | Cost (%CPU)|  Time      |
---------------------------------------------------------------------------------------
|   0 |  SELECT  STATEMENT   |             |    10 |    80 |     3  (34)| 00:00:01 |
|*  1 |   VIEW          index $_join$_001 |    10 |    80 |     3  (34)| 00:00:01 |
|*  2 |   HASH  JOIN      |           |       |       |       |       |
|*  3 |     INDEX  RANGE SCAN| IDX_EMP_MGR      |    10 |    80 |     2  (50)| 00:00:01 |
|*  4 |     INDEX  RANGE SCAN| PK_EMP         |    10 |    80 |     2  (50)| 00:00:01 |
---------------------------------------------------------------------------------------
......

七、AND_EQUAL

AND_EQUAL是针对单个目标表的Hint,它的含义是让优化器对目标表上的多个目标索引执行INDEX MERGE操做。INDEX MERGE能成立的前提条件是目标SQL的where条件里出现了多个针对不一样单列的等值条件,而且这些列上都有单键值的索引。另外,在Oracle数据库里,可以作INDEX MERGE的索引数量的最大值是5。

格式以下:

/*+ AND_EQUAL(目标表 目标索引1 目标索引2 …… 目标索引n)*/

使用范例:

1
2
3
select  /*+ and_equal(emp idx_emp_mgr idx_emp_dept) */ empno,mgr
   from  emp
  where  deptno=20  and  mgr=7902;

看下面的实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
scott@TEST> select  empno,mgr
   2     from  emp
   3    where  deptno=20  and  mgr=7902;
 
 
Execution Plan
----------------------------------------------------------
Plan hash value: 2059184959
 
-------------------------------------------------------------------------------------------
| Id  | Operation           |  Name    Rows   | Bytes | Cost (%CPU)|  Time    |
-------------------------------------------------------------------------------------------
|   0 |  SELECT  STATEMENT      |         |   1 |    11 |   2   (0)| 00:00:01 |
|*  1 |   TABLE  ACCESS  BY  INDEX  ROWID| EMP   |   1 |    11 |   2   (0)| 00:00:01 |
|*  2 |    INDEX  RANGE SCAN      | IDX_EMP_MGR |   2 |      |   1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
......
scott@TEST> select  /*+ and_equal(emp idx_emp_mgr idx_emp_dept) */ empno,mgr
   2     from  emp
   3    where  deptno=20  and  mgr=7902;
 
 
Execution Plan
----------------------------------------------------------
Plan hash value: 3295440569
 
--------------------------------------------------------------------------------------------
| Id  | Operation           |  Name     Rows   | Bytes | Cost (%CPU)|  Time       |
--------------------------------------------------------------------------------------------
|   0 |  SELECT  STATEMENT      |          |  1 |  11 |    3   (0)| 00:00:01 |
|*  1 |   TABLE  ACCESS  BY  INDEX  ROWID| EMP    |  1 |  11 |    3   (0)| 00:00:01 |
|   2 |    AND -EQUAL          |          |    |    |     |      |
|*  3 |     INDEX  RANGE SCAN        | IDX_EMP_MGR  |  2 |     |  1   (0)| 00:00:01 |
|*  4 |     INDEX  RANGE SCAN        | IDX_EMP_DEPT |   5 |     |  1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------
......

4、与表链接顺序相关的Hint

一、ORDERED

ORDERED是针对多个目标表的Hint,它的含义是让优化器对多个目标表执行表链接操做时,执照它们在目标SQL的where条件中出现的顺序从左到右依次进行链接。

格式以下:

/*+ ORDERED */

使用范例:

1
2
3
4
5
6
select  /*+ ordered */ e.ename,j.job,e.sal,d.deptno
   from  emp e,jobs j,dept d 
  where  e.empno=j.empno
    and  e.deptno=d.deptno
    and  d.loc= 'CHICAGO'
  order  by  e.ename;

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
scott@TEST> select  e.ename,j.job,e.sal,d.deptno
   2     from  emp e,jobs j,dept d 
   3    where  e.empno=j.empno
   4      and  e.deptno=d.deptno
   5      and  d.loc= 'CHICAGO'
   6    order  by  e.ename;
 
rows  selected.
 
 
Execution Plan
----------------------------------------------------------
Plan hash value: 4113290228
 
-----------------------------------------------------------------------------------------------
| Id  | Operation                      |  Name          Rows   | Bytes | Cost (%CPU)|  Time      |
-----------------------------------------------------------------------------------------------
|   0 |  SELECT  STATEMENT               |              |     5 |   235 |     9  (23)| 00:00:01 |