cpu高使用率往往會導緻sql server服務響應緩慢,查詢逾時,甚至服務挂起僵死,可以說cpu高使用率是資料庫這種背景程序服務的第一大殺手。本系列文章之一的“索引缺失”就是cpu高使用率的最常見的原因之一。
“鳥啊,我們平時在服務阿裡雲rds sql server客戶的過程中,遇到最多的一個問題就是,客戶回報rds sql server資料庫cpu使用率很高(有時超過90%,甚至到100%),導緻查詢緩慢甚至逾時,這類問題要如何解決啊?”。老鳥已經被類似的問題煩透了。
“鳥哥,關于cpu高使用率高問題,原因各式各樣,不是一兩句話能夠說得清楚的。”,菜鳥開始賣關子了:“那,要不這樣吧,我寫一個專題系列文章來分析各種場景,以解決rds sql server cpu高使用率的問題吧。”。
關系型資料庫(rdbms)系統中,索引缺失最為常見會導緻i/o讀取很高,進而導緻cpu使用率很高。這是因為當查詢優化器在執行計劃評估過程中,發現沒有合适的索引可以使用時,不得不選擇走全表掃描(table scan)或者近似于全表掃描的操作(clustered index scan)來擷取所需要的資料。這種大面積的資料掃面會導緻i/o子系統讀取操作頻繁,sql server需要讀取大量的資料并加載到記憶體中,這些操作最後都會使得cpu使用率飙高。這種場景中,解決cpu高使用率的問題,其實就變成了解決索引缺失的問題。我們可以從下面的例子中來看看如何發現和解決索引缺失的問題。
在這裡,我們将這個例子詳細分解為五個小步驟:
測試環境:搭建簡單的測試環境。
執行查詢:建立缺失索引前後用于做性能對比的查詢語句
缺失索引:查找缺失索引的方法
解決問題:建立缺失的索引
效率對比:建立缺失索引前後的性能對比
建立測試環境包括:建立測試資料庫、測試表對象和初始化200萬條記錄。
初始化了200萬條資料,如下:

查詢使用者10057在近一個月内的商品購買情況(為了擷取性能對比資訊,我打開了time和i/o統計),建議在執行語句之前打開實際執行計劃擷取選項。打開實際執行計劃,方法是點選ssms中的下圖方框中圖示,或者使用快捷鍵ctrl + m:
執行查詢語句:
執行查詢語句的i/o,cpu和時間消耗,其中,邏輯i/o讀取消耗32295,cpu消耗451 ms,執行時間消耗648 ms,如下圖展示:
執行計劃走clustered index scan(性能消耗幾乎于table scan相近),索引缺失警告資訊,如下圖綠色字型,右鍵點選,然後選擇missing indexes details...可以打開缺失索引的詳細資訊:
除了上面事例講解的執行計劃檢視缺失索引的方法以外,我們還可以使用三個重要的系統動态視圖來檢視缺失索引(每個視圖具體含義,請自行檢視幫助文檔):
sys.dm_db_missing_index_group_stats
sys.dm_db_missing_index_groups
sys.dm_db_missing_index_details
利用三個系統動态視圖來查找缺失的索引,方法如下:
執行後的查詢結果如下圖所示:
無論是通過執行計劃檢視索引缺失,還是通過三個動态視圖擷取缺失索引,最終的目的就是解決問題,讓我們建立這個缺失的索引:
建立了這個缺失索引以後,再次上面執行上面“執行查詢”中的查詢語句,執行計劃和性能消耗對比。
執行計劃,已經走到了更加高效的index seek上來了,如下圖所示:
i/o讀邏輯取消耗為126、cpu消耗為16 ms和執行時間消耗為198 ms,截圖如下:
建立索引後,執行時間消耗,cpu消耗,i/o讀取消耗,分别提高了3.27倍,28.19倍和256.3倍,平均性能提高了95.92倍。對比情況做圖如下:
這篇文章從理論結合實際,介紹了cpu高使用率的解決方法系列文章之一,缺失索引。從最終的測試結果來看,建立索引後,對于特定查詢性能在cpu使用率、時間消耗和i/o讀取三個方面都有很大提升,尤其是i/o讀取操作提高了256.3倍,平均的性能提升達到了95.92倍,效果十分明顯。