【DB2】SQL優化


溫馨提醒:

TMP_007數據量為:409373

1.去除在謂詞列上編寫的任何標量函數

優化前:(耗時3.1s)

SELECT START_DATE,CST_NM FROM TMP_007 WHERE YEAR(TO_DATE(START_DATE,'YYYYMMDD'))='2009'

優化后:(耗時0.922s)

SELECT START_DATE,CST_NM FROM TMP_007 WHERE START_DATE BETWEEN '20090101' AND '20091231'

總結:

DB2可以選擇使用START_DATE上的列索引,但是在列上使用了函數后,DB2就無法使用列索引了,從而導致查詢效率變低。


2.去除在謂詞列上編寫的任何數學運算

優化前:(耗時10.265)

SELECT ACCT_ID,CST_ID,CONTRACT_AMT FROM TMP_007 WHERE CONTRACT_AMT*0.1 > 10000

優化后:(耗時3.39s)

SELECT ACCT_ID,CST_ID,CONTRACT_AMT  FROM TMP_007 WHERE CONTRACT_AMT > 10000/0.1

總結:

DB2查詢時候,會優先選擇列CONTRACT_AMT上的索引,如果直接對列CONTRACT_AMT應用數學運算,DB2就無法使用索引了。一定要做到:列本身(不加數學運算)放在操作符的一邊,而所有的計算都放在另外一邊。



3.SQL語句中指定查詢列

優化前:(耗時13.15s)

SELECT * FROM TMP_007

優化后:(耗時2.922s)

SELECT ACCT_ID,CST_ID,CONTRACT_AMT FROM TMP_007

總結:

如果Select包含不需要的列,優化工具會選擇Indexonly=’N’,這會強制DB2必須進入數據頁來得到所請求的特定列,這就要求更多的I/O操作,梁歪,這些多余的列可能是某些排序的部分,這樣一來就需要和傳遞一個更大的排序文件,相應的會使排序成本更高。



4.盡可能不使用distinct

優化前:(耗時0.687s)

SELECT DISTINCT CST_ID FROM TMP_007 ;

優化后:(耗時0.437s)

SELECT CST_ID FROM TMP_007 GROUP BY CST_ID;

總結:

在測試distinct與group by性能的過程中,在列CST_ID上添加索引后,發現group by 確實比distinct快一些,但是在數據分布比較離散的情況下使用group by ,比較集中的情況下使用distinct.表數據量較少的情況隨便使用哪個都一樣,不管選擇誰,都要建立索引


5.Exists、in、not in 、not exists的使用場景選擇

5.1 in跟exists的區別:

例如:表A(小表),表B(大表)                                                                                    

優化前:(耗時1.93s)

select * from A where cc in(select cc from B)  -->效率低,用到了A表上cc列的索引;

優化后:(耗時1.125s)

select * from A where exists(select cc from B where cc=A.cc)  -->效率高,用到了B表上cc列的索引。

相反的,                                                                                 

優化前:(耗時1.9s)

select * from B where cc in(select cc from A)  -->效率高,用到了B表上cc列的索引

優化后:(耗時1.0s)

select * from B where exists(select cc from A where cc=B.cc)  -->效率低,用到了A表上cc列的索引。

總結:

in是把外表和內表作hash連接,而exists是對外表作loop循環,每次loop循環再對內表進行查詢,一直以來認為exists比in效率高的說法是不准確的。如果查詢的兩個表大小相當,那么用in和exists差別不大;如果兩個表中一個較小一個較大,則子查詢表大的用exists,子查詢表小的用in;

簡稱:子大Exists,子小in

5.2 not in 與 not exists區別:

如果查詢語句使用了not in,那么對內外表都進行全表掃描,沒有用到索引;而not exists的子查詢依然能用到表上的索引。所以無論哪個表大,用not exists都比not in 要快。


6.盡可能使用union all來代替union

優化前:(耗時15.344s)

SELECT ACCT_ID,CST_NAME FROM TMP_007 UNION SELECT ACCT_ID,CUST_NM FROM TMP_008

優化后:(耗時2.719s)

SELECT ACCT_ID,CST_NAME FROM TMP_007 UNION ALL SELECT ACCT_ID,CUST_NM FROM TMP_008

總結:

在union中,DB2最后會自動執行一個排序來消除重復值,這樣是很耗費資源的,所以在不需要去重復的情況下,盡可能使用UNION ALL 代替union


N.模板

優化前:(耗時3.1s)


優化后:(耗時0.922s)


總結:





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM