SQL Server のメモリ管理 - Part 3
神谷 雅紀
SQL Server Escalation Engineer
以下に続く、SQL Server のメモリ管理の第 3 回目です。
バッファプール内の領域の用途とそのサイズ
バッファプールは、サイズが 8KB の「ページ (page)」と呼ばれる領域に論理的に分割されています。バッファプールのコミットされている領域のサイズ (以降では、これを単に「バッファプールのサイズ」と呼びます) は、パフォーマンスカウンタ Buffer Manager – Total pages により確認することができます。1 ページは 8KB であるため、このカウンタの値を 8 倍することで、バッファプールの KB 単位のサイズを算出することができます。
データベースファイルのコピーイメージ、言い換えれば、キャッシュしているデータベースのデータは、すべてバッファプール内に置かれます。そのサイズは、パフォーマンスカウンタの Buffer Manager – Database pages により確認することができます。
SQL Server:Buffer Manager オブジェクト
バッファプールは、データベースキャッシュとしてだけではなく、プロシージャキャッシュ (*1) として、また、その他の用途のメモリの供給源としても機能します。データベースデータのキャッシュ以外のために使用されるメモリ領域は、Buffer Manager の観点からは、Stolen pages と呼ばれます。そのサイズは、Buffer Manager – Stolen pages で確認することができます。
(*1) プロシージャキャッシュ : クエリの実行方法 (実行プラン) などをキャッシュしているメモリ領域
仮想アドレス空間に Free があるように、バッファプールにも、利用可能な領域 Free があります。これは、Buffer Manager – Free pages によってそのサイズが表される領域です。通常、Free pages の数は常時増減しています。それは、メモリ要求に答えるために、新しい Free pages が作り出され、それらが消費されるといった状況が、常時発生しているためです。Free pages が常に低い値を示し、また、Buffer Manager - Free list stalls/sec が 1 以上の値を示しているような場合には、SQL Server へのメモリ割り当てを増やす (max server memory の値を大きくする、min server memory の値を大きくする、物理メモリを増設する、32-bit から 64-bit に移行するなど) ことを検討することをお薦めします。
仮想アドレス空間内の予約済み (Reserved) の領域と、Buffer Manager – Reserved pages とは全く異なるものです。前者は、物理メモリやページファイルに領域を持たず、データを置くことのできない仮想アドレス空間内の領域です。後者は SQL Server 固有の概念で、メモリを使用するコンポーネントが将来の使用に備えて予約しているバッファプール内のページです。
バッファプールと AWE
AWE とは、Address Windowing Extention の頭文字であり、Windows の API セットです。AWE API を使用することで、仮想アドレス空間内ではなく、物理メモリ上に直接領域を割り当てることができます。SQL Server は、この AWE API を使用して、直接物理メモリを割り当てることで、32-bit バージョンの SQL Server においても、32-bit 仮想アドレス空間サイズである 2GB を超えるメモリを使用することができます。
AWE API を使用するためには、AWE API を使用するユーザーに lock pages in memory 権限が必要です。SQL Server においては、「AWE API を使用するユーザー」は SQL Server のサービスアカウントであるため、SQL Server が AWE API を使用できるようにするためには、SQL Server のサービスアカウントに lock pages in memory 権限が必要です。また、32-bit SQL Server では、sp_configure 'awe enabled' オプションを 1 に設定することも必要です。
AWE で使用するために MEM_PHYSICAL が指定されて VirtualAlloc API によって割り当てられた領域は、Working Set とはみなされず、Windows のページング対象とはなりません。パフォーマンスカウンタ Process - Working Set にも含まれません。そのため、AWE が使用されている SQL Server プロセスの Working Set サイズは、通常、非常に小さな値になります。
AWE マップ、アンマップ
AWE が有効である場合、バッファプールは、仮想アドレス空間と物理メモリの両方でメモリ割り当てを行います。この場合、Buffer Manager – Total pages カウンタは、仮想アドレス空間と物理メモリでの割り当ての両方を含みます。そのため、32-bit SQL Server であっても、Total pages の値は、仮想アドレス空間サイズの 2GB を超える場合があります。
物理メモリ上に割り当てた領域は、ユーザーモードアプリケーションからは、直接アクセスすることはできません。AWE API により割り当てた物理メモリは、アクセスする前に、AWE API によって仮想アドレス空間にマップしなければなりません。マップした物理メモリへのアクセスが終了し、別の物理メモリ領域をマップしなければならなくなると、今マップされている物理メモリ領域を仮想アドレス空間からアンマップし、その後、別の物理メモリ領域をマップしなければなりません。物理メモリ上に割り当てたメモリサイズよりも仮想アドレス空間のサイズの方が小さければ、このようなマップとアンマップを繰り返し、物理メモリへのアクセスを行います。
データページを見つけるためにマップが要求された回数が Buffer Manager – AWE lookup maps/sec、新たなデータページを置くためにマップが要求された回数が Buffer Manager - AWE stolen maps/sec、アンマップされたページ数を示すカウンタが Buffer Manager – AWE unmap pages/sec、アンマップが要求された回数が Buffer Manager – AWE unmap calls/sec、ディスク上のファイルへデータをフラッシュするためにマップが要求された回数が Buffer Manager – AWE write maps/sec により表されます。
AWE で割り当てた物理メモリ上に置くことのできるデータとできないデータ
AWE API を使用して割り当てた物理メモリ上の領域に置くことのできるデータは、データベースファイルのコピーイメージのみです。つまり、AWE API を使用して割り当てた物理メモリは、データキャッシュとしてのみ使用可能で、プロシージャキャッシュなどその他の用途には使用できません。
これは、AWE API により割り当てた物理メモリ上のデータが、マップ、アンマップされることを考えれば、納得できるかと思います。どのようなプログラムでも、あるデータを置くためにメモリを割り当てた場合、そのデータへのアクセスは、そのデータへのポインタ (仮想アドレス空間内のアドレス) を使用して行われます。マップされていた領域がアンマップされ、その後、再度マップされる際に、もともとマップされていた仮想アドレス空間内の場所と同じ場所にマップできるとは限りません。もし、違う場所にマップされたなら、もともとマップされていた場所を指しているポインタは無効になります。無効となったポインタを使用したアクセスは、アクセス違反 (Access Violation) 例外となればいいですが、アクセス違反例外にはならず、たまたま全く関係のないデータがそこにあった場合、そのデータを使って別のデータを変更してしまったりすると、メモリ上のデータは取り返しのつかない状態となり、プロセスを再起動する以外に修復の方法がなくなります。最悪の状況です。
データベースファイルのコピーイメージだけは、Buffer Manager が管理しているデータベース ID とページ ID によりアクセスすることができるため、アンマップ、マップが行われて以前とは異なる位置に置かれたとしても、意図したページにアクセスすることができます。
64-bit SQL Server と AWE
64-bit 環境においても、AWE API を使用することはできます。64-bit SQL Server では、SQL Server サービスアカウントが lock pages in memory 権限を持っていれば、awe enabled オプションが 0 であっても AWE API を使用します。
ここで、「現状では Windows がサポートする物理メモリの最大サイズよりも大きな 8TB (x64 の場合) もしくは 7TB (IA64 の場合) の仮想アドレス空間をサポートする 64-bit 環境で AWE を使用するメリットは何なのか」という疑問が浮かびます。
64-bit で AWE を使用するメリットは、バッファプールが Windows のページング対象となることを防ぐことです。AWE によって割り当てられた物理メモリ領域は、前述のとおり Working Set とはみなされず、ページングの対象にはなりません。
バッファプールの主要な目的は、データベースファイルから読み込んだデータをメモリ上にキャッシュしておくことでパフォーマンスを向上させることです。つまり、メモリアクセスに比べて非常に低速なディスク I/O を減らすことで、パフォーマンスを向上させることを目的としています。一方、ページングとは、物理メモリ上のデータをディスク上のページファイルへ書き出したり、ページファイルからデータを読み出して物理メモリ上に再配置することです。バッファプールのデータがページング対象になり、Windows によってディスクへ書き出されたり、ディスクから書き戻されたりするのであれば、ディスク上のデータベースファイルからデータを読み取ったり、書き戻したりするのと変わりません。これでは、データをキャッシュしている意味がありません。
ディスク I/O を減らすことでパフォーマンスを向上させようとした場合には、キャッシュされているデータがページングの対象にならないようにすることには、大きなメリットがあります。
32-bit SQL Server と 64-bit SQL Server での AWE の違いは、32-bit では、物理メモリ上のデータにアクセスするために、マップ、アンマップが繰り返し行われるのに対して、広大な仮想アドレス空間を持つ 64-bit では、物理メモリのマップが最初に一度行われると、その後はアンマップされないという点です。また、これに伴い、AWE で割り当てたメモリ上に置くことのできるデータには、前述の 32-bit の場合のような制限がなくなります。
大きな物理メモリが搭載されている環境、例えば、32GB の物理メモリがあるサーバーであれば、32-bit バージョンの SQL Server で AWE を有効にするのと、64-bit SQL Server を動かすのは同等であると理解している人がいますが、以上のとおり、それは全くの誤解です。
長くなってきたので、今回はこのあたりで終了します。次回は、Memory Manager についてです。
Comments
Anonymous
May 26, 2011
待ってました。楽しみにしています。 昨日には気づいていましたが、コメントできず…。Anonymous
May 26, 2011
>SQL Server のメ���リ管理の第 3 回目です。 先頭の「モ」のところだけ化けている気がする。Anonymous
May 26, 2011
上記内容に至って欲しいと、1回目から期待してました。 32bit OSは4GBまでのメモリしか搭載できないでしょ? という話をするエンジニアによく困り果ててます。(大抵先輩ですが…。) アドレス空間は2GBまでだから…とかいろいろ語られるのですが、 Windows サーバー 2003の32bitマシンで4GBを超えるメモリを見せてもなんら気持ちが変わらないようで。 (そんな時に、SQLの説明をしても…。) 掲載された趣旨とは違うとは思いますが、いろいろすっきりしました。 私もまだまだ良くわかってないのでちゃんと理解できるようにがんばります。 AWE API で拡張するサンプルなんかが出てこないかうきうきしてますが、趣旨が違いますね。 ありがとうございます!Anonymous
May 26, 2011
指摘ありがとうございます。ただ、手元の IE8 で見る限りは特に文字化けはしていないので、ブラウザ依存の問題かもしれませんね。Anonymous
May 26, 2011
AWE API 自体の話になると、SQL Server という範疇ではなくなってしまうので、この Blog にはそぐわないかと思いますが、AWE API セットは API 自体の数が少なく、使用方法も非常にシンプルです。 基本的に MEM_PHYSICAL 指定の VirtualAlloc で仮想アドレス空間をアロケートし、AllocateUserPhysicalPages で物理メモリをアロケートしてしまえば、あとは、必要に応じて、MapUserPhysicalPages で map/unmap を行うだけです。実際にアプリケーションで使おうと思った場合に重要になるのは、物理メモリ上のどこにどのようなデータを置いたのかをうまく管理する点でしょうか。Anonymous
May 26, 2011
ありがとうございます。 文字化けは直っているようです。Anonymous
May 26, 2011
おおっ、AWE APIも語っていただきありがとうございます。得した気分です。 ありがとうございます。Anonymous
June 13, 2011
SQL Server のメモリ管理 - Part 1 ~ 4 blogs.msdn.com/.../sql-server-part-1.aspx blogs.msdn.com/.../sql-server-part-2.aspx blogs.msdn.com/.../sql-server-part-3.aspx blogs.msdn.com/.../sql-server-part-4.aspxAnonymous
October 17, 2011
SQLServer2008 x64 の環境で「バッファ プールで使用できるメモリが不足しています」という事象が発生しています。再起動しても1週間ほどで発生。もしかしたら、AWEの設定を行なっていないことが原因なのでしょうか? 本格的に稼働し出して3ヶ月が経過し、この1ヶ月に2回発生。腑に落ちない状況です。