Oracle 查詢轉換初探
概述
Oracle查詢轉換器的作用是把原始sql重寫為語義相同的語句,目的是為了獲得更高效的sql。
查詢轉換主要有四種技術:子查詢展開,檢視合併,謂詞推入,星型轉換。
瞭解查詢轉換是掌握SQL最佳化的基礎,本文將對這四種技術做一些簡單的介紹。
子查詢展開
子查詢展開是指最佳化器不再把子查詢作為獨立的單元處理,而是轉換成等價的join方式。轉換有兩種方式:一是將子查詢的結果集作為檢視,與外層表或檢視做join;二是將子查詢中的表或檢視拆出來,與外層表或檢視做join。子查詢前包含以下條件可以被展開:
· any(= any和in等價)
· all(<> all和not in等價)
· exists
· not exists
single row條件(where後面接=,<,>,<=,>=等條件)子查詢展開的例子:
最終轉換的語句:
可以看到子查詢中的dept表被拆出來,與外部查詢塊的emp表做inner join。可以這樣轉換的前提是dept表的deptno列是唯一鍵。如果deptno列不是唯一鍵,將做semi
join(即所謂的半連線):
如果不做子查詢展開,就會走filter型別的執行計劃,並且子查詢放在最後一步執行,作用是對emp全表掃描之後的結果集進行過濾:
看一個子查詢結果集作為內聯檢視與外層查詢塊做join的例子:
執行計劃仍然走了hash join semi,要使得轉換是等價的,必須先完成子查詢中departments和locations的join,結果集作為內聯檢視VM_NSO_1,與外層查詢塊的結果集做join。
下面的執行計劃中,子查詢的結果被作為nest
loop的驅動表,為保證結果集正確,需要對子查詢做hash unique去重。
如果滿足(不限於)下面的條件,子查詢展開可能導致轉換不等價,因此將不作展開:
· where後面的連線符為=all或者<> any
· exists後面的子查詢中帶有rownum
· exists後面的子查詢中帶有having子句,cube子句或者rollup子句
例如下面的例子:
檢視合併
檢視合併是指對包含檢視的查詢做出轉換,使查詢只包含基表。檢視合併提供了更多的訪問路徑和join的可能性。也就是說,不做檢視合併的執行計劃包含在做了檢視合併的執行計劃中。下面的例子可以幫助理解這句話:
如果不做檢視合併,執行計劃如下:
可以看到不對emp100做檢視合併,執行計劃中出現view字樣,name列對應的就是檢視名emp100。
第二個執行計劃除了多了view的一行,訪問路徑和成本是和第一個相同的。
如果檢視定義中包含下列內容,將不能做檢視合併:
· 集合運算子(UNION,UNION ALL,INTERSECT,MINUS)
· connect by子句
·
rownum偽列
做這些限制是為了防止檢視合併之後得到錯誤的結果集。
不能檢視合併的例子:
複雜檢視合併
複雜檢視合併技術允許對包含gourp by或者distinct的檢視做展開。
_COMPLEX_VIEW_MERGING引數控制是否啟用複雜檢視合併,在9i之後預設為true,同時受OPTIMIZER_FEATURES_ENABLE引數控制:
外連線檢視合併
使用了外連線的sql中,檢視合併需要滿足下列條件之一:
· 檢視為外連線的驅動表
·
檢視的定義只包含單表
下例中檢視v1包含兩張基表,在做外連線的驅動表時發生檢視合併,做被驅動表則沒有。
謂詞推入
最佳化器在處理不能合併的檢視時,可以選擇將外部查詢的謂詞推入該檢視的查詢塊,或者將檢視中的謂詞拉出到主查詢。這樣更早的處理檢視的結果集,有可能會減小後續步驟操作所需的成本。
謂詞推入到檢視內部的例子:
注意到執行計劃中條件EMPLOYEE_ID<205被推入到檢視內部,將兩張基表各過濾一次,然後對結果集做union。
兩表關聯時,連線條件也可以做推入,先來看不做謂詞推入的執行計劃:
執行計劃中emp13作為驅動表與departments表做nest loop,我們使用hint強制發生謂詞推入:
可以看到執行計劃中出現PUSHED PREDICATE字樣,條件e.department_id=d.department_id被轉換成等值條件對employees表做過濾。join的謂詞推入往往產生nest loop的執行計劃(驅動表的每一行驅動被驅動表,來做謂詞的過濾)。如果是大資料集的sql,可以使用hint no_push_pred或者設定引數_push_join_predicate為false禁止謂詞推入。
星型轉換
星型轉換為提高星型查詢的效率發生,在原有條件基礎上會產生新的子查詢對事實表做過濾,然後透過對事實表相應連線列的點陣圖索引做點陣圖操作,達到過濾事實表結果集的目的。
是否開啟星型轉換受引數star_transformation_enabled控制,可以設定為:
true:最佳化器將考慮基於成本的星型查詢轉換;
false:禁止星型轉換;
temp_disable:最佳化器將考慮基於成本的星型查詢轉換,但是轉換中不會使用臨時表。
首先看一下星型轉換的例子:
注意到執行計劃首先對各個維度表過濾出結果集,然後訪問sales表連線列上的索引,做bitmap and操作之後,回表訪問資料。事實上整個過程類似於將查詢轉換為如下等價sql:
下面看一下star_transformation_enabled引數設定為true的結果:
注意到執行計劃中先對customers根據過濾條件cu.country_id
=52789得到臨時表SYS_TEMP_0FD9D6601_11F1D1,後續步驟中每次需要訪問customers表時則由臨時表來替換,這也是為了總共減少所訪問的資料量所考慮。
星型轉換同樣有一些限制條件,本文暫不討論。
以上是對四類查詢轉換概念性的描述,對於具體的應用場景中的SQL要具體分析如何利用這些技術。查詢轉換還有諸如子查詢合併,連線因式分解,表擴充套件,表裁剪,物化檢視重寫等技術。有機會將再寫文章介紹,或者有興趣的同學自行研究。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28218939/viewspace-2051271/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Oracle 查詢轉換Oracle
- Oracle 查詢轉換-01 or expansionOracle
- Oracle查詢轉換(五)子查詢展開Oracle
- 【SQL】Oracle查詢轉換之 OR用法SQLOracle
- 查詢轉換
- Oracle 12CR2查詢轉換之星型轉換Oracle
- Oracle 查詢轉換-04 Subquery UnnestingOracle
- 【SQL】Oracle查詢轉換之物化檢視查詢重寫SQLOracle
- Oracle XQuery查詢、構建和轉換XML(1)(轉)OracleXML
- Oracle 查詢轉換-02 View MergingOracleView
- Oracle 查詢轉換-03 Predicate PushingOracle
- 【SQL】Oracle查詢轉換之謂詞推送SQLOracle
- 使用 Oracle XQuery 查詢、構建和轉換 XMLOracleXML
- Oracle 12CR2查詢轉換之臨時錶轉換Oracle
- 【SQL】Oracle查詢轉換之檢視合併SQLOracle
- Oracle查詢轉換(四)連線謂詞推入Oracle
- 怎樣把Oracle查詢轉換為SQL ServerOracleSQLServer
- 記一次詭異的Oracle查詢轉換Oracle
- Oracle查詢轉換(一)簡單檢視合併Oracle
- Oracle查詢轉換(二)複雜檢視合併Oracle
- Mysql 查詢時間轉換MySql
- SQL Story摘錄(一)————簡單查詢初探 (轉)SQL
- Oracle 12CR2查詢轉換之謂詞推送Oracle
- Oracle查詢轉換(三)外連線檢視合併Oracle
- GP詭異的查詢轉換
- Oracle 12CR2查詢轉換之檢視合併Oracle
- Oracle 12CR2查詢轉換之表擴充套件Oracle套件
- 一條SQL語句查詢塊分解及查詢轉換SQL
- Java初探Oracle(轉)JavaOracle
- (轉)SQL查詢案例:多行轉換為一行SQL
- D4.玩轉查詢與替換
- Oracle 12CR2查詢轉換之cursor-duration臨時表Oracle
- oracle常用經典SQL查詢 (轉)OracleSQL
- 【八】查詢變換
- vim查詢替換
- Oracle 查詢Oracle
- CBO的查詢轉換(謂詞推入與子查詢展開(Subquery Unnesting))
- 關於查詢轉換的一些總結