往期分享
RDS MySQL
RDS MySQL 執行個體空間問題 RDS MySQL 記憶體使用問題 RDS MySQL 活躍線程數高問題 RDS MySQL 慢SQL問題 RDS MySQL 執行個體IO高問題 RDS MySQL 小版本更新最佳實踐RDS PostgreSQL
RDS PostgreSQL 執行個體IO高問題 RDS PostgreSQL 慢SQL問題 RDS PostgreSQL CPU高問題RDS SQL Server
RDS SQL Server 磁盤IO吞吐高問題概述
CPU使用率過高問題是RDS SQL Server使用者遇到的性能問題中較常見的一類。當RDS SQL Server執行個體的CPU使用率持續較高時,很容易導緻資料庫通路卡慢的情況,例如一些很簡單的查詢請求的響應時間也會很久甚至逾時失敗。
資源監控
RDS控制台
RDS SQL Server的控制台中提供了如下兩種方式檢視執行個體的CPU資源使用率情況。
監控與報警
在RDS控制台的“監控與報警”頁中的“标準監控”->“資源監控”下,可以檢視指定時間段内執行個體的CPU使用率資訊。
對于單租戶模式的RDS SQL Server執行個體(除RDS SQL Server 2008 R2本地盤版和RDS SQL Server所有版本的共享型執行個體之外)來說,這裡的CPU使用率指的就是SQL Server服務程序的CPU資源消耗占作業系統總數的比例。
對于多租戶模式的RDS SQL Server執行個體(包括RDS SQL Server 2008 R2本地盤版除獨占主機類型外和RDS SQL Server所有版本的共享型執行個體)來說,同一個作業系統上會運作多個SQL Server服務程序,是以這裡的CPU使用率實際上指的是該RDS執行個體對應的SQL Server服務程序的CPU資源消耗與該執行個體的計算規格所允許的最大CPU資源使用量之間的比例。
無論對于哪一種類型的RDS SQL Server執行個體來說,CPU使用率持續過高(例如持續大于80%或90%)通常都是一個較嚴重的性能問題,并很容易導緻資料庫查詢卡慢的影響。而對于共享型執行個體來說,由于存在部分CPU核在不同執行個體之間共享複用的情況,即使目前執行個體本身的CPU使用率不是很高,也有可能遇到與之共享CPU資源的其他執行個體的CPU開銷較高導緻的CPU資源性能瓶頸問題。是以對資料庫性能的穩定性要求較高的業務來說,應避免使用共享型的RDS執行個體。
另外在“監控與報警”頁中可以設定監控頻率,即監控資料顯示的聚合粒度。對于CPU使用率名額來說,300秒/次的粒度是明顯偏大的,通常建議設為60秒/次,也就是監控曲線中單個點的資料對應連續60秒内的平均值。
CloudDBA
在RDS控制台的“CloudDBA”->“性能優化”頁中可以檢視RDS SQL Server執行個體的各類性能名額,其中預設的第一項就是CPU使用率:
點選以上圖檔可以放大檢視更細粒度的資料:
若預設沒有顯示CPU使用率名額的話,可以點選“自定義名額”按鈕并在名額清單中選中CPU使用率項即可:
相比控制台監控與報警頁中檢視的監控資料,在CloudDBA的性能洞察頁中顯示的CPU使用率資料的粒度更細,為10秒一個聚合點。但性能洞察頁中一次檢視的性能監控資料時間範圍不能超過2天,而監控與告警頁中無此限制。
性能分析與優化
性能名額分析
對于偶發或突然出現的CPU使用率明顯增高的情況,常見的原因有幾類:
-
- 資料庫查詢請求量突然增加。例如業務負載突然增加,或是資料緩存服務層出現了緩存穿透的情況等。
- 查詢請求的開銷突然增大。例如應用中出現了一些新的類型的低效查詢請求,或是某些查詢語句的執行計劃發生了改變等。
- 查詢語句的執行計劃編譯頻率明顯增加。例如當執行個體的緩存壓力增大時,會導緻執行計劃緩存數量明顯下降和緩存命中率下降,并進一步造成查詢語句編譯的頻率和整體開銷明顯增加。
相應的,我們通常可以首先在性能名額監控中重點關注如下性能名額與CPU使用率名額之間的關系,以初步判斷可能是哪種原因導緻的CPU使用率突然增高:
它們分别對應SQL Server中的如下三個性能計數器名額:
-
- SQLServer:SQL Statistics\Batch Requests/sec:這個名額即QPS,如果它的增高和CPU使用率的增高比較一緻的話,則說明是資料庫查詢請求量的增加導緻的CPU使用率增加,那麼CPU高問題的原因本身并不在資料庫層面,而應從應用層面分析是什麼原因導緻了資料庫查詢請求量的增加。
- SQLServer:Buffer Manager\Page lookups/sec:這個名額是平均每秒在執行中的查詢請求累積的總邏輯讀頁數,這個值如果較高則查詢請求執行的CPU開銷也一定會較高,并且導緻Page lookup高的原因往往是查詢語句的執行效率較差。是以如果Page lookup/sec的增高和CPU使用率的增高比較一緻,而QPS值變化并不大的話,則通常說明是資料庫中出現了查詢語句執行開銷高的情況,其中既有可能是出現了新的類型的低效查詢,也有可能是原有的查詢語句的執行計劃發生了改變。這種情況下,就需要進一步分析是哪些類型的查詢語句産生了較高的CPU資源消耗,并針對具體的查詢語句進行性能優化。
- SQLServer:SQL Statistics\SQL Compilations/sec:這個名額是平均每秒的查詢請求編譯的次數,如果SQL Compilations/sec的增高和CPU使用率的增高比較一緻,而QPS值變化不大的話,則有可能是查詢編譯開銷高導緻的CPU增高。這時還可以進一步檢查一下如下與執行計劃緩存數量相關的性能名額,如果Cache_Object_Counts和Cache_Pages的值下降也比較明顯的話,則有較大可能是執行個體的緩存壓力大原因所緻。這種情況下,提升執行個體的記憶體規格通常是比較有效的優化方法。
以下為一個實際的案例參考:
從CPU使用率名額的監控中可以看到,CPU的飙高主要出現在9:10-9:20和9:30-9:40這兩個時段。該實時段内執行個體的QPS并沒有增加,QPS的增加實際上是在9:40之後,是以CPU使用率的增高并不是資料庫查詢請求數量的增加導緻的。同期SQL Compilations/sec的值也無明顯飙升,并且其絕對值也很低,是以查詢編譯開銷也不是導緻CPU增高的原因。而Page lookups/sec值的增高與CPU使用率的增高時間基本一緻,是以較大的可能性是9:10-9:20和9:30-9:40這兩個時段内有某些執行開銷較高的查詢請求存在,導緻了執行個體整體CPU使用率的明顯飙升。
在這種情況下,我們就需要進一步去分析在上述時段内主要有哪些查詢語句的執行導緻了較高的CPU資源消耗。另外Page lookups/sec的值增高一定會導緻CPU使用率增高,但也會有些查詢語句的執行CPU開銷很高而邏輯讀開銷并不高的情況,這時我們也是要先去分析CPU高時段内的查詢語句的執行資訊以定位原因。
查詢語句性能分析
活動會話分析
在導緻SQL Server執行個體的CPU使用率突然增高的各種原因中,最常見的情況還是資料庫中出現了某些執行效率較差的查詢語句,并造成語句執行過程中的CPU資源消耗較高。對于這類查詢語句性能問題的定位和分析,主要可以利用CloudDBA性能洞察中的Average Active Sessions(AAS)功能。
RDS背景會每10秒檢查一次SQL Server執行個體中的活動會話(Active Session)的資訊,并記錄下目前處于活動狀态的查詢請求的SQL語句、query hash、執行計劃及等待事件類型等。對于CPU開銷高的查詢語句來說,它在處于執行狀态的過程中有很大可能其等待類型會是CPU,這樣在性能洞察的AAS部分的top SQL清單中,等待類型是CPU的占比較高的語句,基本上也就是對CPU資源消耗占比較高的語句了。
這裡的SQL Hash列的值即對SQL語句結構參數化之後的哈希值,它用于辨別在語句結構上完全相同的一類SQL語句,對于将SQL語句按照結構進行歸類聚合統計提供了便利,利用它可以直接從系統視圖sys.dm_exec_query_stats中基于query_hash列的值進行檢索,進而獲得該語句最新的執行情況統計的資訊。此外在上圖中直接點選語句的SQL Hash列的連結,還可以檢視該語句本身的AAS統計結果:
對于CPU開銷高的語句的性能問題分析與優化,主要還是通過分析其執行計劃來進行。在以上top SQL清單中,可以直接點選“分析”檢視SQL語句的執行計劃,或是點選“下載下傳”将其執行計劃下載下傳到本地(擴充名為.sqlplan),并在SQL Server Management Studio工具中打開并檢視詳細資訊。
點選“分析”之後,除了可以檢視到SQL語句的執行計劃,還可以看到CloudDBA基于對語句的執行計劃的分析給出的一些性能優化參考建議:
不過以上優化建議主要基于一些正常的基本優化政策,對于結構較為簡單的SQL語句來說,效果往往會比較好。但對于一些較為複雜的SQL語句來說,建議使用者還是應在參考以上優化建議的基礎上對執行計劃的資訊進行具體的分析,進而得出優化方案并做實際測試驗證。
Top SQL分析
利用CloudDBA性能洞察中的活動會話監控功能,可以比較友善的定位在特定時段内導緻CPU資源使用率飙升的問題SQL語句。但這種方式并不能提供各類SQL語句的執行頻率、平均CPU開銷及整體CPU資源消耗占比等資訊。從優化執行個體的整體CPU資源效率的角度考慮,擷取CPU資源消耗top SQL語句的詳細統計資訊往往是很有必要的。
SQL Server中對于SQL語句和存儲過程等對象的執行相關的資訊提供了自動彙總統計的功能,并可通過sys.dm_exec_query_stats和sys.dm_exec_procedure_stats等系統視圖直接檢視,對于定位各類資源開銷的top SQL語句是非常友善的。視圖中的worker_time相關的列即是關于SQL語句執行的實際CPU開銷統計的,例如以下語句可以用于統計自SQL Server服務啟動以來,目前執行個體上總體CPU開銷排名前10的SQL語句的執行統計情況,也包括其最後緩存使用的執行計劃的資訊等。
select top 10
DB_NAME(qp.dbid) as database_name, OBJECT_NAME(qp.objectid,qp.dbid) as object_name,
SUBSTRING(st.text,(qs.statement_start_offset/2)+1,((case qs.statement_end_offset when -1 then DATALENGTH(st.text) else qs.statement_end_offset end - qs.statement_start_offset)/2) + 1) as sql_statement
,qp.query_plan
,qs.sql_handle,qs.statement_start_offset,qs.statement_end_offset,qs.plan_generation_num,qs.plan_handle,qs.creation_time,qs.last_execution_time,qs.execution_count,qs.total_worker_time,qs.last_worker_time,qs.min_worker_time,qs.max_worker_time,qs.total_physical_reads,qs.last_physical_reads,qs.min_physical_reads,qs.max_physical_reads,qs.total_logical_writes,qs.last_logical_writes,qs.min_logical_writes,qs.max_logical_writes,qs.total_logical_reads,qs.last_logical_reads,qs.min_logical_reads,qs.max_logical_reads,qs.total_elapsed_time,qs.last_elapsed_time,qs.min_elapsed_time,qs.max_elapsed_time
from sys.dm_exec_query_stats qs
cross apply sys.dm_exec_sql_text(sql_handle) st
cross apply sys.dm_exec_query_plan(plan_handle) qp
order by qs.total_worker_time desc
關于系統視圖sys.dm_exec_query_stats的更多詳細說明,可參考如下連結:
https://docs.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-exec-query-stats-transact-sql此外Management Studio中自帶的Top query類報表,以及CloudDBA性能優化中的TOP SQL/TOP Objects報表功能,實際也是基于以上系統視圖的,使用起來較為友善,但是不如直接基于系統視圖進行查詢的方式更加靈活。
參數優化
SQL Server執行個體級的參數選項max degree of parallelism(最大并行度,簡稱MAXDOP)用于控制單個查詢請求可以同時使用的最大活躍線程數(也即CPU核數)。對于一些CPU開銷較高的SQL語句來說,若使用并行度較高的執行計劃,其執行時間可能會顯著縮短,但也意味着其在機關時間内的CPU資源消耗會明顯增加,并可能由此導緻執行個體的CPU使用率在短時間内大幅飙升。
最大并行度值的設定,往往要在提升低效查詢語句的執行速度和保持執行個體的CPU資源使用率整體平穩之間進行權衡。一般來說,對于查詢請求的并發量較高且絕大部分SQL語句的執行開銷都很低的OLTP型負載的執行個體來說,MAXDOP的值應設的較小一些,甚至為1(即完全無并行)。而對于查詢請求的并發量較低且存在一些執行開銷較高的SQL語句的OLAP型或混合型負載的執行個體來說,MAXDOP的值可以設的相對大一些,但一般建議不超過執行個體可使用的最大CPU核數的1/2或1/4。
另外查詢并行度的提升,雖然可以幫助提高某些SQL語句的執行速度,但往往也會帶來語句執行過程中的整體CPU資源開銷的增加,并導緻執行個體的整體CPU使用率的增加。是以對于執行個體的整體CPU使用率不高的情況,MAXDOP的值通常可以設的相對高一些。而對于執行個體的整體CPU使用率已經很高的情況,增大MAXDOP往往會進一步加劇CPU資源的競争,并導緻查詢語句性能的整體下降,這種情況下MAXDOP的值通常就應設的低一些。
在RDS SQL Server中,max degree of parallelism參數的預設值為2,是一個相對平衡偏保守的選擇。使用者可以通過RDS專用的存儲過程sp_rds_configure來對該參數的設定值進行修改,并且是立即生效的,無需重新開機執行個體:
https://help.aliyun.com/document_detail/88094.html#section-exf-v53-v2b當出現執行個體的CPU使用率過高的情況時,如果從CloudDBA性能洞察的AAS中看到Parallelism類型等待的占比較高,則可以考慮适當降低max degree of parallelism參數的設定值來緩解執行個體的CPU壓力。