1. 程式人生 > >讓天下沒有難用的資料庫 » RDS

讓天下沒有難用的資料庫 » RDS

早上收到客戶反饋使用者操作非常的卡,聯絡幫助進行排查,下面總結關於sqlserver 問題排查的方法經驗:

方法一:ACTIVE MONITOR

通過sqlserver 的active monitor 來觀察當前系統的實時執行狀況

A. OVERVIEW 概況:CPU,WAITING TASK,DATABASE IO,BATCH REQUESTS

(1).CPU 是代表了當前例項的cpu 的使用情況,通常情況下,cpu 使用越高,代表了你的例項存在效能問題,常見的比如索引選擇錯誤,全表掃描導致資料庫的邏輯讀非常的高,當然不能僅僅憑cpu 來判斷問題,要綜合結合其他指標來進行判斷系統問題,這
個時候就需要把當前正在執行的sql 取出來,排查邏輯讀高的sql;
(2) WATING tasks 代表了當前例項正在等待的任務,通常情況下,使用者在反饋自己的系統很卡的時候,該值任務佇列都非常的高,資料庫此時堆積了大量等待任務等待完成,造成任務堆積的原因常見的為鎖等待,由於資料庫在對資料進行操作的過程中(update,delete)都需要獲得該資源的鎖,如果前一個任務如果長時間獲得鎖沒有釋放,那麼後續獲取任務獲取鎖的時候就會等待,解決方法為找出引起等待的任務,對其進行調優;
(3)Database io 這個指標可以反映當前資料庫的io 使用情況,通常情況下如果系統出現了很高的io 請求(100M 以上),往往是你的資料庫出現了大量全表掃描造成的,這個時候的解決辦法就是把當前正在執行的sql 拉出來,看看那些sql 的使用的io 很高;
(4)Batch requests 這個指標是當前系統的一個事實請求數,有時候使用者的系統的併發存在問題,會導致系統的請求數彪高,這個時候需要使用者降低併發呼叫;
B.Recent expensive queries:這個選型是統計了當前例項正在執行的top sql,從下面的資料中我們著重關注以下指標:邏輯讀寫(logical write/reads /sec),平均執行時間(averageduaration/ms)

(1) 邏輯讀寫:這個指標很高的sql 往往是,其cpu 的消耗也會很高,我們在排查效能問題的時候,往往是需要我們重點關注,出現較高的邏輯讀通常都是索引建立的不好,或者全表掃描;
(2) 平均執行時間:這個指標實際是sql 執行完需要的時間,這部分時間包括了:資源等待時間+時間執行時間+返回時間,所以使用者的系統出現較卡的情況,其實就是在執行時間上出現了問題;
對邏輯讀寫和執行時間較高的sql,我們可以分析其執行計劃來判斷是否存在上述問題。
詳細sql:

效能sql 1:
Select OrderId from Pro_Order_List where H_OrderId=2013010260759 and Fxs_Cancel <> 2 and Fxy_Cancel <>
建立組合索引:
Create index ind_pro_order_list on pro_order_list(H_OrderId,H_OrderId);
效能sql 2:
Select OrderId from Pro_Order_List where oState=’0′ and C_Name Is Null and Batch_Rnd_OrderId Is Not Null and
DateDiff(Hour, Addtime, ‘2013-1-25 11:06:32′) > 5
Addtime 的datediff 函式要去掉,改為addtime>’程式計算好的時間’
效能sql 3:
INSERT INTO
[#Temp_Paging](Temp_Paging_Id, RowNumber) SELECT Id, ROW_NUMBER() OVER (Order By show_Exp_Num Asc,Exp_Time desc) AS RowNumber FROM Pro_Order_List Where show_Exp_Num=1 and CkNo=’D1006’ and Exp_Time >= ‘2012-12-24 0:00:00’ and Exp_Time <= ‘2013-1-24 23:59:59′ and oResult=’0’

Pro_Order_List 上已經含有exp_time 的索引,但不是最有效的,因為單獨查詢exp_time 條件的記錄有6w 多條:

在加上ckno 查詢後, 記錄只有0 條了, 所以需要一個組合索引(exp_time,ckno);

###############################################################################
方法二:基於等待型別的分析方法,通過獲取當前系統正在等待的事件型別,資源來判斷系統的瓶頸:

###############################################################################
方法三:查詢系統的資源等待事件,通過下面的sql 就可以查詢出是那些會話,那些sql 導致了系統的鎖等待:
SELECT ss.host_name, req.session_id ,req.status ,req.blocking_session_id,req.wait_type ,req.wait_time ,req.wait_
resource ,req.transaction_id ,st.text FROM sys.dm_exec_requests req CROSS APPLY sys.dm_exec_sql_text(req.sql_handle) as ST cross apply sys.dm_exec_sessions ss where req.status =
N’suspended’ and ss.session_id=req.session_id

可以看到有兩條update 的sql 已經等待了1w 多ms,所以我們來分析一下這兩天sql 的執行計劃:
Update Top(100) Pro_Order_List set Chk_Send_Order_Time=’2013-1-25 10:51:51′ where
show_Exp_Num_Time > ‘2013-1-22 10:51:51’ and show_Exp_Num > 0 and Import_Order_From=’QQ 網購
‘ and Is_Send_Import_Order=0 and (Chk_Send_Order_Time is Null or Chk_Send_Order_Time < ‘2013-1-25 10:46:51’)
表中Pro_Order_List 沒有合適的索引供update 使用,所以建立的組合索引:
create index ind_show_Exp_Num_Time on Pro_Order_List(show_Exp_Num_Time,Import_Order_From);

最後優化後的效果:lock 等待已經沒有再出現在等待事件中: