SQL优化之列裁剪和投影消除
列裁剪
對于沒用到的列,則沒有必要讀取它們的數據去浪費無謂的IO
比如我們有一張表table1,它含有四列數據(a,b,c,d)。當我們執行查詢select a from table1 where c 10時,我們可以清晰的看到,table1中只有a,c兩列被用到了。分別是Selection算子用到c列和Projection算子用到a列。那么DataSource讀取數據時,b,d兩列則不需要讀取,可以裁剪掉。
那么都有哪些算子與列有關系呢?綜合我們多年來使用SQL的經驗來看,Selection(Where 條件)、Projection(搜索的列)、Sort(排序列)、Join(等值連接)、Aggregation(Group By及相關聚合操作)等。
列裁剪的算法就是自頂向下的把算子過一遍,某個節點需要用到的列就等于它自己需要用到的列加上它的父節點所需要用到的列。這樣得到整個SQL語句所涉及到的列,從而再讀取數據時只讀取需要的列即可。
列裁剪通過只讀取需要的數據減少IO操作來達到優化的目的
投影消除
投影消除是把不必要的Projection給消除掉
那么問題來了,什么情況下,投影算子是可以被消除的呢?
如何Projection算子需要投影的列跟子節點的輸出列一樣,那么這個投影就是一個廢操作,可以被消除掉。比如說:select a,b from table1 如果再表table1中剛好只有a,b兩列,也就是DataSource的輸出和Projection需要投影的列一樣,那么這時候就沒必要在TableScan之后再做一次Projection操作了。
如果Projection的子節點還是Projection的話,那么子節點的Projection就沒有意義了,可以干掉。如:select a from (select a,b,c from table2) 這條語句里面有兩個Projection,分別是最上層的Projection(a)和它的子節點Projection(a,b,c)。那么Projection(a,b,c)這個節點就是廢操作,可以被消除掉。
Aggregation在某種意義上也屬于投影操作,因為從這個節點出來的都是列的概念,比如Max(a)、Min(b)等。因此在Aggregation-Projection的過程中,這個Projection也是可以被消除掉的。
所以說,一個節點是否可以被消除,一方面是由它的父節點告訴它,它是否是一個冗余的Projection操作。另一方面是它自己和孩子節點做比較,看自身是否可以被消除。
public void eliminate(Plan plan, boolean canEliminate) {
//如果plan為Projection則判斷是否需要被消除
if (plan is Projection) {
//如果父節點調用時指定canEliminate為true,則進行消除操作
if (canEliminate) {
doEliminate(plan);
}
//如果plan的輸出和子節點的輸出一樣則消除plan
if (checkPlanOutEqualsNext(plan)) {
doEliminate(plan);
}
}
//遞歸調用,遍歷子節點
eliminate(plan.next(), checkPlanNextCanEliminate(plan));
}
最大最小消除
最大最小消除嚴格上說不是標準邏輯優化里面需要做的事情
舉個栗子:
語句1select min(a) from table1可以轉換為語句2select a from table1 order by a desc limit 1
語句1生成的邏輯執行計劃是一個 TableScan 上面接一個 Aggregation,也就是說這是一個全表掃描的操作。
語句2生成的邏輯執行計劃是TableScan + Sort + Limit,在某些情況,比如a是主鍵或者是存在索引,數據本身是有序的, Sort 就可以消除,最終變成 TableScan 或者 IndexLookUp 加 Limit,這樣子就不需要全表掃了,讀到第一條數據就得到結果!全表掃跟只查一條數據,查詢速度可是天壤之別。也許這一點點寫法上的區別,就是幾分鐘甚至更長,跟毫秒級響應的差距。
最大最小消除就是SQL優化器自動把上面的操作實現了。比如說:
select max(id) from table1 生成的查詢計劃會變成下面這種(最大消除):
select max(id) from (select id from table1 order by id desc limit 1 where id is not null) t
select min(id) from table1生成的查詢計劃會變成下面這種(最小消除):
select min(id) from (select id from table1 order by id limit 1 where id is not null) t
然后轉換后的語句再經過其他的轉換規則最終得到最后的查詢計劃。
?
轉載于:https://juejin.im/post/5c6cfa926fb9a049ac79be11
總結
以上是生活随笔為你收集整理的SQL优化之列裁剪和投影消除的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Kanboard简单的可视化任务板,项目
- 下一篇: 持续集成之理论篇