一大早收到一堆CPU預警郵件,通常每天只在統計作業執行期間會收到2~3封CPU預警郵件。這次的預警來自另一台服務器,並且明細數據顯示其CPU一直維持在49%。
登錄到服務器,查看任務管理器(查看資源監視器更好),CPU時不時上漲到100%,CPU被誰使用了呢?雖然猜測到是被SQLServer,還是打開性能監視器添加\Processor(_Total)\% Processor Time、Process(sqlservr)\% Processor Time計數器
可以看到CPU使用率持續98%時,SQLServer占用CPU持續約為1575%,服務器有16個logical cores,平均值為1575%/16=98.44%,也就是CPU繁忙基本是由SQLServer引起。
那么就用profiler把高消耗語句拎出來(此時猜測可能是頻繁執行某一高消耗的語句),列篩選設置CPU>=100毫秒,等了十來秒沒看到任何語句,不斷地更改篩選條件,
終於看到一條異常語句,語句每1分鍾執行一次,每次執行時長約30秒,執行期間服務器CPU接近100%!

--問題語句 SELECT TOP 100 T1.guid, T1.UserID, T1.UserChairID, T1.UserTreasure, T1.FirstRound, T1.SecondRound, T1.ThreeRound, T1.MachineSerial, T1.LoginIP, T1.RecordTime, T1.ServerID, T2.UserID AS JSID, T2.UserChairID AS JSChairID, T2.UserTreasure AS JSUserTreasure, T2.FirstRound AS JSFirstRound, T2.SecondRound AS JSSecondRound, T2.ThreeRound AS JSThreeRound, T2.MachineSerial AS JSMachineSerial, T2.LoginIP AS JSLoginIP FROM dbo.XxxxRecordDetail AS T1 WITH(NOLOCK) LEFT JOIN dbo.XxxxRecordDetail AS T2 WITH(NOLOCK) ON T1.Guid = T2.Guid AND T1.UserID != T2.UserID WHERE T1.PeopleNum = 2 AND T2.PeopleNum = 2 AND T1.UserTreasure < 0 AND T1.RecordTime >= '2017-5-10 8:36:36' AND T1.RecordTime < '2017-5-10 13:36:36' ORDER BY T1.RecordTime ASC
由於語句執行期間CPU過高,因此沒必要再次執行語句來查看執行計划。直接從計划緩存查找

--參考 http://www.cnblogs.com/Uest/p/6419017.html 計划緩存 --特定語句聚合性能統計µs select top 100 SUBSTRING (c.text,(b.statement_start_offset/2) + 1 ,((CASE WHEN b.statement_end_offset = -1 THEN LEN(CONVERT(NVARCHAR(MAX), c.text)) * 2 ELSE b.statement_end_offset END - b.statement_start_offset)/2) + 1) RunSQL ,b.creation_time --編譯計划的時間 ,b.last_execution_time --上次開始執行計划的時間 ,b.execution_count AS SQLExCount--計划自上次編譯以來所執行的次數 ,b.last_logical_reads --上次執行計划時所執行的邏輯讀取次數 ,b.total_logical_reads/b.execution_count avg_logical_reads ,b.last_worker_time --上次執行計划所用的 CPU 時間(微秒) ,b.last_elapsed_time --最近一次完成執行此計划所用的時間(微秒) ,b.total_elapsed_time/b.execution_count avg_elapsed_time --上次完成執行此計划所用的總時間 --,b.sql_handle,b.plan_handle ,d.query_plan ,c.text FROM sys.dm_exec_query_stats b with(nolock) CROSS APPLY sys.dm_exec_sql_text(b.sql_handle) c CROSS APPLY sys.dm_exec_query_plan(b.plan_handle) d where c.text like '%KeyWords%'
語句對應執行計划
可以看到消耗花費在聚集索引掃描,語句T2用了條件peoplenum=2進行掃描~
分析語句業務邏輯,其實就是返回Xx游戲2人局各場明細信息。T1能快速返回滿足where條件的記錄,何不用這些記錄到T2中查找。通過指定索引,指引語句按照我們的期望的方式去執行。優化前、后跟蹤對比
優化前、后性能計數器對比
可以看到修改后CPU立馬降下去。在文章的開頭收到的預警郵件顯示最高CPU使用率為49%,但實際在某些時候達到98%+。難道sys.dm_os_ring_buffers記錄數據時CPU剛好回落●-●