使用优化器提示(Optimizer Hints)
優化器提示(Optimizer Hints)可以用在SQL語句中改變執行計劃。
?
理解優化器提示
提示讓你作出決定,這決定一般由優化器來作出。作為一個應用的設計者,你知道一些優化器不知道的關于你的數據的信息。提示提供了一種機制來指導優化器基于特殊條件下選擇某個查詢執行計劃。
例如,對于某些查詢,你知道一個索引更具選擇性。在這些信息基礎上,你可以比優化器選擇出一個更有效率的執行計劃。在這樣的情況下,使用提示來指導優化器使用最優執行計劃。
注意:使用提示包含了必須管理、檢查和控制的額外代碼。
?
提示的類型
提示包括以下類型:
1. Single-table:Single-table提示是特定在一個表或視圖上。INDEX和USE_NL是single-table提示的例子。
2. Multi-table:Multi-table提示與single-table提示相似,除了它可以特定在一個或多個表或視圖上。LEADING是multi-table提示的一個例子。注意USE_NL(table1 table2)不能認為是multi-table提示,因為它實際是USE_NL(table1)和USE_NL(table2)的快捷方式。
3. Query block:Query block提示在單個查詢塊中操作。STAR_TRANSFORMATION和UNNEST是query block提示的例子。
4. Statement:Statement提示應用在整個SQL語句中。ALL_ROWS是Statement提示的一個例子。
?
提示分成以下幾種分類:
1. 用于優化方法和目標的提示
2. 用于訪問路徑的提示
3. 用于查詢轉換的提示
4. 用于連接順序的提示
5. 用于連接操作的提示
6. 用于平行執行的提示
7. 其他提示
?
用于優化方法和目標(Optimization Approaches)的提示
以下提示讓你在優化方法和目標之間選擇:
1. ALL_ROWS
2. FIRST_ROWS(n)
如果一個SQL語句有一個提示來指定優化的方法和目標,那么優化器會使用指定的方法,而不管統計信息是否存在,或者OPTIMIZER_MODE初始化參數的值,或者ALTER SESSION語句的OPTIMIZER_MODE參數。
注意:優化器的目標只會應用在直接提交的查詢。使用提示為任何從PL/SQL中提交的SQL語句指定訪問路徑。ALTER SESSION ... SET OPTIMIZER_MODE語句不會影響到PL/SQL中運行的SQL語句。
如果你在SQL語句中指定ALL_ROWS或FIRST_ROWS(n)的其中一個提示,并且如果數據字段沒有語句要訪問的表的統計信息,那么優化器會使用默認值,例如那些表的分配存儲空間,來估計缺少的統計信息,然后選擇一個執行計劃。這些估計可能沒有用DBMS_STATS包收集的信息精確,所以你應該用DMBS_STATS包來收集統計信息。
如果你連同ALL_ROWS或FIRST_ROWS(n)一起來為訪問路徑或連接操作指定提示,那么優化器會優先選擇由提示指定的訪問路徑和連接操作。
?
用于訪問路徑(Access Paths)的提示
以下每種提示都指導優化器使用一種特定的訪問路徑來訪問表:
1. FULL
2. CLUSTER
3. HASH
4. INDEX
5. NO_INDEX
6. INDEX_ASC
7. INDEX_COMBINE
8. INDEX_JOIN
9. INDEX_DESC
10. INDEX_FFS
11. NO_INDEX_FFS
12. INDEX_SS
13. INDEX_SS_ASC
14. INDEX_SS_DESC
15. NO_INDEX_SS
指定這些提示中的一個會引起優化器特定的訪問路徑,但只有在這個訪問路徑基于索引或簇的存在且SQL語句中語法的正確時才可用。如果提示指定的是一個不可用的訪問路徑,那么優化器會忽略它。
你必須在語句中指定要訪問的表。如果語句中用了別名來引用表,那么在提示要用別名而不是表名。如果語句中有方案名,提示中的表名不要包含方案名。
注意:對于訪問路徑提示,如果你在SELECT語句中的FROM子句部分指定了SAMPLE選項,那么Oracle會忽略這個提示。
?
用于查詢轉換(Query Transformation)的提示
以下的提示各指導優化器使用一種特定的SQL查詢轉換:
1. NO_QUERY_TRANSFORMATION
2. USE_CONCAT
3. NO_EXPAND
4. REWRITE
5. NO_REWRITE
6. MERGE
7. NO_MERGE
8. STAR_TRANSFORMATION
9. NO_STAR_TRANSFORMATION
10. FACT
11. NO_FACT
12. UNNEST
13. NO_UNNEST
?
用于連接順序(Join Orders)的提示
以下提示為連接順序提供建議:
1. LEADING
2. ORDERED
?
用于連接操作(Join Operations)的提示
以下每個提示都可以指導優化器對表使用一種特定的連接操作:
1. USE_NL
2. NO_USE_NL
3. USE_NL_WITH_INDEX
4. USE_MERGE
5. NO_USE_MERGE
6. USE_HASH
7. NO_USE_HASH
推薦與任何連接順序提示(join order hint)一起使用USE_NL和USE_MERGE提示。當引用的表被強制為連接中的內部表時,Oracle使用這些提示;如果引用的表是外部表,那么這些提示會被忽略。
?
用于平行執行(Parallel Execution)的提示
當使用平行執行時,以下提示是指導優化器如何平行化或非平行化語句的。
1. PARALLEL
2. PQ_DISTRIBUTE
3. PARALLEL_INDEX
4. NO_PARALLEL_INDEX
?
其他提示(Additional Hints)
以下是一些其他提示:
1. APPEND
2. NOAPPEND
3. CACHE
4. NOCACHE
5. PUSH_PRED
6. NO_PUSH_PRED
7. PUSH_SUBQ
8. NO_PUSH_SUBQ
9. QB_NAME
10. CURSOR_SHARING_EXACT
11. DRIVING_SITE
12. DYNAMIC_SAMPLING
13. MODEL_MIN_ANALYSIS
?
指定提示(Specifying Hints)
提示只對它們出現在的語句塊的優化起作用。一個語句塊是指以下語句或語句的一部分:
1. 一個簡單的SELECT,UPDATE或DELETE語句
2. 一個父語句或一個復雜語句的子查詢
3. 一個組合查詢的一部分
例如,一個由兩個通過UNION操作符構成組件查詢(component queries)組成的組合查詢有兩個塊,每個都對應一個組件查詢。因此,在第一個組件查詢的提示只對它自己的優化起作用,而不會去優化第二個組件查詢。
?
指定提示的Full Set
當使用提示時,有些情況下,你需要指定提示的full set來確保最優執行計劃。例如,如果你有一個非常復雜的查詢,包含多個表連接,并且你只對其中一個給定的表指定了INDEX提示,那么優化器需要決定剩余的要使用的訪問路徑和相關的連接方法。因此,盡管你給定了INDEX提示,優化器可能不會使用該提示,因為由優化器選擇的連接方法和訪問路徑不會使用這個請求的索引。
在下面的例子中,LEADING提示指定了要被使用的確實連接順序;同時也指定了在不同表上使用的連接方法。
?
在提示中指定查詢塊(Query Block)
要識別一個查詢中的查詢塊,可以在提示中使用一個可選的查詢塊名來指定要對哪個查詢塊進行提示。查詢塊參數的語法是@queryblock的形式,這里的queryblock是在查詢中指定查詢塊的識別符。識別符queryblock可以是系統產生的,也可以是用戶指定的。
1. 用EXPLAIN PLAN來查看查詢可以得到系統產生的識別符。可以通過運行EXPLAIN PLAN來決定用NO_QUERY_TRANSFORMATION提示的查詢的預轉換查詢塊(pre-transformation query block)的名字。
2. 用戶指定的名字可以用QB_NAME提示來設置。
在下面的例子中,查詢塊名字被用來連同NO_UNNEST提示在視圖上的SELECT語句指定查詢塊。
在為查詢運行EXPLAIN PLAN并顯示計劃表(plan table)輸出后,你就可以看到系統產生的查詢塊識別符。例如,下面例子中顯示的輸出:
[java]?view plain?copy
? 知道查詢塊名稱后,就可以使用到下面的SQL語句中:
[java]?view plain?copy
?
指定全局表(Global Table)提示
通常指定表的提示一般是引用提示所在的DELETE,SELECT或UPDATE查詢塊中,而不是語句引用的視圖里的表。當你想要為一個出現在視圖內部的表指定提示時,Oracle推薦使用全局提示來代替嵌入提示到視圖中。在本章描述的表提示可以通過使用一個擴展的包含表名和視圖名的tablespec語法來轉換成全局提示。
除此之外,可以在tablespec語法之前設置一個可選的查詢塊名稱。
使用以下的語法來指定一個表的提示:
tablespec::=[view.]table
其中:
1. view指定了視圖的名稱
2. table指定了表名或表的別名
?
如果指定了視圖的路徑,提示是從左到右處理的,這樣第一個視圖必須在FROM子句中,然后每個后續的視圖必須在前一個視圖的FROM子句中。
例如,在下面的例子中,視圖v用來返回雇員的性和名,他的工作和他的下屬各個部門最高工資的雇員的工資總和。當查詢數據時,你想在視圖e2中對表e3強制使用索引emp_job_ix。
通過使用全局提示,你可以避免修改視圖v來在視圖e2中指定索引提示。要強制在表e3中使用索引emp_job_ix,可以用以下一種方法:
[java]?view plain?copy
全局提示語法也可以用在非融合視圖中,如下:
[java]?view plain?copy
這個提示導致v2不被融合,且指定了employees和departments表的訪問連接。這些提示都下推到(非融合的)視圖v2里。
?
指定復雜索引(Complex Index)提示
指定一個索引的提示可以使用單個索引名稱或用括號括起來的字段列表,如下:
indexspec::=index|([table.]column{1,})
其中:
1. table指定表名
2. column指定特定表的字段名
2.1 在字段前面可以可選地加上表限定詞作為前綴,這樣可以允許在索引字段不在索引表的情況下指定位圖連接索引。如果使用了表限定詞,那么必須使用全名,而不能用別名。
2.2 索引中的每個字讀必須是特定表的基礎字段,而不是表達式。基于函數的索引不能用于字讀特定提示,除非索引說明指定的字段形成基于函數的索引的前綴。
3. index指定索引名
?
這種提示是這樣處理的:
1. 如果指定了index名稱,那么只考慮索引。
2. 如果指定了字段列表,且這個列表與一個存在的索引在指定的字段和順序上吻合,那么只考慮這個索引。如果沒有那樣的索引存在,那么表上的任何含有指定字段作為前綴的索引都會被考慮。任何一種情況,都會像用戶在所有符合的索引上指定相同的提示。
例如,下面的例子中,job_history表有一個在employee_id字段上的單字段索引和一個連接了employee_id和start_date字段的索引。要特定地指導優化器使用索引,查詢要這樣提示:
?
與視圖一起使用提示
Oracle不建議在視圖(或子查詢)里面或本身上面使用提示。這是因為你可以在一個上下文中定義視圖,然后在另一個中使用它們。還有,那樣的提示可能導致不確定的執行計劃。特別地,在視圖內部或本身上的提示根據視圖是否可以跟頂層查詢融合來不同地處理。
如果你想在視圖或子查詢中為一個表指定提示,那么推薦使用全局提示語法。
雖然如此,如果你決定與視圖一起使用提示,那下面部分給出每種情況的描述。
?
提示與復雜視圖
默認地,提示不會擴展到一個復雜視圖的內部。例如,如果你在一個選擇復雜視圖的查詢中指定了提示,那么那個提示不會產生作用,因為它不能推到視圖的內部。
注意:如果視圖是一個單表,那么提示提示不會被擴展。
除非提示是在基視圖的內部,否則它們是不會在一個對于該視圖的查詢中起作用的。
?
提示和可融合的視圖
優化方法和目標(Optimation approach and goal)提示可以發生在頂層查詢或視圖內部。
1. 如果在頂層查詢中有那樣一個提示,那么提示會被使用而無視任何在視圖內部的那種提示。
2. 如果沒有頂層優化器模式提示,那么在引用視圖里的模式提示將和視圖中的索引模式提示一起使用。
3. 如果兩個或多個在引用視圖中的模式提示沖突的話,那么忽略所有在視圖里的模式提示,并且使用會話模式,不管是默認或者是用戶指定的。
?
在引用的視圖上的訪問路徑和連接提示會被忽略,除非視圖包含一個單表(或者應用的是一個和單表一起的其他提示的視圖)。對于那些單表視圖,訪問路徑提示或連接提示會應用到視圖內部的表中。
?
訪問路徑和連接提示可以出現在視圖的定義里。
1. 如果視圖是一個內聯視圖(即如果它出現在SELECT語句的FROM子句里),那么視圖內部的所有訪問路徑和連接提示在與頂層查詢融合時都會保留下來。
2. 對于不是內聯視圖來說,視圖內的訪問路徑和連接提示只有在引用的查詢不引用其他表或視圖(即如果SELECT語句的FROM子句只包含這個視圖)時才保留下來。
?
在視圖上的PARALLEL,NO_PARALLEL,PARALLEL_INDEX和NO_PARALLEL_INDEX提示會被遞歸地應用到引用視圖的索引表中。在頂層查詢的平行執行提示會覆蓋引用視圖內部的那些提示。
?
視圖內部的PARALLEL,NO_PARALLEL,PARALLEL_INDEX和NO_PARALLEL_INDEX提示在當視圖與頂層查詢融合時保留下來。在頂層查詢的平行執行提示會覆蓋引用視圖內部的那些提示。
?
提示和非融合視圖
對于非融合視圖,視圖內的優化方法和目標提示被忽略;頂層查詢決定優化模式。
因為非融合視圖是從頂層查詢中分開優化的,所以視圖內部的訪問路徑和連接提示會被保留下來。相同原因,頂層查詢里的視圖上的訪問路徑提示會被忽略。
盡管如此,頂層查詢里的視圖上的連接提示會被保留,因為那種情況下,非融合視圖類似一個表。
總結
以上是生活随笔為你收集整理的使用优化器提示(Optimizer Hints)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle常用的时间格式转换
- 下一篇: 销售抬头文本配置方法