最近,下面的一個項目遇到緊急問題,我這匹老馬也要和年輕人一起奮斗一下。問題是當把一倍壓力 數據灌入數據庫,很多查詢都奇慢無比。
說道這裡必須要說一下性能問題的基本准則。性能問題 Tunning的次序
1)架構設計(軟件架構和數據庫設計,糟糕的設計幾乎是致命的)
2)代碼缺 陷(導致性能問題的90%)
3)增加索引(這個是要根據實際情況來確定)
4)資源調優(CPU- >內存->Disk IO)
這裡網絡不是考慮因素。
把程序的SQL文拿出來一看,有的一看一 堆子查詢構成的JOIN,基本上一眼就可以斷定,需要重寫。我們這個運用系統把SQL文都配置成動態的, 這個設計給現在的調優帶來了方便。
突然出現了一個很有趣的現象。有一個查詢很慢(一分鐘才 出來),檢查SQL文。這句SQL文是這樣
SELECT ISNULL(a.CWB_NO,b.CWB_NO) AS CWB_NO,a.IMPORT_AWB_NO,
a.IMPORT_BWB_NO,ISNULL(a.PCS,0) AS RS2PCS,ISNULL(b.PCS,0) AS DECPCS,a.CCC_STATUS
FROM
(SELECT * FROM TB_CWB WHERE IMPORT_AWB_NO = @IMPORT_AWB_NO) a
FULL JOIN
(SELECT * FROM TP_DECSUMMARY WHERE AWB_NO = @IMPORT_AWB_NO) b
ON a.CWB_NO = b.CWB_NO AND b.AVAILABLE = 'Y'
WHERE a.AVAILABLE = 'Y'
FULL JOIN不是問題核心(因為業務規則就是這樣),也不是 SELECT *,其實SELECT *和指定字段或許有差異,但是絕對不會有很大差別。
我在後台運行了一 下,0秒都不到。但是另外一個程序員說同樣運行要59秒。奇怪!!!
拿過來對比一下,就發現差 異了。
因為,我們的系統采取的是用.NET中cmd指定參數的寫法,轉換成後台sql文,等於運行 sp_executesql的方法。更簡單說就是替換變量。
即等價的SQL文應該是
SELECT ISNULL(a.CWB_NO,b.CWB_NO) AS CWB_NO,a.IMPORT_AWB_NO,
a.IMPORT_BWB_NO,ISNULL(a.PCS,0) AS RS2PCS,ISNULL(b.PCS,0) AS DECPCS,a.CCC_STATUS
FROM
(SELECT * FROM TB_CWB WHERE IMPORT_AWB_NO = '25200000011') a
FULL JOIN
(SELECT * FROM TP_DECSUMMARY WHERE AWB_NO ='25200000011') b
ON a.CWB_NO = b.CWB_NO AND b.AVAILABLE = 'Y'
WHERE a.AVAILABLE = 'Y'