新四季網

Oracle RAC講解(詳解Oracle中常見的Hint)

2023-04-18 23:27:53 1

概述

Oracle中的Hint可以用來調整SQL的執行計劃,提高SQL執行效率。下面分類介紹Oracle資料庫中常見的Hint。這裡主要介紹Oracle11gR2中的常見Hint。像我們在做優化的時候,如果一個sql執行效率比較低,我們可以用不同的hint來看下執行計劃,對比選擇最優的hint,如果CBO選擇了不好的執行計劃,就要考慮是不是沒對表做統計分析了...

一、與優化器模式相關的Hint

1、ALL_ROWS

ALL_ROWS是針對整個目標SQL的Hint,它的含義是讓優化器啟用CBO,而且在得到目標SQL的執行計劃時會選擇那些吞吐量最佳的執行路徑。這裡的「吞吐量最佳」是指資源消耗量(即對I/O、CPU等硬體資源的消耗量)最小,也就是說在ALL_ROWS Hint生效的情況下,優化器會啟用CBO而且會依據各個執行路徑的資源消耗量來計算它們各自的成本。

ALL_ROWS Hint的格式如下:

/* ALL_ROWS */

set line 200set autotrace onselect /* all_rows */ empno,ename,sal,job from emp where empno=7396;

從Oracle10g開始,ALL_ROWS就是默認的優化器模式,啟用的就是CBO。

show parameter optimizer_mode;

如果目標SQL中除了ALL_ROWS之外還使用了其他與執行路徑、表連接相關的Hint,優化器會優先考慮ALL_ROWS。

2、FIRST_ROWS(n)

FIRST_ROWS(n)是針對整個目標SQL的Hint,它的含義是讓優化器啟用CBO模式,而且在得到目標SQL的執行計劃時會選擇那些能以最快的響應時間返回頭n條記錄的執行路徑,也就是說在FIRST_ROWS(n) Hint生效的情況下,優化器會啟用CBO,而且會依據返回頭n條記錄的響應時間來決定目標SQL的執行計劃。

FIRST_ROWS(n)格式如下:

/* FIRST_ROWS(n) */

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

上述SQL中使用了/* first_rows(10) */,其含義是告訴優化器我們想以最短的響應時間返回滿足條件"deptno=30"的前10條記錄,並不是只返回10條,這裡需要注意。

注意,FIRST_ROWS(n) Hint和優化器模式FIRST_ROWS_n不是一一對應的。優化器模式FIRST_ROWS_n中的n只能是1、10、100、1000。但FIRST_ROWS(n) Hint中的n還可以是其他值。

3、RULE(基本不用)

RULE是針對整個目標SQL的Hint,它表示對目標SQL啟用RBO。

格式如下:

/* RULE */

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跑出正確執行計劃的概率將大大降低。

二、與表訪問相關的Hint

1、FULL

FULL是針對單個目標表的Hint,它的含義是讓優化器對目標表執行全表掃描。

格式如下:

/* FULL(目標表) */

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

上述SQL中Hint的含義是讓優化器對目標表EMP執行全表掃描操作,而不考慮走表EMP上的任何索引(即使列EMPNO上有主鍵索引)。

2、ROIWD

ROIWD是針對單個目標表的Hint,它的含義是讓優化器對目標表執行RWOID掃描。只有目標SQL中使用了含ROWID的where條件時ROWID Hint才有意義。

格式如下:

/* ROWID(目標表) */

select /* rowid(emp) */ empno,ename,sal,job from emp where rowid='AAAR3xAAEAAAACXAAN';

Oracle 11gR2中即使使用了ROWID Hint,Oracle還是會將讀到的塊緩存在Buffer Cache中。

三、與索引訪問相關的Hint

1、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個目標索引,只不過此時是用指定目標索引的索引列名來代替對應的目標索引名。如果目標索引是複合索引,則在用於指定該索引列名的括號內也可以指定該目標索引的多個索引列,各個索引列之間用空格分隔就可以了。

格式的表示指定了目標表上所有已存在的索引,此時優化器只會考慮對該目標表上所有已存在的索引執行索引掃描操作,而不會去考慮全表掃描操作。注意,這裡優化器在考慮該目標表上所有已存在的索引時,可能是分別計算出單獨掃描這些索引的成本後再選擇其中成本值最低的索引;也可能是先分別掃描這些索引中的兩個或多個索引,然後再對掃描結果執行合併操作。當然,後面這種可能性的前提條件是優化器計算出來這樣做的成本值是最低的。

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;

2、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表示指定了目標表上的所有已存在的索引,即此時優化器不會考慮對該目標表上所有已存在的索引執行索引掃描操作,這相當於對目標表指定了全表掃描。

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;

2、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(目標表) */

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;

3、INDEX_JOIN

INDEX_JOIN是針對單個目標表的Hint,它的含義是讓優化器對目標表上的多個目標索引執行INDEX JOIN操作。INDEX JOIN能成立的前提條件是SELECT語句中所有的查詢列都存在於目標表上的多個目標索引中,即通過掃描這些索引就可以得到所有的查詢列而不用回表。

格式如下:

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

上述兩種格式的含義與INDEX_COMBINE Hint中對應格式的含義相同。

select /* index_join(emp pk_emp idx_emp_mgr) */ empno,mgr from emp where empno>7369 and mgr7369 and mgr7369 and mgr7369 and mgrEMP->JOBS,但是使用ordered Hint後,表掃描的順序變為了EMP->JOBS->DEPT與目標SQL中的順序一致了,在修改了目標SQL文本之後表的掃描順序也相應地變為了EMP->DEPT->JOBS。

