oracle Hint 使用
http://docs.oracle.com/cd/B19306_01/server.102/b14211/hintsref.htm
?
?http://database.51cto.com/art/200911/163085.htm
在向大家詳細介紹Oracle Hints之前,首先讓大家了解下Oracle Hints是什么,然后全面介紹Oracle Hints,希望對大家有用。基于代價的優(yōu)化器是很聰明的,在絕大多數(shù)情況下它會選擇正確的優(yōu)化器,減輕了DBA的負擔。但有時它也聰明反被聰明誤,選擇了很差的執(zhí)行計劃,使某個語句的執(zhí)行變得奇慢無比。
此時就需要DBA進行人為的干預,告訴優(yōu)化器使用我們指定的存取路徑或連接類型生成執(zhí)行計劃,從而使語句高效的運行。例如,如果我們認為對于一個特定的語句,執(zhí)行全表掃描要比執(zhí)行索引掃描更有效,則我們就可以指示優(yōu)化器使用全表掃描。在Oracle中,是通過為語句添加 Hints(提示)來實現(xiàn)干預優(yōu)化器優(yōu)化的目的。
Oracle Hints是一種機制,用來告訴優(yōu)化器按照我們的告訴它的方式生成執(zhí)行計劃。我們可以用Oracle Hints來實現(xiàn):
1) 使用的優(yōu)化器的類型
2) 基于代價的優(yōu)化器的優(yōu)化目標,是all_rows還是first_rows。
3) 表的訪問路徑,是全表掃描,還是索引掃描,還是直接利用rowid。
4) 表之間的連接類型
5) 表之間的連接順序
6) 語句的并行程度
除了”RULE”提示外,一旦使用的別的提示,語句就會自動的改為使用CBO優(yōu)化器,此時如果你的數(shù)據(jù)字典中沒有統(tǒng)計數(shù)據(jù),就會使用缺省的統(tǒng)計數(shù)據(jù)。所以建議大家如果使用CBO或Hints提示,則最好對表和索引進行定期的分析。
如何使用Hints:
Hints只應用在它們所在sql語句塊(statement block,由select、update、delete關鍵字標識)上,對其它SQL語句或語句的其它部分沒有影響。如:對于使用union操作的2個 sql語句,如果只在一個sql語句上有Hints,則該Hints不會影響另一個sql語句。
我們可以使用注釋(comment)來為一個語句添加Hints,一個語句塊只能有一個注釋,而且注釋只能放在SELECT, UPDATE, or DELETE關鍵字的后面
使用Oracle Hints的語法:
{DELETE|INSERT|SELECT|UPDATE} /*+ hint [text] [hint[text]]... */
or
{DELETE|INSERT|SELECT|UPDATE} --+ hint [text] [hint[text]]...
注解:
1) DELETE、INSERT、SELECT和UPDATE是標識一個語句塊開始的關鍵字,包含提示的注釋只能出現(xiàn)在這些關鍵字的后面,否則提示無效。
2) “+”號表示該注釋是一個Hints,該加號必須立即跟在”/*”的后面,中間不能有空格。
3) hint是下面介紹的具體提示之一,如果包含多個提示,則每個提示之間需要用一個或多個空格隔開。
4) text 是其它說明hint的注釋性文本
如果你沒有正確的指定Hints,Oracle將忽略該Hints,并且不會給出任何錯誤。
?
====
http://www.360doc.com/content/08/0314/11/7362_1116866.shtml
使用HINT
HINT是一種SQL優(yōu)化的重要手段。在缺省情況下,SQL的執(zhí)行計劃和優(yōu)化方案是數(shù)據(jù)庫的優(yōu)化器自動完成的,不需要編程人員進行干預。但是數(shù)據(jù)庫優(yōu)化器的優(yōu)化方案和執(zhí)行計劃不總是最優(yōu)的。ORACLE數(shù)據(jù)庫提供了開發(fā)人員強制性制定優(yōu)化方案的方法來彌補數(shù)據(jù)庫優(yōu)化器在這方面的不足。這種方法就是使用HINT。
HINT的使用方法是在SQL語句中插入/*+ <規(guī)則> */ 這樣的提示,這些提示需要放在SELECT、UPDATE、DELETE這些詞的后面,比如:
SELECT /*+ FIRST_ROWS */ * FROM T_TEST WHERE R>10;
要注意的是,在早期的Oracle版本中,“/*+”一定要連寫,之間不能有空格,“/*+”后面一定要有空格。需要注意以下幾個問題:
提示將使語句強制執(zhí)行基于成本的優(yōu)化器(除了提示RULE外)
如果表名包含類似<SCHEMA>.<TABLE>或<TABLE>@<DB_LINK>這樣的格式的時候,在HINT里要使用表的別名
確認相關的表都分析過,并且最近一次分析能夠反映出該表現(xiàn)在的狀態(tài)
在SQL語句優(yōu)化過程中,我們經(jīng)常會用到hint,現(xiàn)總結一下在SQL優(yōu)化過程中常見Oracle HINT的用法:
1. /*+ALL_ROWS*/
表明對語句塊選擇基于開銷的優(yōu)化方法,并獲得最佳吞吐量,使資源消耗最小化.
例如:
SELECT /*+ALL+_ROWS*/ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO=‘SCOTT‘;
2. /*+FIRST_ROWS*/
表明對語句塊選擇基于開銷的優(yōu)化方法,并獲得最佳響應時間,使資源消耗最小化.
例如:
SELECT /*+FIRST_ROWS*/ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO=‘SCOTT‘;
3. /*+CHOOSE*/
表明如果數(shù)據(jù)字典中有訪問表的統(tǒng)計信息,將基于開銷的優(yōu)化方法,并獲得最佳的吞吐量;
表明如果數(shù)據(jù)字典中沒有訪問表的統(tǒng)計信息,將基于規(guī)則開銷的優(yōu)化方法;
例如:
SELECT /*+CHOOSE*/ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO=‘SCOTT‘;
4. /*+RULE*/
表明對語句塊選擇基于規(guī)則的優(yōu)化方法.
例如:
SELECT /*+ RULE */ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO=‘SCOTT‘;
5. /*+FULL(TABLE)*/
表明對表選擇全局掃描的方法.
例如:
SELECT /*+FULL(A)*/ EMP_NO,EMP_NAM FROM BSEMPMS A WHERE EMP_NO=‘SCOTT‘;
6. /*+ROWID(TABLE)*/
提示明確表明對指定表根據(jù)ROWID進行訪問.
例如:
SELECT /*+ROWID(BSEMPMS)*/ * FROM BSEMPMS WHERE ROWID>=‘AAAAAAAAAAAAAA‘
AND EMP_NO=‘SCOTT‘;
7. /*+CLUSTER(TABLE)*/
提示明確表明對指定表選擇簇掃描的訪問方法,它只對簇對象有效.
例如:
SELECT /*+CLUSTER */ BSEMPMS.EMP_NO,DPT_NO FROM BSEMPMS,BSDPTMS
WHERE DPT_NO=‘TEC304‘ AND BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;
8. /*+INDEX(TABLE INDEX_NAME)*/
表明對表選擇索引的掃描方法.
例如:
SELECT /*+INDEX(BSEMPMS SEX_INDEX) USE SEX_INDEX BECAUSE THERE ARE FEWMALE BSEMPMS */ FROM BSEMPMS WHERE SEX=‘M‘;
9. /*+INDEX_ASC(TABLE INDEX_NAME)*/
表明對表選擇索引升序的掃描方法.
例如:
SELECT /*+INDEX_ASC(BSEMPMS PK_BSEMPMS) */ FROM BSEMPMS WHERE DPT_NO=‘SCOTT‘;
10. /*+INDEX_COMBINE*/
為指定表選擇位圖訪問路經(jīng),如果INDEX_COMBINE中沒有提供作為參數(shù)的索引,將選擇出位圖索引的布爾組合方式.
例如:
SELECT /*+INDEX_COMBINE(BSEMPMS SAL_BMI HIREDATE_BMI)*/ * FROM BSEMPMS
WHERE SAL<5000000 AND HIREDATE<SYSDATE;
11. /*+INDEX_JOIN(TABLE INDEX_NAME)*/
提示明確命令優(yōu)化器使用索引作為訪問路徑.
例如:
SELECT /*+INDEX_JOIN(BSEMPMS SAL_HMI HIREDATE_BMI)*/ SAL,HIREDATE
FROM BSEMPMS WHERE SAL<60000;
12. /*+INDEX_DESC(TABLE INDEX_NAME)*/
表明對表選擇索引降序的掃描方法.
例如:
SELECT /*+INDEX_DESC(BSEMPMS PK_BSEMPMS) */ FROM BSEMPMS WHERE DPT_NO=‘SCOTT‘;
13. /*+INDEX_FFS(TABLE INDEX_NAME)*/
對指定的表執(zhí)行快速全索引掃描,而不是全表掃描的辦法.
例如:
SELECT /*+INDEX_FFS(BSEMPMS IN_EMPNAM)*/ * FROM BSEMPMS WHERE DPT_NO=‘TEC305‘;
14. /*+ADD_EQUAL TABLE INDEX_NAM1,INDEX_NAM2,...*/
提示明確進行執(zhí)行規(guī)劃的選擇,將幾個單列索引的掃描合起來.
例如:
SELECT /*+INDEX_FFS(BSEMPMS IN_DPTNO,IN_EMPNO,IN_SEX)*/ * FROM BSEMPMS WHERE EMP_NO=‘SCOTT‘ AND DPT_NO=‘TDC306‘;
15. /*+USE_CONCAT*/
對查詢中的WHERE后面的OR條件進行轉換為UNION ALL的組合查詢.
例如:
SELECT /*+USE_CONCAT*/ * FROM BSEMPMS WHERE DPT_NO=‘TDC506‘ AND SEX=‘M‘;
16. /*+NO_EXPAND*/
對于WHERE后面的OR 或者IN-LIST的查詢語句,NO_EXPAND將阻止其基于優(yōu)化器對其進行擴展.
例如:
SELECT /*+NO_EXPAND*/ * FROM BSEMPMS WHERE DPT_NO=‘TDC506‘ AND SEX=‘M‘;
17. /*+NOWRITE*/
禁止對查詢塊的查詢重寫操作.
18. /*+REWRITE*/
可以將視圖作為參數(shù).
19. /*+MERGE(TABLE)*/
能夠對視圖的各個查詢進行相應的合并.
例如:
SELECT /*+MERGE(V) */ A.EMP_NO,A.EMP_NAM,B.DPT_NO FROM BSEMPMS A (SELET DPT_NO
,AVG(SAL) AS AVG_SAL FROM BSEMPMS B GROUP BY DPT_NO) V WHERE A.DPT_NO=V.DPT_NO
AND A.SAL>V.AVG_SAL;
20. /*+NO_MERGE(TABLE)*/
對于有可合并的視圖不再合并.
例如:
SELECT /*+NO_MERGE(V) */ A.EMP_NO,A.EMP_NAM,B.DPT_NO FROM BSEMPMS A (SELECT DPT_NO,AVG(SAL) AS AVG_SAL FROM BSEMPMS B GROUP BY DPT_NO) V WHERE A.DPT_NO=V.DPT_NO AND A.SAL>V.AVG_SAL;
21. /*+ORDERED*/
根據(jù)表出現(xiàn)在FROM中的順序,ORDERED使ORACLE依此順序對其連接.
例如:
SELECT /*+ORDERED*/ A.COL1,B.COL2,C.COL3 FROM TABLE1 A,TABLE2 B,TABLE3 C WHERE A.COL1=B.COL1 AND B.COL1=C.COL1;
22. /*+USE_NL(TABLE)*/
將指定表與嵌套的連接的行源進行連接,并把指定表作為內部表.
例如:
SELECT /*+ORDERED USE_NL(BSEMPMS)*/ BSDPTMS.DPT_NO,BSEMPMS.EMP_NO,BSEMPMS.EMP_NAM FROM BSEMPMS,BSDPTMS WHERE BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;
23. /*+USE_MERGE(TABLE)*/
將指定的表與其他行源通過合并排序連接方式連接起來.
例如:
SELECT /*+USE_MERGE(BSEMPMS,BSDPTMS)*/ * FROM BSEMPMS,BSDPTMS WHERE BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;
24. /*+USE_HASH(TABLE)*/
將指定的表與其他行源通過哈希連接方式連接起來.
例如:
SELECT /*+USE_HASH(BSEMPMS,BSDPTMS)*/ * FROM BSEMPMS,BSDPTMS WHERE BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;
25. /*+DRIVING_SITE(TABLE)*/
強制與ORACLE所選擇的位置不同的表進行查詢執(zhí)行.
例如:
SELECT /*+DRIVING_SITE(DEPT)*/ * FROM BSEMPMS,DEPT@BSDPTMS WHERE BSEMPMS.DPT_NO=DEPT.DPT_NO;
26. /*+LEADING(TABLE)*/
將指定的表作為連接次序中的首表.
27. /*+CACHE(TABLE)*/
當進行全表掃描時,CACHE提示能夠將表的檢索塊放置在緩沖區(qū)緩存中最近最少列表LRU的最近使用端
例如:
SELECT /*+FULL(BSEMPMS) CAHE(BSEMPMS) */ EMP_NAM FROM BSEMPMS;
28. /*+NOCACHE(TABLE)*/
當進行全表掃描時,CACHE提示能夠將表的檢索塊放置在緩沖區(qū)緩存中最近最少列表LRU的最近使用端
例如:
SELECT /*+FULL(BSEMPMS) NOCAHE(BSEMPMS) */ EMP_NAM FROM BSEMPMS;
29. /*+APPEND*/
直接插入到表的最后,可以提高速度.
insert /*+append*/ into test1 select * from test4 ;
30. /*+NOAPPEND*/
通過在插入語句生存期內停止并行模式來啟動常規(guī)插入.
insert /*+noappend*/ into test1 select * from test4 ;
?
http://blog.csdn.net/tianlesoftware/article/details/5833020
Hint 是Oracle 提供的一種SQL語法,它允許用戶在SQL語句中插入相關的語法,從而影響SQL的執(zhí)行方式。
?
因為Hint的特殊作用,所以對于開發(fā)人員不應該在代碼中使用它,Hint 更像是Oracle提供給DBA用來分析問題的工具 。在SQL代碼中使用Hint,可能導致非常嚴重的后果,因為數(shù)據(jù)庫的數(shù)據(jù)是變化的,在某一時刻使用這個執(zhí)行計劃是最優(yōu)的,在另一個時刻,卻可能很差,這也是CBO 取代RBO的原因之一,規(guī)則是死的,而數(shù)據(jù)是時刻變化的,為了獲得最正確的執(zhí)行計劃,只有知道表中數(shù)據(jù)的實際情況,通過計算各種執(zhí)行計劃的成本,則其最優(yōu),才是最科學的,這也是CBO的工作機制。 在SQL代碼中加入Hint,特別是性能相關的Hint是很危險的做法。
Hints
Hints are comments in a SQL statement that pass instructions to the Oracle Database optimizer. The optimizer uses these hints to choose an execution plan for the statement, unless some condition exists that prevents the optimizer from doing so.
Hints were introduced in Oracle7, when users had little recourse if the optimizer generated suboptimal plans. Now Oracle provides a number of tools, including the SQL Tuning Advisor, SQL plan management, and SQL Performance Analyzer, to help you address performance problems that are not solved by the optimizer. Oracle strongly recommends that you use those tools rather than hints. The tools are far superior to hints, because when used on an ongoing basis, they provide fresh solutions as your data and database environment change.
Hints should be used sparingly, and only after you have collected statistics on the relevant tables and evaluated the optimizer plan without hints using the EXPLAIN PLAN statement. Changing database conditions as well as query performance enhancements in subsequent releases can have significant impact on how hints in your code affect performance.
The remainder of this section provides information on some commonly used hints. If you decide to use hints rather than the more advanced tuning tools, be aware that any short-term benefit resulting from the use of hints may not continue to result in improved performance over the long term.
Oracle 聯(lián)機文檔對Hint的說明:
http://download.oracle.com/docs/cd/E11882_01/server.112/e10592/sql_elements006.htm#SQLRF50705
?
之前整理的一篇文章:
常見Oracle HINT的用法
http://blog.csdn.net/tianlesoftware/archive/2009/12/13/4969702.aspx
?
在使用Hint時需要注意的一點是,并非任何時刻Hint都起作用。 導致HINT 失效的原因有如下2點:
(1)?????? 如果CBO 認為使用Hint 會導致錯誤的結果時,Hint將被忽略。
如索引中的記錄因為空值而和表的記錄不一致時,結果就是錯誤的,會忽略hint。
(2)?????? 如果表中指定了別名,那么Hint中也必須使用別名,否則Hint也會忽略。
Select /*+full(a)*/ * from t a; -- 使用hint
Select /*+full(t) */ * from t a; --不使用hint
?
?
?
根據(jù)hint的功能,可以分成如下幾類:
????????
| Hint | Hint 語法 |
| 優(yōu)化器模式提示 | ALL_ROWS Hint FIRST_ROWS Hint |
| RULE Hint | |
| 訪問路徑提示 | CLUSTER Hint |
| FULL Hint | |
| HASH Hint | |
| INDEX Hint NO_INDEX Hint | |
| INDEX_ASC Hint INDEX_DESC Hint | |
| INDEX_COMBINE Hint | |
| INDEX_FFS Hint | |
| INDEX_SS Hint | |
| INDEX_SS_ASC Hint | |
| INDEX_SS_DESC Hint | |
| NO_INDEX_FFS Hint | |
| NO_INDEX_SS Hint | |
| ORDERED Hint | |
| LEADING Hint | |
| USE_HASH Hint NO_USE_HASH Hint | |
| 表連接順序提示 | USE_MERGE Hint NO_USE_MERGE Hint |
| USE_NL Hint USE_NL_WITH_INDEX Hint NO_USE_NL Hint | |
| 表關聯(lián)方式提示 | PARALLEL Hint NO_PARALLEL Hint |
| PARALLEL_INDEX Hint NO_PARALLEL_INDEX Hint | |
| PQ_DISTRIBUTE Hint | |
| 并行執(zhí)行提示 | FACT Hint NO_FACT Hint |
| MERGE Hint NO_MERGE Hint | |
| NO_EXPAND Hint | |
| USE_CONCAT Hint | |
| 查詢轉換提示 | REWRITE Hint NO_REWRITE Hint |
| UNNEST Hint NO_UNNEST Hint | |
| STAR_TRANSFORMATION Hint NO_STAR_TRANSFORMATION Hint | |
| NO_QUERY_TRANSFORMATION Hint | |
| APPEND Hint NOAPPEND Hint | |
| CACHE Hint NOCACHE Hint | |
| CURSOR_SHARING_EXACT Hint | |
| 其他Hint | DRIVING_SITE Hint |
| DYNAMIC_SAMPLING Hint | |
| PUSH_PRED Hint NO_PUSH_PRED Hint | |
| PUSH_SUBQ Hint NO_PUSH_SUBQ Hint | |
| PX_JOIN_FILTER Hint NO_PX_JOIN_FILTER Hint | |
| NO_XML_QUERY_REWRITE Hint | |
| QB_NAME Hint | |
| MODEL_MIN_ANALYSIS Hint |
?
一.???????? 和優(yōu)化器相關的Hint
Oracle 允許在系統(tǒng)級別,會話級別和SQL中(hint)優(yōu)化器類型:
???????? 系統(tǒng)級別:
?????????????????? SQL>alter system set optimizer_mode=all_rows;
??????? 會話級別:
?????????????????? SQL>alter system set optimizer_mode=all_rows;
?
關于優(yōu)化器,參考:
???????? Oracle Optimizer CBO RBO
http://blog.csdn.net/tianlesoftware/archive/2010/08/19/5824886.aspx
?
1.1?? ALL_ROWS 和FIRST_ROWS(n) -- CBO 模式
?
對于OLAP系統(tǒng),這種系統(tǒng)中通常都是運行一些大的查詢操作,如統(tǒng)計,報表等任務。 這時優(yōu)化器模式應該選擇ALL_ROWS.? 對于一些分頁顯示的業(yè)務,就應該用FIRST_ROWS(n)。 如果是一個系統(tǒng)上運行這兩種業(yè)務,那么就需要在SQL 用hint指定優(yōu)化器模式。
?
如:
???????? SQL> select /* + all_rows*/ * from dave;
???????? SQL> select /* + first_rows(20)*/ * from dave;
?
1.2 ????? RULE Hint?? -- RBO 模式
盡管Oracle 10g已經(jīng)棄用了RBO,但是仍然保留了這個hint。 它允許在CBO 模式下使用RBO 對SQL 進行解析。
如:
SQL> show parameter optimizer_mode
NAME???????????????????????????????? TYPE??????? VALUE
------------------------------------ ----------- ------------------------------
optimizer_mode?????????????????????? string????? ALL_ROWS
SQL> set autot trace exp;
SQL> select /*+rule */ * from dave;
?
執(zhí)行計劃
----------------------------------------------------------
Plan hash value: 3458767806
----------------------------------
| Id? | Operation???????? | Name |
----------------------------------
|?? 0 | SELECT STATEMENT? |????? |
|?? 1 |? TABLE ACCESS FULL| DAVE |
----------------------------------
Note
-----
? ?- rule based optimizer used (consider using cbo)? -- 這里提示使用RBO
SQL>
?
二.???????? 訪問路徑相關的Hint
?
這一部分hint 將直接影響SQL 的執(zhí)行計劃,所以在使用時需要特別小心。 該類Hint對DBA分析SQL性能非常有幫助,DBA 可以讓SQL使用不同的Hint得到不同的執(zhí)行計劃,通過比較不同的執(zhí)行計劃來分析當前SQL性能。
?
2.1?? FULL Hint
該Hint告訴優(yōu)化器對指定的表通過全表掃描的方式訪問數(shù)據(jù)。
示例:
???????? SQL> select /*+full(dave) */ * from dave;
?
要注意,如果表有別名,在hint里也要用別名, 這點在前面已經(jīng)說明。
?
2.2 ????? INDEX Hint
Index hint 告訴優(yōu)化器對指定的表通過索引的方式訪問數(shù)據(jù),當訪問索引會導致結果集不完整時,優(yōu)化器會忽略這個Hint。
?
示例:
???????? SQL> select /*+index(dave index_dave) */ * from dave where id>1;
?
謂詞里有索引字段,才會用索引。
?
2.3 ????? NO_INDEX Hint
No_index hint 告訴優(yōu)化器對指定的表不允許使用索引。
?
示例:
???????? SQL> select /*+no_index(dave index_dave) */ * from dave where id>1;
?
2.4 ????? INDEX_DESC Hint
???????? 該Hint 告訴優(yōu)化器對指定的索引使用降序方式訪問數(shù)據(jù),當使用這個方式會導致結果集不完整時,優(yōu)化器將忽略這個索引。
????????
示例:
?????????????????? SQL> select /*+index_desc(dave index_dave) */ * from dave where id>1;
?
2.5 ?????? INDEX_COMBINE Hint
???????? 該Hint告訴優(yōu)化器強制選擇位圖索引,當使用這個方式會導致結果集不完整時,優(yōu)化器將忽略這個Hint。
????????
???????? 示例:
?????????????????? SQL> select /*+ index_combine(dave index_bm) */ * from dave;
?
2.6 ????? INDEX_FFS Hint
???????? 該hint告訴優(yōu)化器以INDEX_FFS(INDEX Fast Full Scan)的方式訪問數(shù)據(jù)。當使用這個方式會導致結果集不完整時,優(yōu)化器將忽略這個Hint。
???????? 示例:
?????????????????? SQL> select /*+ index_ffs(dave index_dave) */ id from dave where id>0;
?
2.7 ?????? INDEX_JOIN Hint
???????? 索引關聯(lián),當謂詞中引用的列上都有索引時,可以通過索引關聯(lián)的方式來訪問數(shù)據(jù)。
????????
示例:????
???????? SQL> select /*+ index_join(dave index_dave index_bm) */ * from dave where id>0 and name='安徽安慶';
?
2.8 ????? INDEX_SS Hint
???????? 該Hint強制使用index skip scan 的方式訪問索引,從Oracle 9i開始引入這種索引訪問方式,當在一個聯(lián)合索引中,某些謂詞條件并不在聯(lián)合索引的第一列時(或者謂詞并不在聯(lián)合索引的第一列時),可以通過index skip scan 來訪問索引獲得數(shù)據(jù)。 當聯(lián)合索引第一列的唯一值很小時,使用這種方式比全表掃描效率要高。當使用這個方式會導致結果集不完整時,優(yōu)化器將忽略這個Hint。
?
?
???????? 示例:
?????????????????? SQL> select /*+ index_ss(dave index_union) */ * from dave where id>0;
?
?
三.???????? 表關聯(lián)順序的Hint
表之間的連接方式有三種。 具體參考blog:
???????? 多表連接的三種方式詳解 HASH JOIN MERGE JOIN NESTED LOOP
????? http://blog.csdn.net/tianlesoftware/archive/2010/08/20/5826546.aspx
?
3.1 ????? LEADING hint
???????? 在一個多表關聯(lián)的查詢中,該Hint指定由哪個表作為驅動表,告訴優(yōu)化器首先要訪問哪個表上的數(shù)據(jù)。
????????
???????? 示例:
?
SQL> select /*+leading(t1,t) */ * from scott.dept t,scott.emp t1 where t.deptno=t1.deptno;
?
SQL> select /*+leading(t,t1) */ * from scott.dept t,scott.emp t1 where t.deptno=t1.deptno;
--------------------------------------------------------------------------------
| Id? | Operation??????????????????? | Name??? | Rows? | Bytes | Cost (%CPU)| Ti
--------------------------------------------------------------------------------
|?? 0 | SELECT STATEMENT???????????? |?? ??????|??? 14 |?? 812 |???? 6? (17)| 00
|?? 1 |? MERGE JOIN????????????????? |???????? |??? 14 |?? 812 |???? 6? (17)| 00
|?? 2 |?? TABLE ACCESS BY INDEX ROWID| DEPT??? |???? 4 |??? 80 |???? 2?? (0)| 00
|?? 3 |??? INDEX FULL SCAN?????????? | PK_DEPT |???? 4 |?????? |???? 1?? (0)| 00
|*? 4 |?? SORT JOIN????????????????? |???????? |??? 14 |?? 532 |???? 4? (25)| 00
|?? 5 |??? TABLE ACCESS FULL???????? | EMP???? |??? 14 |?? 532 |???? 3?? (0)| 00
--------------------------------------------------------------------------------
?
3.2 ????? ORDERED Hint
???????? 該hint 告訴Oracle 按照From后面的表的順序來選擇驅動表,Oracle 建議在選擇驅動表上使用Leading,它更靈活一些。
????????
SQL> select /*+ordered */ * from scott.dept t,scott.emp t1 where t.deptno=t1.deptno;
?
?
四.???????? 表關聯(lián)操作的Hint
?
4.1 ????? USE_HASH,USE_NL,USE_MERGE hint
?
表之間的連接方式有三種。 具體參考blog:
???????? 多表連接的三種方式詳解 HASH JOIN MERGE JOIN NESTED LOOP
????? http://blog.csdn.net/tianlesoftware/archive/2010/08/20/5826546.aspx
?
這三種關聯(lián)方式是多表關聯(lián)中主要使用的關聯(lián)方式。 通常來說,當兩個表都比較大時,Hash Join的效率要高于嵌套循環(huán)(nested loops)的關聯(lián)方式。
?
???????? Hash join的工作方式是將一個表(通常是小一點的那個表)做hash運算,將列數(shù)據(jù)存儲到hash列表中,從另一個表中抽取記錄,做hash運算,到hash 列表中找到相應的值,做匹配。
????????
Nested loops 工作方式是從一張表中讀取數(shù)據(jù),訪問另一張表(通常是索引)來做匹配,nested loops適用的場合是當一個關聯(lián)表比較小的時候,效率會更高。
?
???????? Merge Join 是先將關聯(lián)表的關聯(lián)列各自做排序,然后從各自的排序表中抽取數(shù)據(jù),到另一個排序表中做匹配,因為merge join需要做更多的排序,所以消耗的資源更多。 通常來講,能夠使用merge join的地方,hash join都可以發(fā)揮更好的性能。
?
USE_HASH,USE_NL,USE_MERGE? 這三種hint 就是告訴優(yōu)化器使用哪種關聯(lián)方式。
?
?示例如下:
???????? SQL> select /*+use_hash(t,t1) */ * from scott.dept t,scott.emp t1 where t.deptno=t1.deptno;
???????? SQL> select /*+use_nl(t,t1) */ * from scott.dept t,scott.emp t1 where t.deptno=t1.deptno;
???????? SQL> select /*+use_merge(t,t1) */ * from scott.dept t,scott.emp t1 where t.deptno=t1.deptno;
?
4.2 NO_USE_HASH,NO_USE_NL,NO_USE_MERGE HINT
???????? 分別禁用對應的關聯(lián)方式。
?
示例:
???????? SQL> select /*+no_use_merge(t,t1) */ * from scott.dept t,scott.emp t1 where t.deptno=t1.deptno;
???????? SQL> select /*+no_use_nl(t,t1) */ * from scott.dept t,scott.emp t1 where t.deptno=t1.deptno;
???????? SQL> select /*+no_use_hash(t,t1) */ * from scott.dept t,scott.emp t1 where t.deptno=t1.deptno;
?
?
五.???????? 并行執(zhí)行相關的Hint
?
5.1 ????? PARALLEL HINT?????
???????? 指定SQL 執(zhí)行的并行度,這個值會覆蓋表自身設定的并行度,如果這個值為default,CBO使用系統(tǒng)參數(shù)值。
?
示例:
???????? SQL> select /*+parallel(t 4) */ * from scott.dept t;
?
關于表的并行度,我們在創(chuàng)建表的時候可以指定,如:
SQL> CREATE TABLE Anqing
? 2? (
? 3? name VARCHAR2 (10)
? 4? )
? 5 ?PARALLEL 2;
表已創(chuàng)建。
SQL> select degree from all_tables where table_name = 'ANQING'; ?-- 查看表的并行度
DEGREE
--------------------
???????? 2
SQL> alter table anqing parallel(degree 3);? -- 修改表的并行度
表已更改。
SQL> select degree from all_tables where table_name = 'ANQING';
DEGREE
--------------------
???????? 3
SQL> alter table anqing noparallel;? -- 取消表的并行度
表已更改。
SQL> select degree from all_tables where table_name = 'ANQING';
DEGREE
--------------------
???????? 1
?
?
5.2 NO_PARALLEL HINT
???????? 在SQL中禁止使用并行。
?
???????? 示例:
?????????????????? SQL> select /*+ no_parallel(t) */ * from scott.dept t;
?
?
六.???????? 其他方面的一些Hint
?
6.1 ?APPEND HINT
???????? 提示數(shù)據(jù)庫以直接加載的方式(direct load)將數(shù)據(jù)加載入庫。
????????
???????? 示例:
?????????????????? Insert? /*+append */ into t as select * from all_objects;
?
這個hint 用的比較多。 尤其在插入大量的數(shù)據(jù),一般都會用此hint。
???????? Oracle 插入大量數(shù)據(jù)
http://blog.csdn.net/tianlesoftware/archive/2009/10/30/4745144.aspx
?
6.2 DYNAMIC_SAMPLING HINT
???????? 提示SQL 執(zhí)行時動態(tài)采樣的級別。 這個級別從0-10,它將覆蓋系統(tǒng)默認的動態(tài)采樣級別。
?
示例:
???????? SQL> select /*+ dynamic_sampling(t 2) */ * from scott.emp t where t.empno>0;
?
?
6.3 DRIVING_SITE HINT
???????? 這個提示在分布式數(shù)據(jù)庫操作中比較有用,比如我們需要關聯(lián)本地的一張表和遠程的表:
?????????????????? Select /* + driving_site(departmetns) */ * from employees,departments@dblink where
?employees .department_id = departments.department_id;
?
如果沒有這個提示,Oracle 會在遠端機器上執(zhí)行departments 表查詢,將結果送回本地,再和employees表關聯(lián)。 如果使用driving_site(departments), Oracle將查詢本地表employees,將結果送到遠端,在遠端將數(shù)據(jù)庫上的表與departments關聯(lián),然后將查詢的結果返回本地。
?
???????? 如果departments查詢結果很大,或者employees查詢結果很小,并且兩張表關聯(lián)之后的結果集很小,那么就可以考慮把本地的結果集發(fā)送到遠端。 在遠端執(zhí)行完后,在將較小的最終結果返回本地。
?
6.4 ????? CACHE HINT
???????? 在全表掃描操作中,如果使用這個提示,Oracle 會將掃描的到的數(shù)據(jù)塊放到LRU(least recently Used: 最近很少被使用列表,是Oracle 判斷內存中數(shù)據(jù)塊活躍程度的一個算法)列表的最被使用端(數(shù)據(jù)塊最活躍端),這樣數(shù)據(jù)塊就可以更長時間地駐留在內存當中。 如果有一個經(jīng)常被訪問的小表,這個設置會提高查詢的性能;同時CACHE也是表的一個屬性,如果設置了表的cache屬性,它的作用和hint一樣,在一次全表掃描之后,數(shù)據(jù)塊保留在LRU列表的最活躍端。
?
???????? 示例:
?????????????????? SQL> select /*+full(t) cache (t) */ * from scott.emp;
?
?
?
小結:
???????? 對于DBA來講,掌握一些Hint操作,在實際性能優(yōu)化中有很大的好處,比如我們發(fā)現(xiàn)一條SQL的執(zhí)行效率很低,首先我們應當查看當前SQL的執(zhí)行計劃,然后通過hint的方式來改變SQL的執(zhí)行計劃,比較這兩條SQL 的效率,作出哪種執(zhí)行計劃更優(yōu),如果當前執(zhí)行計劃不是最優(yōu)的,那么就需要考慮為什么CBO 選擇了錯誤的執(zhí)行計劃。當CBO 選擇錯誤的執(zhí)行計劃,我們需要考慮表的分析是否是最新的,是否對相關的列做了直方圖,是否對分區(qū)表做了全局或者分區(qū)分析等因素。
?
?
???????? 關于執(zhí)行計劃參考:
?????????????????? Oracle Explain Plan
?????????????????? http://blog.csdn.net/tianlesoftware/archive/2010/08/20/5827245.aspx
?
?
總之,在處理問題時,我們要把問題掌握在可控的范圍內,不能將問題擴大化,甚至失控。 作為一個DBA,需要的扎實的基本功,還有膽大心細,遇事不慌。
?
?
?
總結
以上是生活随笔為你收集整理的oracle Hint 使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 表里有索引,为什么还都是全表扫描?
- 下一篇: Oracle查看死锁 .