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 |
相關文章
相關標籤/搜索