SE の雑記

SQL Server の情報をメインに Microsoft 製品の勉強内容を日々投稿

バッファープールとワーカースレッドスタックについて

leave a comment

SQL Server のメモリ領域として、バッファプールと非バッファプールという領域があります。

今回の投稿ではこのバッファプールと非バッファプールで使用されているワーカースレッドスタックについて確認をしてみたいと思います。

■バッファープールについて


SQL Server には max server memory というオプションがあります。

このオプションを使用して設定している領域がバッファプールになります。

min server memory および max server memory の 2 つのサーバー メモリ オプションを使用して、Microsoft SQL Server のインスタンスで使用されるバッファー プールのメモリ量を MB 単位で再構成します。

 

現在、max server memory を 12GB に設定しています。
image

トレースフラグ 834 を設定している場合は挙動が変わるのですが、このトレースフラグを設定していない場合、SQL Server は起動時に必要なサイズのメモリのみを確保した状態となります。
この確保状態はTotal Server Memory 等のカウンタを見ることで確認ができます。
image

現状、起動直後は 500MB のメモリが確保された状態となっています。

この状態でデータのキャッシュを増やしてみます。
image

約 11.5 GB 程度のデータをキャッシュすることができました。

この時の Total Server Memory は約 12GB となっています。

データキャッシュだけでなく、クエリキャッシュを増やすとどうなるでしょう。
Memory Manager で値を取得している場合、クエリのキャッシュは Stolen Server Memory として表されます。
# バッファキャッシュからストールされたメモリという認識になるため。

image

Database Cache Memory が減少していますが、Total Server Memory は先ほどとほとんど同一の内容となっています。

このことから、max server memory を設定することで、Memory Manager が制御しているメモリ領域の上限を設定できていることが確認できます。

 

■非バッファプール


SQL Server を利用するにあたって、バッファプールの領域だけ意識していればよいかというとそういうこともありません。
Memory Manager の制御外となっている非バッファプールの領域に関しても意識しておく必要があります。

-g オプションを設定することで設定を変更することが可能な MemToLeave (Memory to Reserve) の領域や、ワーカースレッドで使用しているワーカースレッドスタック等がこの非バッファプールを使用しているものになります。

SQL Server でどれだけワーカースレッドスタックを使用しているかを見る方法として、sys.dm_os_threads や sys.dm_os_schedulers を使用する方法があります。
image

64 ビットの SQL Server ではひとつのワーカースレッドにつき 2MB のメモリが必要になります。
max worker threads の設定を 0 にしている場合、SQL Server がスケジューラーの数に応じて動的にワーカースレッドの最大数を設定します。

設定されている最大数に関しては、[sys.dm_os_sys_info] から確認することができます。
image

スケジューラーが 8 個の場合は、576 が最大値となります。

この最大値ですが、SQL Server が起動した直後に最大数まで確保されるのではなく、必要に応じて確保され、その確保の最大数が設定されている値となります。

576 × 2MB = 1152 MB となりますが、起動直後は必要最小限のワーカースレッドの確保のみがされており、sys.dm_os_threads や sys.dm_os_schedulers で確認をした数が確保された状態となります。

起動直後だと、100  ~ 200MB 程度が確保された状態となっていると思います。

576 だと少し確認しにくいので 2000 に変えて、ワーカースレッドをこの上限値まで確保し、メモリの使用状況を確認してみたいと思います。
image

上限まで確保した結果がこちらになります。
image

max worker threads が 2000 ですので設定値までワーカースレッドの確保が行われた状態となっています。

これで大体 4GB 程度のメモリがワーカースレッドで使用されていることになります。

この時の Memory Manager の値がこちらになります。
image

Memory Manager はバッファプールの状況を確認するためには使用できますが、非バッファプールの状況を確認するためには使用できません。

そのため、ワーカースレッドで使用しているメモリの情報についてはこのカウンターでは確認ができないことになります。

ワーカースレッドで使用しているメモリを確認するための方法として 2 つの方法を思いつきました。

ひとつは Sysinternals の VMMap を使用する方法です。
image

Stack の項目を見るとワーカースレッドで使用しているメモリのサイズが確認できます。
4GB となっているので SQL Server から取得した情報とほぼ一致していますね。
VMMap を使用してワーカースレッドで使用しているメモリのサイズを確認する方法として利用できそうです。

もう一つがパフォーマンスモニタで SQL Server のプロセスの Private Bytes を確認する方法です。
image

今回は SQL Server 2012 RC 0 + Locked pages の権限を有効にしている状態なのですが、Find Non-Buffer Pool Memory (MemToLeave) in "Private Bytes" によると、Private Bytes に非バッファプールのみが含まれるかは設定によって変わってくるそうです。
Private Bytes にバッファプールのサイズが含まれている場合は、Private Bytes – Total Server Memory で計算するとよいのかなと。

ワーカースレッドが一定時間使用されておらず、破棄された後の Private Bytes の情報がこちらになります。
image

ワーカースレッドの破棄に伴い、Private Bytes が減少しているのが確認できますね。

非バッファプールの中でワーカースレッドのメモリ領域が一番確保しやすかったので軽く試してみたのですが、取得したデータの感じでは、非バッファプールで取得しているメモリの量を把握する方法として、Private Bytes は使用できそうな気がします。

SQL Server のメモリ管理は概略だけ調べても奥が深いのでもっと勉強しなければ。

Share

Written by Masayuki.Ozawa

2月 29th, 2012 at 12:57 am

Posted in SQL Server

Tagged with

Leave a Reply