早上收到客户反馈用户操作非常的卡,联系帮助进行排查,下面总结关于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 等待已经没有再出现在等待事件中: