SQL調優日記--並行等待的原理和問題排查


前言

  
今天處理項目,客戶反應數據庫在某個時間段,反應特別慢。需要我們提供一些優化建議。
 

現象

     由於是特定的時間段慢,排查起來就比較方便。直接查看這個時間段數據庫的等待情況。查看等待類型發現了大量的CXPAKET等待類型且等待時間長.


 
有的看官可能知道,出現這個等待類似時,可以適當降低最大並行度來解決。但是爲什麼這麼做呢?降低並行度就一定可以解決問題嗎?

CXPAKET原理

 
  那什麼是CXPAKET 等待呢。 當數據庫引擎分析查詢的開銷超過設定的閥值時,SQL SERVER會選擇並行執行。數據庫引擎會爲這個請求創建多個任務。每個任務處理數據的一個子集。每個任務可以在一個分開的CPU/核上執行。請求主要使用生產-消費 隊列跟這些任務交互。如果這個隊列是空的,(即生產者沒有推入任何數據到這個隊列)。這個消費者必須暫停並且等待。相應等待類型就是CXPACKET 等待類型。顯示這個等待類型的請求 說明這個任務應該提供,但是沒有提供任何(或足夠)數據來消費。這些生產商任務反過來可能會暫停,等待一些其他類型的等待.
如下圖:索引掃描就是一個並行執行的動作。

 

打個比方
  客戶端程序就是老闆,數據庫引擎是部門領導,老闆發出一個要求(request),查看最近一年的銷售數據。領導一看這任務工作量大,一個人查太慢,要查到猴年馬月。果斷決定多派幾個人。一次最多可以派多少個攻城獅呢?(就取決於最大並行度)這裏假設是4個。這就分配4個人 小李、小王、小張、小陳去完成。 那這一年的任務怎麼分配呢? 以後再細說。 因爲各種原因,其他人都做得了,小王還沒有完成。領導不可能拿着半成品的數據就去找老闆,只能等着小王。這就是CXPACKET.
 

問題排查


 弄懂了CXPACKET的原理,那我們怎麼來排查這類問題呢?首先,小王並不是偷懶,他的工作能力和其他人是相同的。所以,我們需要找出小王慢的原因,
 使用下面的腳本:
select r.session_id,
status,
command,
r.blocking_session_id,
r.wait_type as[request_wait_type],
r.wait_time as[request_wait_time],
t.wait_type as[task_wait_type],
t.wait_duration_ms as[task_wait_time],
t.blocking_session_id,
t.resource_description
from sys.dm_exec_requests r
LEFT join sys.dm_os_waiting_tasks t
on r.session_id = t.session_id
where r.session_id >=50
and r.session_id <> @@spid;
 


通過上面的語句我們找到,並行等待正在等待LCK_M_S.說明查詢是被其他的操作阻塞了。上面的問題是由於一個寫入語句引起的。這個語句是一個很簡單的插入動作,爲什麼寫入會這麼慢呢。可以查看磁盤響應時間,,磁盤隊列發現都出奇的高。


建議


看來問題是由於磁盤本身引起的。給出如下的解決建議:
1.更換讀寫速度更快的磁盤
2.目前數據文件和日誌文件在同一物理磁盤,分割開來
3.從業務出發。經過和客戶溝通後發現,這個表是操作日誌表。每次做業務操作都會記錄日誌。所以特別的大。
對應這樣的表,可以單獨建立文件夾組,文件,並把表放在單獨的磁盤,緩解IO壓力
4. 比如傳統機械磁盤IOPS往往是瓶頸,而吞吐量並不是,所以磁盤格式化的簇大小就比較重要,較大的簇可以減少IOPS瓶頸。
5.對於日誌表,如果能改程序,在前端程序合併寫入,或者在情況允許的情況下開trace flag 610最小化日誌寫入
6.整理磁盤碎片,另外合併&刪除日誌表的索引減少寫入開銷也能起到一定作用
 

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