1. 程式人生 > >基於Oracle的SQL優化--學習(十六)

基於Oracle的SQL優化--學習(十六)

連線謂語推入

   連線謂詞推入(JoinPredicatePushdown)是優化器處理帶檢視的目標SQL的另外一種優化手段,它是指雖然優化器還是會把該SQL中檢視的定義SQL語句當作一個獨立的處理單元來單獨執行,但此時優化器會把原本處於該檢視外部査詢中和該檢視之間的連線條件推入到該檢視的定義SQL語句內部,這樣做是為了能使用上該檢視內部相關基表上的索引,進而能走出基於索引的巢狀迴圈連線。和之前介紹的各種查詢轉換一樣,連線謂詞推入使優化器在選擇目標SQL的執行計劃時多出了走基於索引的巢狀迴圈連線這種選擇,這就增加了走出更高效執行計劃的可能性。
    但是請注意,連線謂詞推入所帶來的基於索引的巢狀迴圈連線並不一定能走出更高效的執行計劃,因為當做了連線謂詞推入後,原目標SQL中的檢視就和外部査詢產生了關聯,同時Oracle又必須將該檢視的定義SQL語句當作一個獨立的處理單元來單獨執行,這也就意味著對於外部查詢所在結果集中的每一條記錄,上述檢視的定義SQL語句都得單獨執行一次,這樣一旦外部査詢所在結果集的Cardinality比較大的話,即便在執行上述檢視的定義SQL語句時能用上索引,整個SQL的執行效率也不一定會比不做連線謂詞推入時的雜湊連線或排序合併連線髙。所以,Oracle在做連線謂詞推入時會考慮成本,只有當經過連線謂詞推入後走巢狀迴圈連線的等價改寫SQL的成本值小於原SQL的成本值時,Oracle才會對目標SQL做連線謂詞推入。
    Oracle是否能做連線謂詞推入與目標檢視的型別、該檢視與外部查詢之間的連線型別以及連線方法有關。到目前為止,Oracle僅僅支援對如下型別的檢視做連線謂詞推入。
    (1)檢視定義SQL語句中包含UNIONALL/UNION的檢視

    (2)檢視定義SQL語句中包含DISTINCT的檢視

    (3)檢視定義SQL語句中包含GROUP BY的檢視

    (4)和外部查詢之間的連線型別是外連線的檢視

    (5)和外部查詢之間的連線方法是反連線的檢視

    (6)和外部查詢之間的連線方法是半連線的檢視

連線因式分解

   連線因式分解(Join Factorization)是優化器處理帶UNIONALL的目標SQL的一種優化手段,它是指優化器在處理以UNIONALL連線的目標SQL的各個分支時,不再原封不動地分別重複執行每個分支,而是會把各個分支中公共的部分提出來作為一個萆獨的結果集,然後再和原UNIONALL中剩下的部分做表連線。連線因式分解在OraclellgR2中才被引入,它的好處是顯而易見的。如果不把UNIONALL中公共的部分提出來,則意味著這些公共部分中所包含的表會在UNIONALL的各個分支中被重複訪問;而連線因式分解則能夠在最大程度上避免這種重複訪問現象的產生,當UNIONALL的公共部分所包含的表的資料量很大時,即便是隻減少一次對大表的重複訪問,那也意味著執行效率上的巨大提升。 

    在Oracle11gR2及其後續的版本中,即使由於在檢視定義SQL語句中包含了集合運算子UNIONALL而導致Oracle不能對其做檢視合併,Oracle也不一定會把該檢視的定義SQL語句當作一個整體來單獨執行,因為此時Oracle還可能會對其做連線因式分解。這裡需要注意的是,Oracle對包含UNIONALL的目標SQL做連線因式分解的前提條件是,連線因式分解後的等價改寫SQL和原SQL在語義上完全等價,如果不能滿足這一點,那麼Oracle就不會做連線因式分解。

表擴充套件

   表擴充套件(TableExpansion)是優化器處理針對分割槽表的目標SQL的一種優化手段,它是指當目標SQL中分割槽表的某個區域性分割槽索引由於某種原因在某些分割槽上變得不可用(索引狀態為UNUSABLE)時,Oracle能將原目標SQL等價改寫成按分割槽UNIONALL的形式,這樣除了那些不可用的分割槽所對應的UNIONALL分支之外,其他分割槽所對應的UNIONALI:分支還是可以正常使用該區域性分割槽索引。

    我們都知道,當查詢的資料只是全部資料中的少部分時,使用索引確實能極大提高查詢的速度,但索引的維護必然會同時減慢相關DML操作的執行速度,所以使用索引是有副作用的。有的系統的業務特點就是要儘可能快地往目標表的當前分割槽中匯入資料,其修改的資料也僅限於該表中處於當前分割槽的活動資料,同時還會有針對目標表的査詢,這個査詢並不侷限於當前分割槽。針對這種型別的系統,為了儘可能快地對當前分割槽執行DML操作,往往人為地把當前分割槽的區域性分割槽索引的狀態設為UNUSABLE,這樣就省去了對當前分割槽執行DML操作時同步維護相關區域性分割槽索引的成本,所以這樣做是能夠提高相關DML操作的速度的。但現在的問題是,在OraclellgR2之前,這樣做會導致所有原本可以使用該區域性分割槽索引的査詢語句都無法正常使用該區域性分割槽索引。。