Multi Page Allocatorとは
内部コンポーネントが必要とするメモリは、8KBを超えるメモリが必要となる場合があります。例えば複雑なクエリはクエリプランも複雑になり、そのプランをキャッシュするために8KBを超えるメモリが必要となる場合があります。内部コンポーネントがメモリマネージャに 8KBを超えるメモリを要求した場合、バッファプールから割り当てはおこなわれません。この場合はMulti Page Allocatorと呼ばれるコンポーネントを使用します。Multi Page AllocatorはVirtualAlloc APIを使用してメモリを獲得して、コンポーネントに割り当てます。
Multi Page AllocatorがVirtualAlloc APIでメモリを獲得するときは64KBの単位でおこないます。内部コンポーネントが16KBのメモリを必要とする場合は、メモリを64KBを獲得してそのうちの16KBを内部コンポーネントに割り当てます。64KBのメモリは Multi Page Allocatorによって管理されており、他の内部コンポーネントがメモリを必要とした場合、64KBのメモリに空いている領域がある場合、そこから割り当てをおこないます。そして 64KBのブロックのすべての領域が使用されなくなった時にVirtualFree APIを使用してすぐに解放されます。ここがバッファプールと異なる点で、バッファプールのように獲得したメモリを再利用するようなことはありません。
バッファ プールとMulti Page AllocatorはVirtualAlloc APIを使用してメモリを獲得します。 NUMAアーキテクチャの場合、バッファプールは獲得したメモリがローカルメモリかリモートメモリかをチェックしています。リモートメモリの場合、リモートメモリの本来のノードのaway listで管理し、バッファプールが拡張される時に解放します。こうすることで本来のノードで獲得が行われるようにします。
Multi Page Allocatorは獲得したメモリがローカルメモリかリモートメモリかをチェックしません。VirtualAlloc APIつまりOSに依存していて、バッファプールのようなNUMAに対応するメモリ管理の仕組みはないのです。
また、バッファプールはAWEメモリを使用する場合や64bit環境でLocked pages in memory OS特権を設定している場合、それぞれデータベースページのキャッシュに使用されるメモリやバッファプールのメモリの獲得にAWEのAPIを使用します。バッファプールがAWE APIを使用する場合でもMulti Page Allocatorは常にVirtualAlloc APIを使用します。
* * *
ご紹介してきたようにSQL Serverのメモリ管理は、バッファプールとMulti Page Allocatorの異なるコンポーネントによって行われています。どちらも似たような機能をもちながら、そのメカニズムは異なっています。Denaliでは8KBと8KBを超えるメモリで異なるメカニズムを使用するのではなく、メモリマネージャのアーキテクチャを変更して全てのサイズのメモリ管理を同じメカニズムで行うようになります。それによりリソースガバナーは全てのサイズのメモリを制御できるようになります。また‘max server memory’もバッファプール以外のメモリを制御できるようになります。そのアーキテクチャについて早速ご紹介したいところですが、次回までお待ちください。