Cost-based query transformation in Oracle算法
Enhanced Subquery Optimizations in Oracleapp
本文介紹Oracle的查詢優化框架,框架
先描述,Oracal分別在RBO和CBO作了哪些事情,爲何要這樣作函數
先看下RBO的部分,RBO部分的Rule基本都是肯定能夠帶來優化的oop
Subquery Unnesting性能
子查詢消除,子查詢若是用apply的方式的話,文中稱TIS,Tuple iteration semantics,基本等同於nested loop方式,比較低效優化
消除的方法分紅兩大類,ui
1. 把子查詢 merge 到外部查詢裏面去spa
以下面的例子,把exists變成semi-join3d
2. 產生inline views,或derived table的方式,這種方式會放到CBO裏面,因此後面給出例子
Join Elimination
消除無用的Join
其中Q4,dept_id是foreign key,因此每一個employee都必須有一個dept,這裏join起不到filter的做用
Filter Predict Move Around
Filter下推,儘早的過濾數據,前提是這裏的Filter是inexpensive的
Group Pruning
刪掉在外層查詢中不須要的group
下面的例子,在外層查詢中,過濾city,那麼city其實就決定了state,country,子查詢中的group by 就沒有必要了
這裏講到重點,看下哪些Transformation應該在CBO裏面去作的
Subquery Unnesting
第一個仍然是子查詢消除,前面說了,若是是產生inline view的方式,須要用CBO
下面的例子,從Q1到Q10,產生了inline view或派生表 V
這裏產生inline view的方式不必定會比nested loop的方式更好,若是filter出的row不多,而索引建的很好,極可能nested loop的方式更優
因此這種不肯定的狀況下,須要CBO來判斷
Group-by and Distinct View Merging
右稱爲,Groupby Pull-up,若是join會大幅下降數據量,那麼把groupby上提是覈算的,由於groupby通常都是聚合,比較expensive的操做
好比下面Q11的例子,
把計算平均salary的inline view,挪到了外部查詢的group by
能夠看到把group by移到外面後,group by的field須要加上join key
Group-by Placement
對應於上面說的Pull Up,這裏是Push Down
Join Predicate Pushdown
把外部查詢的join predicate下推到子查詢中,
通常套路都是uncorrelation,這裏反之,不是全部狀況均可以這樣下推
例子,
Join Factorization
將公共的 join tables 上提
Predicate Pullup
將Expensive的Predicate進行上提,
Set Operator Into Join
Disjunction Into Union All
State Space Search Tech
CBO有個關鍵的問題是,若是Transformation持續變多,那麼搜索空間是成指數級別上升的
針對這樣的問題,比較可行的方式是引入隨機算法,
Oracle的搜索算法以下,
Exhaustive,窮盡法
Iterative,局部最優,每次選擇不一樣的初始點,有點像退火
Linear,動態迴歸
Two-pass,強行下降搜索空間
而後這裏比較有借鑑意義,針對不一樣的search規模,咱們應該選用不一樣的搜索算法
Transformation執行的方式
Oracle中按照順序的方式去執行Transformations,
這裏給出各個分類的執行順序
固然有些狀況下光順序執行是不夠的,
3.3裏面提到了,
Interleaving方式,有些rule須要交叉的執行
舉得例子是,Unnesting和View merging
Juxtaposition的方式,
本文討論Oracle對於子查詢的優化方法
子查詢合併,把多個子查詢合併成一個
這裏提出,Container和Contained的概念
直觀上,若是A contain B
A and B,就能夠remove A
A or B,就能夠removeB
Coalescing Subqueries of The Same Type
SameType,類型同樣,要不都是Exist,要不都是Not Exist
和上面說的一致,只是這裏加上Exist和Not Exist,有點繞
總之conjunction留小的,contained,disjunctive留大的,container
對於不知足Containment Property的子查詢,仍然可能進行coalescing,
只要他們除了filter和predicates之外是equivalent的
這個很直觀,由於若是隻是Predicate不同,是能夠合併的
例子,雖然沒有containment關係,可是僅僅只有predict不同
能夠看到,能夠直接把Exists間的OR,轉化爲predict之間的OR,很直覺
Coalescing Subqueries of Different Type
不一樣的Type,Exist和Not Exist之間的
能夠看TPC-H的Q21,
兩個子查詢是知足Containment關係的,可是類型不同
這裏的感受就要從Container中挖去Contained的那塊
是這樣轉換的,
用Having,對知足條件的case求sum,而後過濾,好tricky
Coalescing and Other Transformations
Q5加上外層的Join就是Q6
這裏作的轉換是,View merging,就是Groupby Pullup
可是GroupBy的Pull up仍是Push down,須要經過cost-based來決定
Oracle有窗口函數,能夠用於替換子查詢,論文裏說,對於TCP-H,性能會有10倍提高
這裏有subsume的概念,outer query包含子查詢中的全部tables和predicates
這個例子,知足Subsume關係,在子查詢中主要爲了作AGG
因此這裏用窗口函數就能夠簡單的remove掉子查詢
Correlated Subsumed Subquery
相關子查詢,在TCP-H中的表明是Q2,Q17
Q2,子查詢中主要爲了求min
用窗口函數,改造後
對於Q17,微軟提出的是SegmentApply的方案,這裏用窗口函數改造後,
底下關於Duplicate rows,沒太懂
說是窗口函數必須within a view,沒看出和上面的區別
Uncorrelated Subsumed Subquery
非相關子查詢,TCP-H,Q15
用窗口函數轉化爲,由於是非相關子查詢,因此OVER裏面是空的,不須要PBY