查詢效能調校

1.將非 SARG Statement 改成為 SARG Statement

SARG中文叫”查詢參數”,意指WHERE子句中的所有條件。當查詢相同結果時,每個開發人員寫出來的WHERE子句格式可能都不太相同,

在大多數情況下,如果想讓查詢最佳化程式透過索引快速找尋資料(比較索引鍵值),那WHERE子句必須符合SARG格式。

符合的運算子: <、>、=、<=、>=、LIKE(視萬用字元所在位置) 和BETWEEN。

不符合運算子: <>、!<、!>、NOT、NOT IN、NOT EXISTS和NOT LIKE..等。

當然非SARG語法還有很多,如不要對欄位做運算、不要對欄位使用函數…等。

雖然有時會因使用者需求導致寫出的查詢語法無法如願符合SARG格式,

但無論如何請盡可能將不符合SARG改成符合SARG,因為這是查詢調校最直覺的第一步。

 

2.確認相關索引或資料表統計值是否過時

簡單來說,統計值是紀錄資料內容分布的情形,可以針對索引或是資料表某個欄位建立統計值,

而查詢最佳化程式就是憑者資料分布的統計值資訊才可以得知使用某個索引對查詢的選擇性如何,

透過分析該索引的執行成本高低,建立最佳執行計畫,若沒有統計值或統計值過時(久未更新),

就會影響查詢最佳化程式無法找出最佳執行查詢 Statement的邏輯步驟,進而建立極差的執行計畫,導致查詢效能不佳。

 

3.執行查詢效能低落並產生實際執行計畫

image

在分析執行計畫時,我們不能只單看成本(CBO),應該將 statistics i/o statistics time 也列入分析中

(如你使用圖型執行計畫請選擇包括實際執行計畫,勿選擇顯示估計執行計畫)。

 

4.分析執行計畫中邏輯和實體作業(關注成本高的作業)

image

閱讀圖型執行計畫是由上而下、由右到左,每個圖示都表示一項以執行的邏輯和實體作業,

而箭頭表示作業之間的資料流向。厚度表示作業之間傳遞的資料列數量,越厚表示資料列越多。

如果將滑鼠移到資料表掃描圖示上,會顯示該作業的詳細資料 (如下圖),這階段我們將關注點放在成本高的作業

image

叢集索引掃描作業詳細資料。

 

5.降低高成本作業

如何降低高成本作業,這階段端看個人經驗累積(個人認為勿戰),

就個人查詢調校經驗中大多是DBA或開發人員未建立相關正確Index而導致查詢效能低落,

雖然有同事和朋友曾對我說使用工具就好了,何必去了解什麼是SARG(search argrment)?

SQL Server如何去處理查詢statement?  統計值和執行計畫能吃嗎? 索引搜尋作業就是最佳嗎?…等,

我不能否認UI工具所帶來的便利性,但就我個人使用過的經驗,絕大部分的調校工具都只能當做參考,

好比 Oracle SQL Tunning AdvisorSQL Server DTA..等。anyway~這裡我就簡單來模擬一下該網友問題。

 

image

(這裡我使用SQL2008,雖然各版本查詢優化程式不太相同,但不影響該次結果)

 

資料量:3百萬筆

image

 

執行查詢語法(改善前)

image

邏輯讀取:242081 實體讀取:4440

CPU時間(ms):7703 經過時間(ms):56284

 

執行計畫:

image

可以看到查詢優化程式採用了平行查詢執行計畫,叢集索引掃描作業成本:91%。

 

執行查詢語法(改善後)

這裡我針對 BILL_TYPE 欄位建立nonclustered index

create nonclustered index nix_3 on dbo.blxx
(BILL_TYPE)

再次執行查詢

先清除BUFFER

dbcc dropcleanbuffers

image

邏輯讀取:6014 實體讀取:0

CPU時間(ms):781 經過時間(ms):460

 

執行計畫

image

可以看到這裡使用剛剛我們所建立的索引。

 

如果你覺得這樣還是不夠,還能再進一步提高嗎?答案是可以的,

你可以使用 Indexed View再進一步提高查詢效能,但Indexed View的維護成本比標準索引還高,

所以請謹慎使用。

 

如同我說!絕大部分的查詢效能問題,只要建立正確的索引即能解決

(經過時間(ms)從 56284 降低為 460 ,邏輯讀取從:242081 降低為 6014),

就像這位網友的問題一樣。