根據數據庫的SQL執行機制以及大量的實踐總結發現:通過一定的規則調整SQL語句,在保證結果正確的基礎上,能夠提高SQL執行效率。
- 使用union all代替union
union在合并兩個集合時會執行去重操作,而union all則直接將兩個結果集合并、不執行去重。執行去重會消耗大量的時間,因此,在一些實際應用場景中,如果通過業務邏輯已確認兩個集合不存在重疊,可用union all替代union以便提升性能。
- join列增加非空過濾條件
若join列上的NULL值較多,則可以加上is not null過濾條件,以實現數據的提前過濾,提高join效率。
- not in轉not exists
not in語句需要使用nestloop anti join來實現,而not exists則可以通過hash anti join來實現。在join列不存在null值的情況下,not exists和not in等價。因此在確保沒有null值時,可以通過將not in轉換為not exists,通過生成hash join來提升查詢效率。
如下所示,如果t2.d2字段中沒有null值(t2.d2字段在表定義中not null)查詢可以修改為
SELECT * FROM t1 WHERE NOT EXISTS (SELECT * FROM t2 WHERE t1.c1=t2.d2);
產生的計劃如下:
not exists執行計劃


- 選擇hashagg 。
查詢中GROUP BY語句如果生成了groupagg+sort的plan性能會比較差,可以通過加大work_mem的方法生成hashagg的plan,因為不用排序而提高性能。
- 嘗試將函數替換為case語句。
DWS函數調用性能較低,如果出現過多的函數調用導致性能下降很多,可以根據情況把可下推函數的函數改成CASE表達式。
- 避免對索引使用函數或表達式運算。
對索引使用函數或表達式運算會停止使用索引轉而執行全表掃描。
- 盡量避免在where 子句中使用!= 或<> 操作符、null值判斷、or連接、參數隱式轉換。
- 對復雜SQL語句進行拆分。
對于過于復雜并且不易通過以上方法調整性能的SQL可以考慮拆分的方法,把SQL中某一部分拆分成獨立的SQL并把執行結果存入臨時表,拆分常見的場景包括但不限于:
?作業中多個SQL有同樣的子查詢,并且子查詢數據量較大。
?Plan cost計算不準,導致子查詢hash bucket太小,比如實際數據1000W行,hash bucket只有1000。
?函數(如substr,to_number)導致大數據量子查詢選擇度計算不準。
?多DN環境下對大表做broadcast的子查詢。
其他更多調優點,請參考《開發指南》中的“典型SQL調優點”。