SQL Server でメモリサイズが少ない場合に、バックグラウンド タスクであるリソースモニター (Resource Monitor) の CPU 使用率が上昇する事象として、High CPU consumed by Resource Monitor due to low virtual memory というドキュメントが公開されています。
このような挙動は最新の SQL Server でも想定される動作として発生する可能性があります。
最近、リソースモニターのメモリ調整について動作を把握する必要があったのですが、WPR でリソースモニターの挙動を確認する際の素振りとして、この挙動を調べてみると情報の整理がわかりやすかったので、まとめておきたいと思います。
SQL Server のリソースモニターについてのドキュメント
SQL Server のリソースモニターについての情報は次のドキュメントを見ることになります。
リソースモニターが担う役割については次のように記載されています。
SQL Server データベース エンジン では、動的メモリ管理の一環として、メモリ不足の検出および処理のために専用のフレームワークが実装されます。 このフレームワークには、リソース モニターと呼ばれるバックグラウンド タスクが含まれています。 リソース モニター タスクでは、外部および内部のメモリ インジケーターの状態が監視されます。 これらのインジケーターのいずれかの状態が変化すると、対応する通知が計算され、その通知がブロードキャストされます。 これらの通知は各エンジン コンポーネントからの内部メッセージであり、リング バッファーに格納されます。
リソース モニターは SQL Server の動的メモリ管理を実行するためのバックグラウンド タスクとなり、メモリ状態の監視を行い必要に応じてメモリの割り当ての変更の制御を行っています。
SQL Server が使用するメモリが極端に低い場合、リソースモニターによるメモリの割り当ての制御のための処理が頻繁に行われ、リソースモニターのタスクで使用される CPU 使用率が高くなるという事象が発生します。
この事象が冒頭に記載したドキュメントに記載されているものとなります。
リソースモニターの CPU 使用時間を確認する
冒頭に記載したドキュメントでは、リソースモニターの CPU 使用時間を確認するクエリが記載されています。
記載されているクエリを少し修正したものが次のクエリとなります。(レイジーライター (Lazy Writer) もメモリの調整に関連するタスクとなるため、今回の範囲では情報は不要なのですが今後の調査用にこのタスクの CPU 使用時間も取得しています)
declare @curCPU int, @prevCPU int, @delta int, @curLazyCPU int, @prevLazyCPU int, @deltaLazy int, @msg varchar(max), @maxServerMemory int, @cnt bigint set @curCPU =0 set @prevCPU = 0 set @curLazyCPU = 0 set @prevLazyCPU = 0 set @cnt = 0 while 1 = 1 begin select @curCPU = SUM(cpu_time) from sys.dm_exec_requests where command like '%Resource%Monitor%' select @curLazyCPU = SUM(cpu_time) from sys.dm_exec_requests where command like '%LAZY%WRITER%' select @maxServermemory = CAST(value_in_use AS int) from sys.configurations where name = 'max server memory (MB)' set @delta = @curCPU - @prevCPU set @deltaLazy = @curLazyCPU - @prevLazyCPU set @prevCPU = @curCPU set @prevLazyCPU = @curLazyCPU set @msg = '[' + FORMAT(@cnt,'00000') + '] ' + FORMAT(GETDATE(), 'yyyy-MM-dd HH:mm:ss') + ' : ' + FORMAT(@maxServerMemory, '0,000') + ' MB : ' + FORMAT((@delta / 1000.00), '0.000') + ' sec : ' + FORMAT((@deltaLazy / 1000.00), '0.000') + ' sec' if(@cnt>0) begin raiserror (@msg, 10, 1) with nowait end set @cnt+=1 waitfor delay '00:00:10' end
クエリを実行するとメッセージに次のような情報が出力されます。
[00001] 2024-10-21 21:09:41 : 1,536 MB : 4.547 sec : 0.000 sec [00002] 2024-10-21 21:09:51 : 1,536 MB : 4.422 sec : 0.015 sec [00003] 2024-10-21 21:10:01 : 1,536 MB : 4.140 sec : 0.000 sec [00004] 2024-10-21 21:10:11 : 1,536 MB : 4.375 sec : 0.000 sec [00005] 2024-10-21 21:10:21 : 1,536 MB : 4.547 sec : 0.000 sec [00006] 2024-10-21 21:10:31 : 1,536 MB : 4.360 sec : 0.000 sec [00007] 2024-10-21 21:10:41 : 1,536 MB : 4.062 sec : 0.000 sec
現在 Max Server Memory は 1.5GB なのですが、この設定の場合、取得期間の差分としては 4 秒程度の CPU 使用時間となっています。
次のクエリを実行して、メモリの割り当てを 4GB に変更してみます。
EXEC sys.sp_configure N'max server memory (MB)', N'4096' GO RECONFIGURE WITH OVERRIDE GO
1.5GB から 4GB に変更した際の出力内容が以下となります。
[00013] 2024-10-21 21:11:41 : 1,536 MB : 4.375 sec : 0.000 sec [00014] 2024-10-21 21:11:51 : 1,536 MB : 4.484 sec : 0.016 sec [00015] 2024-10-21 21:12:01 : 1,536 MB : 4.532 sec : 0.015 sec [00016] 2024-10-21 21:12:11 : 1,536 MB : 4.468 sec : 0.000 sec [00017] 2024-10-21 21:12:21 : 4,096 MB : 4.141 sec : 0.000 sec [00018] 2024-10-21 21:12:31 : 4,096 MB : 2.266 sec : 0.000 sec [00019] 2024-10-21 21:12:41 : 4,096 MB : 0.000 sec : 0.000 sec [00020] 2024-10-21 21:12:51 : 4,096 MB : 0.000 sec : 0.016 sec
メモリサイズの変更が行われたことで、リソースモニターの CPU 使用時間が減少していることが確認できます。
このような挙動が冒頭に記載したドキュメントの基本的な内容となります。
WPR を使用した処理の確認
最近の Windows Server では、Windows Performance Recorder (WPR) が標準で含まれているため、Windows SDK 等をインストールしなくても標準で情報を取得することができるようになっています。
WPR のコマンド ライン オプション に記載されているコマンドを使用することで、Windows で動作しているプロセスで呼び出されている処理を確認することができます。
コマンドの例としては次のような内容となります。
# ビルトインのプロファイルを使用して WPR の取得を開始 wpr -start generalprofile -start cpu -filemode # WPR の取得を停止し、取得内容をファイルに出力 wpr -stop C:\log\wpr.etl
取得された ETL ファイルは Windows Performance Analyzer (WPA) で解析をすることができます。(WPA は標準で含まれていないかもしれませんので、解析する環境には Windows SDK が必要となる可能性があります)
WPA ではシンボルファイルを読み込ませることができるため、SQL Server のシンボルファイルと組み合わせて使用すると、次のような情報を確認することができます。
赤線でマークしているタイミングが Max Server Memory を変更したタイミングとなるのですが、変更後は「sqldk.dll!ResourceMonitor::ResourceMonitorTask」の呼び出しの回数が減少しています。
メモリサイズに余裕がある状態では、リソースモニターのバックグラウンド タスクの処理の状況が変化するため、CPU 使用時間の減少につながっているのではないでしょうか。
WPR を使用すると、SQL Server でどのような処理が実行されているかを確認することができますので、挙動を確認する際の一助となります。