一條語句導致CPU持續100%


一大早收到一堆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
View Code

由於語句執行期間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%'
View Code

語句對應執行計划

可以看到消耗花費在聚集索引掃描,語句T2用了條件peoplenum=2進行掃描~
分析語句業務邏輯,其實就是返回Xx游戲2人局各場明細信息。T1能快速返回滿足where條件的記錄,何不用這些記錄到T2中查找。通過指定索引,指引語句按照我們的期望的方式去執行。優化前、后跟蹤對比

優化前、后性能計數器對比

可以看到修改后CPU立馬降下去。在文章的開頭收到的預警郵件顯示最高CPU使用率為49%,但實際在某些時候達到98%+。難道sys.dm_os_ring_buffers記錄數據時CPU剛好回落●-●


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM