SQL Server性能调优入门(图文版)
?
第一步,在業務高峰期抓取樣本數據(2個小時左右)。采用的工具是sqlserver自帶的profiler,也叫事件探查器,如下圖:
進入后,點擊最左面的按鈕,建立一個新的跟蹤:
登錄需要用DBO權限,所以可以用sa登錄,也可以用windows集成驗證方式(如果當前登錄的就是sqlserver的話)
新建跟蹤,一共有4個tab頁進行配置,首先看第一個。跟蹤名稱不用更改,默認的即可。保存一共有兩種方式,一是文件,擴展名是.trc(這種方式方便你把客戶那里的跟蹤結果發給你),其二是數據庫中的表。
為了分析方便,我們把它另存為表。此時sql提示你重新進行登錄,這里我們把表保存到master中
假設表名字叫做jq(如果有重復的,系統會提示是否覆蓋)
確定后回到了剛才的第一個tab頁中:
然后切換到第二個選項卡中:
左面列出了各種事件類(Event Class),右面是當前已有的事件類。對于性能調優,我們不需要安全審核、會話信息,點擊刪除按鈕即可:
繼續切換到第三個tab頁上,這里的數據列默認就夠了,當然,如果你看著不順眼,可以把Appname/NT username等都刪除。
最后一個tab頁上,我們需要把系統自己產生的事件ID屏蔽掉:
把那個排除系統ID進行check即可,如下圖:
所有項目配置好后,點擊“運行”按鈕。持續運行兩個小時左右即可(業務高峰期,能典型的反應客戶最近一段時間內的業務模式)
好了,第一步的準備工作完成了,等待一段時間后,我們開始檢查剛才自動保存到master中的表jq。
第二步,開始查找影響速度的地方。
打開查詢分析器(sql analyzer),登錄到master中,從 表jq里面按照I/O倒序,讀取若干個sql。根據我的習慣,一般是讀取1000條記錄。為什么根據I/O來找呢,而不是根據時間來找呢?原因很簡單,一句SQL執行,“穩定”的是I/O,而duration是一個不穩定的因素。我們進行sql調優的目的,就是降低I/O成本,從而提高效率。(一般而言,I/O降低了,duration自然就會降低)詳細內容,參考我以前的post:http://blog.joycode.com/juqiang
執行完成后,我們仔細看下面的輸出。
1、 XL_TALLY_Proc04這個sp的reads最大,將近100w,duration也達到了25秒多。
2、 Erp_IM_GMBill_GetBill這個sp的I/O不算大,才7w,duration平均都在1秒多點。但是這個sp執行的次數非常多。
經過詢問客戶,XL_TALLY_Proc04這個sp執行的頻度很低,一天也就一兩次,但是Erp_IM_GMBill_GetBill大概5分鐘就要一次。這樣整體I/O就占用的非常大。
所以這里我們要重點分析Erp_IM_GMBill_GetBill這個sp,而不是第一個!
總結一個原則就是:調整的重點是客戶最關心的內容,是執行頻度最高、看起來I/O又比較大的那種。I/O最大的,不一定是我們要優先解決的內容。
第三步,開始分析剛才看到的那個語句。既然我們要分析I/O,那么就要把I/O打開,這樣每次調整sql,我們都能隨時看到I/O的變化情況。這句很有用處地:set statistics io on
單純看I/O變化,我們會暈倒的。因為我們不知道自己做的任何改動,對I/O是如何產生影響的。所以,還要看sql的執行計劃是怎佯的。 在查詢分析器中,我們按Ctrl+K,或者如下圖的菜單,check上即可。
好了,準備工作都做好了,下面開始干活了。
我們首先看sql語句的調優,假設下面這條sql語句性能低下:
上面的sql一共讀取了6636條數據,邏輯讀是1126。那么這個I/O是否合理呢?大了還是小了?還有改進的余地嗎?我們看執行計劃:
哦,一共4個咚咚在里面。Index seek的成本占了2%, index scan的占了47%,hash match占了51%,select最終是0%。我們應該牢記第二個原則,所有的index,盡可能的都走index seek。
我們看一下billsoflading的索引信息:
當前索引為什么走scan,這里就不說了,感興趣的可以隨便找一本介紹數據庫索引的書籍來看看即可。根據我以前那篇blog的描述,我們知道應該建立一個復合索引(也叫convered index):boldate+companyid+bolcode
然后我們重新執行sql,看看I/O變化情況:
Ooh,非常cool!logical reads降低到了50。為什么會這樣呢?我們看一下執行計劃:
原來是index scan變成了index seek,效率自然大大的提升!
Sql語句在index上調優的方法,基本就是這樣。我們繼續看sp的。
對于sp的調優,有一點是和sql調優不同的:sp內部的邏輯處理可能非常復雜。單純從查詢分析器中,我們無法得知哪一小塊的sql執行的I/O最大,我們只能看到一個總體的描述。所以,我們要知道sp內部的信息。
首先,了解自己當前的spid是多少。一種方法是select @@spid,另一種方法是看查詢分析器下面的status bar的信息。
Ooh,我的spid是101。(上圖的最下面那個tips)
然后我重新打開profiler(事件探查器),重新建立一個跟蹤,這里面要修改第二個tab頁的信息,把左面事件列“存儲過程”中的SmtpCompleted加上
增加后的樣子如下:
然后修改第4個tab頁,把剛才看到的spid=101的信息填上:
點擊運行后,這樣profiler只能抓到在查詢分析器中,spid=101那個窗口發送的sql。我們切換回查詢分析器,執行有問題的sp,執行完成后,我們再回到profiler,點停止按鈕。一個sp內部所有執行的sql,都被分開了!
這次的結果假設保存在了jq2表中,我們把所有執行的小片sql都列出來:
第一個是sp執行后的總體結果,I/O為62328,就是這個sp自己的。第二個是向臨時表中插入數據,I/O為61514,我們很容易看到,這一句占用了整個sp的大概95%以上的成本。如果我們把這句insert into #temptable搞定,整個sp的成本自然就下來了。所以我們需要把這句insert搞出來。
但是慢著!default情況下,sqlserver的results只顯示很少的字符,第二行的sql,我們根本抓不全的,所以我們需要修改一下設置。在查詢分析器的工具-選項菜單中,切換到“結果”這個tab頁,修改每列最多字符個數為8192(這是最大的允許值),然后點擊“確定”按鈕,重新從jq2中讀取信息。也許你會問,如果某個sql特別長,怎么辦?其實很簡單,在你的代碼中把這句sql單獨寫到log中,或者直接修改sp,把這句print出來即可。
Ok,我們把這句insert sql抓下來后,放到查詢分析器中。因為temptable我們沒有它的結構,所以我們把insert部分注釋掉,看后面的select語句。執行后,ooh,在goodsmovement表上的成本是57834。
老辦法,我們繼續看執行計劃:
其實,現在又回歸到了sql調優的步驟,下面的工作我就不寫啦!
這個步驟,看起來很簡單,希望大家對于sql調優(索引部分)心中都有這么一個概念,知道第一步作什么,第二步作什么。還是那句話,索引調優,基本上是最簡單的。但是貌似簡單的東西,我們越應該重視。你隨便找一個應用跟蹤一下,各種效率低下的索引,會讓你實在#¥*#(**……¥
最后,看看偶的桌面,14集何時能夠出來呢?期待中……
?
轉載于:https://www.cnblogs.com/ivan-zheng/archive/2009/10/09/1579828.html
總結
以上是生活随笔為你收集整理的SQL Server性能调优入门(图文版)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 给Repeater、Datalist和D
- 下一篇: [转]Flex unit testfle