性能調優2:CPU
關系型數據庫嚴重依賴底層的硬件資源,CPU是服務器的大腦,當CPU開銷很高時,內存和硬盤系統都會產生不必需要的壓力。CPU的性能問題,直觀來看,就是任務管理器中看到的CPU利用率始終處於100%,而偵測CPU壓力的工具,最精確的就是性能監控器。
一,使用性能監控器偵測CPU壓力
性能監控器(PerfMon)是偵測CPU壓力的首選工具,對於CPU高利用率,在使用性能監控器時可以重點關註下面的3個計數器:
- Processor/ %Privileged Time:花費在執行Winidows內核命令上的處理器時間的百分比
- Processor/ %User Time:花費在處理應用程序上的處理器時間的百分比
- Process(sqlserver.exe)/ % Processor Time:每個處理器所有進程的總處理時間
除了上面這3給計數器之外,還可以使用SQL Statistics計數器來監控:
- SQL Server:SQL Statistics/Auto-Param Attempts/sec
- SQL Server:SQL Statistics/Failed Auto-params/sec
- SQL Server:SQL Statistics/Batch Requests/sec
- SQL Server:SQL Statistics/SQL Compilations/sec
- SQL Server:SQL Statistics/SQL Re-Compilations/sec
- SQL Server:Plan Cache/Cache Hit Ratio
二,使用DMV偵測CPU壓力
使用DMV來偵測當前系統CPU的壓力,常規的步驟是:
- step1:使用sys.dm_os_wait_stats 檢查等待,查看是否存在CPU壓力
- step2:根據等待類型,通過sys.dm_os_wait_stats 和 sys.dm_os_schedulers 確定CPU問題的種類
- step3:通過sys.dm_exec_query_stats 和 sys.dm_exec_sql_text 找出計劃緩存中CPU消耗最高的查詢
- step4:通過sys.dm_os_waiting_tasks找到當前任務中CPU相關的等待類型中CPU消耗最高的任務
- step5:從sys.dm_exec_requests中找到當前查詢中CPU資源使用最高的查詢。
三,CPU相關的等待
從sys.dm_os_wait_stats 中檢查等待,對於CPU壓力,通常相關的等待類型是:SOS_SCHEDULER_YIELD和CXPACKET
1,CXPACKET
CXPACKET是最常見的並行等待,如果一個查詢由多個線程組成,那麽只有在最慢的那個線程完成之後,整個查詢才會完成。這就是並行查詢的木桶效應,一個木桶的容量取決於組成木桶最短的那塊木條的長度。
在多CPU的環境中,一個單獨的查詢可以使用多個線程來共同完成,每個線程單獨處理數據集的一部分。在並行處理的過程中,如果某個線程處於落後狀態,CXPACKET等待就會產生。但是,應該註意,CXPACKET等待並不總是表示系統存在性能問題。需要測試,合理設置並行度閾值(Cost Threshold for Parallelism,CTP)和最大並發度(Max Degree of Parallelism,MDP),這兩個配置項的用途是:
- CTP是指只有查詢的開銷超過一定的閾值之後,才會使用並發操作
- MDP應設置為CPU的內核數量,表示最多使用多少個線程同時處理任務
出現CXPACKET等待的原因是:
- 在可變類型中,數據的分布存在嚴重的傾斜,比如某列nvarchar類型的數據,有些數據的長度是幾個字符,有些的幾千個字符,對這樣的數據進行查詢時,會導致某些線程執行很快,但另一個線程執行很慢。
- 查詢所需要的數據存放在不同的IO子系統中,而這些子系統的性能又存在差異
- 查詢所需要的數據中,不同部分的碎片不同,所需的IO也不同。IO數量直接影響運行速度和資源開銷,從而導致查詢過程中不同線程的運行速度不同。
2,SOS_SCHEDULER_YIELD
多任務等待,多任務是指服務器同時處理多個任務,SOS_SCHEDULER_YIELD等待類型就發生在一個任務資源放棄當前占用的資源,讓其他任務使用資源執行下去。
SQL Server以協同模式運行,在必要的時候,SQL Server會讓出資源給其他線程,通常來說,這種讓步是臨時的,但是,當長期、大量出現這種等待的時候,有可能意味著CPU存在壓力,這個時候,可以檢查 sys.dm_os_schedulers,看看當前有多少個 runnable的任務在運行,
select schedule_id, current_tasks_count, runnable_task_count, work_queue_count, pending_disk_io_count from sys.dm_os_schedulers where schedule_id<255
通常情況下,如果 runnable_task_count 字段長時間存在兩位數的數值,就意味著CPU可能存在壓力,無法應對當前的工作負載。
四,常見的高CPU利用率的原因
下面總結了7個常見的高CPU利用率的情況。
1,缺失索引
當沒有合適的索引用於支持查詢時,一般只能通過大面積表掃描來獲取所需要的信息,這會導致SQL Server需要處理很多非必要的數據,由於需要加載很多非必要的數據到內存,這些IO操作需要消耗CPU資源,大量數據被加載到內存也會引起內存壓力,導致計劃緩存被移除,使得SQL Server必須重新編譯執行計劃,編譯和生成執行計劃也是高CPU開銷操作。
2,統計信息過時
SQL Server 優化器借助統計信息來預估查詢開銷,如果統計信息過時、不準確,會導致優化器產生不合適的執行計劃。
可以檢查一下圖形執行計劃,如果預估行數和實際行數的的差異很大,就說明統計信息過時,需要更新。
3,非SARG查詢
SARG是 Search Argumeng的縮寫,簡單來說,如果一個查詢條件(where,on)能用到索引查找操作(seek index),那麽該表達式就是SARG。
通常情況下,對索引列使用了計算式或函數,或者使用了 like ‘%str‘等都會導致索引失效,這類查詢都屬於非SARG查詢。
4,隱式轉換
由於SQL Server無法匹配不同類型的數據,所以需要先把數據轉換為相同的類型,才能進行匹配。
如果在實際的執行計劃中出現 CONVERT_IMPLICIT 操作符,就說明出現了類型的隱式轉換。
5,參數嗅探
參數嗅探是指在創建存儲過程,或者參數化查詢的執行計劃時,根據傳入的參數進行預估並生成執行計劃。SQL Server生成的執行計劃對當前參數來說是最優的,而對其他大多數參數來說,是非常低效的。有些時候,針對一個查詢的第一次傳參,已經產生了一個執行計劃,當後續傳參時,由於存在對應參數的數據分布等問題,導致原有的執行計劃無法高效地響應查詢請求,這就出現參數嗅探問題。
對於參數嗅探問題,可以使用語句重編譯,編譯提示(optimize for)等功能來避免。
6,非參數Ad-Hoc查詢
非參數Ad-Hoc查詢,是指SQL Server 緩存了大量的只用一次的計劃緩存,造成內存資源和CPU資源的浪費,可以使用存儲過程、參數化的Ad-Hoc查詢或啟用 “Optimize for Ad Hoc Workloads”來避免。
參數化的Ad-Hoc查詢通常是指使用 sp_executesql 來執行一段TSQL代碼。
“針對即席工作負載進行優化”是一個Server級別的性能優化選項,用於提高包含許多臨時批處理的工作負載的計劃緩存的效率,如果把該選項設置為True,則數據庫引擎在首次編譯批處理時只保留計劃緩存中的一個存根,而不是存儲整個執行計劃。當再次調用該批處理時,數據庫引擎識別出該批處理在之前被執行過,進而從計劃緩存中刪除該執行計劃的存根,並把完全編譯的執行計劃添加到計劃緩存中。當非參數化的Ad-Hoc查詢較多時,可以避免計劃緩存存儲過多的不會被復用的執行計劃。
7,壓縮操作
壓縮和解壓縮都是CPU高開銷的操作,數據壓縮、備份壓縮和日誌流壓縮通過增加CPU的利用率來降低IO子系統壓力和硬盤空間壓力。數據壓縮的優點是降低IO子系統的壓力,提高查詢的性能,其缺點是消耗CPU資源,對數據的插入和更新操作有負面影響。
參考文檔:
性能調優2:CPU