——SQL語句改寫
這星期沒干啥別的,把這本書粗粗?jǐn)]了一遍,數(shù)據(jù)庫基礎(chǔ)差,平時也就寫寫增刪改查,感覺看了一遍,概念知道了不少,但是感覺啥也沒學(xué)會,以后玄學(xué)寫sql的嘗試范圍可能變的更廣泛了??,慢慢來吧。
看了一遍,暫時簡單上手的大概就是第十章里的sql改寫,還有就是看看十一章里的例子圍觀一下。

在排除了CBO出現(xiàn)問題需要借助Hint的情況下,簡單的邏輯一般通過slq改寫來優(yōu)化基本夠用了。
一般性原則:
- 能用join的,不要用in和not in子查詢
- 能用in子查詢的,不要用exists相關(guān)查詢
- 能用not exists相關(guān)子查詢的,不要用not in子查詢
(所有場景都是以sql存在性能問題為前提)
1. 消除查詢中的視圖(view):
場景:
- from中連接數(shù)據(jù)對象比較多
- 視圖子查詢from中連接數(shù)據(jù)對象比較多
- 視圖嵌套層次比較多
2. 標(biāo)量子查詢改為外連接:
標(biāo)量子查詢這個詞看的我一臉蒙蔽:Oracle允許在select子句中包含單行子查詢,這個也就是oracle的標(biāo)量子查詢,標(biāo)量子查詢有點(diǎn)類似于外連接,當(dāng)使用到外連接時我們可以靈活的將其轉(zhuǎn)化為標(biāo)量子查詢。
好吧,就是select 里加了個查詢
注意:
- 原標(biāo)量子查詢下沉為內(nèi)嵌視圖時,需要和原主查詢表進(jìn)行outer join
- 存在多個標(biāo)量子查詢時,分別改為相應(yīng)內(nèi)嵌視圖并下沉,同時分別和主查詢表進(jìn)行outer join
3. update改為merge into
傳說中大數(shù)據(jù)環(huán)境下的利劍
merge into,沒接觸過。
說明:MERGE語句是Oracle9i新增的語法,用來合并UPDATE和INSERT語句。
通過MERGE語句,根據(jù)一張表或子查詢的連接條件對另外一張表進(jìn)行查詢,
連接條件匹配上的進(jìn)行UPDATE,無法匹配的執(zhí)行INSERT。
這個語法僅需要一次全表掃描就完成了全部工作,執(zhí)行效率要高于INSERT+UPDATE
場景:
- update語句中存在相關(guān)子查詢
4. 正確使用分析函數(shù)
利用分析函數(shù)來改寫匯聚相關(guān)的sql語句
場景:
- 原sql語句執(zhí)行計劃中存在對同一數(shù)據(jù)對象的多次掃描
5. with as 去除多次掃描
with as 語句可以動態(tài)地創(chuàng)建一個臨時表,用以存儲中間數(shù)據(jù)
注意:
- 改寫為with as 語句時,注意要抽取所有相關(guān)的子查詢的最大集合(超集),并合理消除所有或部分相關(guān)的子查詢
- 改寫時如果存在多個臨時表,那么后面的臨時表應(yīng)盡量利用前面的臨時表
場景:
- sql中子查詢導(dǎo)致執(zhí)行計劃中對某個或某些數(shù)據(jù)對象的多次掃描,且子查詢結(jié)果集足夠小
- 原sql中子查詢在執(zhí)行計劃中已展開
6. union 改為 or
場景:
- sql中子查詢在執(zhí)行計劃中已展開
- sql中子查詢導(dǎo)致執(zhí)行計劃中對相關(guān)對象掃描次數(shù)過多
- sql中子查詢在執(zhí)行計劃中對相關(guān)索引的使用情況不理想
7. or 改為 union
場景:
- sql中子查詢在執(zhí)行計劃中未展開
- sql中子查詢在執(zhí)行計劃中對相關(guān)索引的使用情況不理想
8. in 改為 join
注意:
- in改為join后,需要將結(jié)果集去重(distinct)
場景:
- sql中子查詢在執(zhí)行計劃中未展開
9.in 改為exists
注意:
- in改為exists時,注意相關(guān)子查詢的where條件和select-list
場景:
- sql中子查詢在執(zhí)行計劃中未展開
- sql中子查詢在執(zhí)行計劃中已展開,且主查詢及子查詢相關(guān)表間連接效果不理想
10. not in 改為 not exists
注意:
- 注意相關(guān)子查詢的where條件和select-list
場景:
- sql中子查詢在執(zhí)行計劃中未展開
- sql中子查詢在執(zhí)行計劃中已展開,且主查詢及子查詢相關(guān)表間連接效果不理想
11. not exists 改為 not in
場景:
- sql中子查詢在執(zhí)行計劃中未展開
- sql中子查詢在執(zhí)行計劃中已展開
12. exists 改為 join
注意:
- exists改寫為join的過程中,注意sql語句中where的合并
場景:
- sql中子查詢在執(zhí)行計劃中未展開
- sql中子查詢在執(zhí)行計劃中已展開,且主查詢及子查詢相關(guān)表間連接效果不理想
13. not exists 改為 join
場景:
- sql中子查詢在執(zhí)行計劃中未展開
- sql中子查詢在執(zhí)行計劃中已展開,且主查詢及子查詢相關(guān)表間連接效果不理想
14. join 改為 exists
注意:
- 注意sql中where條件的分解
場景:
- sql語句執(zhí)行計劃中相關(guān)表間連接效果欠佳
15. join 改為 not exists
注意:
- 注意sql中where條件的分解
場景:
- sql語句執(zhí)行計劃中相關(guān)表間連接效果欠佳
16. 改寫為集合運(yùn)算符
集合運(yùn)算符,主要包括:
union,minus,intersect等,用來完成數(shù)據(jù)集間的操作
注意:
- sql語句where條件,乃至整個語句的分解
場景:
- 原sql語句執(zhí)行計劃中相關(guān)索引使用情況不理想