2、LEADING

LEADING是針對多個目標表的Hint,它的含義是讓優化器將我們指定的多個表的連接結果作為目標SQL表連接過程中的驅動結果集,並且將LEADING Hint中從左至右出現的第一個目標表作為整個表連接過程中的首個驅動表。

LEADING比ORDERED要溫和一些,因為它只是指定了首個驅動表和驅動結果集,沒有像ORDERED那樣完全指定了表連接的順序,也就是說LEADING給了優化器更大的調整餘地。

當LEADING Hint中指定的表並不能作為目標SQL的連接過程中的驅動表或者驅動結果集時,Oracle會忽略該Hint。

格式如下:

/* LEADING(目標表1 目標表2 …… 目標表n) */

select /* leading(t e) */ e.ename,j.job,e.sal,d.deptno from emp e,jobs j,dept d,emp_temp t where e.empno=j.empno and e.deptno=d.deptno and d.loc='CHICAGO' and e.ename=t.ename order by e.ename;

實例:

select e.ename,j.job,e.sal,d.deptno from emp e,jobs j,dept d,emp_temp t where e.empno=j.empno and e.deptno=d.deptno and d.loc='CHICAGO' and e.ename=t.ename order by e.ename;select /* leading(t e) */ e.ename,j.job,e.sal,d.deptno from emp e,jobs j,dept d,emp_temp t where e.empno=j.empno and e.deptno=d.deptno and d.loc='CHICAGO' and e.ename=t.ename order by e.ename;select /* ordered */ e.ename,j.job,e.sal,d.deptno from emp e,jobs j,dept d,emp_temp t where e.empno=j.empno and e.deptno=d.deptno and d.loc='CHICAGO' and e.ename=t.ename order by e.ename;

從上面的執行計劃可以看出不使用Hint時表掃描順序是DEPT->EMP->JOBS->EMP_TEMP;使用LEADING Hint時表掃描順序是EMP_TEMP->EMP->DEPT->JOBS,EMP_TEMP做首個驅動表和表EMP的連接結果做為驅動結果集,與Hint要求一致。;使用Ordered Hint時表掃描順序是EMP->JOBS->DEPT->EMP_TEMP,與SQL中順序一致。

篇幅有限,關於oracle常見的一些hint就介紹到這了,如果大家想深入學習資料庫的話hint這一塊內容還是必不可少的,特別是做優化的時候。

後面會分享更多關於DBA方面內容,感興趣的朋友可以關注下!

,
同类文章
葬禮的夢想

葬禮的夢想

夢見葬禮,我得到了這個夢想,五個要素的五個要素,水火只好,主要名字在外面,職業生涯良好,一切都應該對待他人治療誠意,由於小,吉利的冬天夢想,秋天的夢是不吉利的
找到手機是什麼意思?

找到手機是什麼意思?

找到手機是什麼意思?五次選舉的五個要素是兩名士兵的跡象。與他溝通很好。這是非常財富,它擅長運作,職業是仙人的標誌。單身男人有這個夢想,主要生活可以有人幫忙
我不怎麼想?

我不怎麼想?

我做了什麼意味著看到米飯烹飪?我得到了這個夢想,五線的主要土壤,但是Tu Ke水是錢的跡象,職業生涯更加真誠。他真誠地誠實。這是豐富的,這是夏瑞的巨星
夢想你的意思是什麼?

夢想你的意思是什麼?

你是什​​麼意思夢想的夢想?夢想,主要木材的五個要素,水的跡象,主營業務,主營業務,案子應該抓住魅力,不能疏忽,春天夢想的吉利夢想夏天的夢想不幸。詢問學者夢想
拯救夢想

拯救夢想

拯救夢想什麼意思?你夢想著拯救人嗎?拯救人們的夢想有一個現實,也有夢想的主觀想像力,請參閱週宮官方網站拯救人民夢想的詳細解釋。夢想著敵人被拯救出來
2022愛方向和生日是在[質量個性]中

2022愛方向和生日是在[質量個性]中

[救生員]有人說,在出生88天之前,胎兒已經知道哪天的出生,如何有優質的個性,將走在什麼樣的愛情之旅,將與生活生活有什么生活。今天
夢想切割剪裁

夢想切割剪裁

夢想切割剪裁什麼意思?你夢想切你的手是好的嗎?夢想切割手工切割手有一個真正的影響和反應,也有夢想的主觀想像力。請參閱官方網站夢想的細節,以削減手
夢想著親人死了

夢想著親人死了

夢想著親人死了什麼意思?你夢想夢想你的親人死嗎?夢想有一個現實的影響和反應,還有夢想的主觀想像力,請參閱夢想世界夢想死亡的親屬的詳細解釋
夢想搶劫

夢想搶劫

夢想搶劫什麼意思?你夢想搶劫嗎?夢想著搶劫有一個現實的影響和反應,也有夢想的主觀想像力,請參閱週恭吉夢官方網站的詳細解釋。夢想搶劫
夢想缺乏缺乏紊亂

夢想缺乏缺乏紊亂

夢想缺乏缺乏紊亂什麼意思?你夢想缺乏異常藥物嗎?夢想缺乏現實世界的影響和現實,還有夢想的主觀想像,請看官方網站的夢想組織缺乏異常藥物。我覺得有些東西缺失了