SQL Server性能調優雜記(一)----傻瓜機的失效效應

      最近,下面的一個項目遇到緊急問題,我這匹老馬也要和年輕人一起奮鬥一下。問題是當把一倍壓力數據灌入數據庫,很多查詢都奇慢無比。

      說道這裏必須要說一下性能問題的基本準則。性能問題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'

 

而我調試用的替換SQL文

DECLARE @IMPORT_AWB_NO VARCHAR(20)
SET @IMPORT_AWB_NO='25200000011'

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'

            這個即相當於SP的寫法。

            這2句的結果導致就是執行計劃完全不一樣。從而產生天壤之別的效果。這個問題和SQL文的好壞沒有關係。我對比了者2個執行計劃,個人認爲由於SQL Server的CBO分析這個“傻瓜機”失效效應導致。

           我們先看一下2種的執行計劃的區別。我用第2種(即SP)方法的執行計劃。

          

    2個執行計劃的唯一差別就是圖中的2個Paralism(數據庫服務器是8個CPU)。即我的那句SQL採用了並行裝載數據的方法。而第一中沒有使用並行裝載。原因很簡單,因爲執行計劃分析器認爲前面這句SQL執行代價很小,而我的執行代價很高。因此進行了區別對待,前者不需要動用硬件資源,後者則需要動用硬件資源。這就是失效效應。而一般認爲慢就是因爲硬件不夠,在這裏充分體現是無稽之談。至少性能問題只有5%甚至更低的情況才和硬件有關。

   至於這個代價估算的計算方法,只有查具體的技術文件,大體應該和數據大小,索引大小,邏輯讀寫,物理讀寫,CPU資源有關。因爲是估算,因此有偏差很正常。

   那麼解決這個問題,加索引纔是正途。這就是我前面講到的原則。通過加索引,執行計劃發生了變化。見下圖。

 

 

    增加索引後的速度結果飛快。

   Paralism和索引的概念就好比,在南京路上找某戶戶主是王五,Paralism是出動16個警察,而索引就好比一個警察拿戶籍登記冊找。一個是擁有資源多而致勝,一個是工作方法好而致勝。

    從這裏可以看出,性能調優起始是一個根據實際情況進行平衡選擇的過程,武斷認爲就是加索引,提升硬件都說明你不了原理。對了也只是運氣好。

    總結這個例子,失效效應就是CBO帶來的一個有趣的現象。顯然CBO要用,但是要去學習明白它的原理和特點。就好比傻瓜照相機還是用的人多,但是你要懂得傻瓜機也有判斷失誤的時候,所以要用“白加黑減”的曝光補償。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章