次の方法で共有


メモリ管理アーキテクチャ ガイド

適用対象: SQL Server Azure SQL データベース Azure SQL Managed Instance Azure Synapse Analytics Analytics Platform System (PDW)

Windows 仮想メモリ マネージャー

Windows 仮想メモリ マネージャー (VMM) は、使用可能な物理メモリにコミット済みのアドレス空間をマップします。

さまざまなオペレーティング システムでサポートされている物理メモリ量の詳細については、Windows のマニュアルの「Windows のリリース別のメモリ制限」を参照してください。

仮想メモリ システムでは、仮想メモリと物理メモリの比率が 1:1 を超えるような物理メモリの設定を許可しています。 その結果、さまざまな物理メモリ構成のコンピューターで大規模なプログラムを実行できます。 しかし、すべてのプロセスの平均ワーキング セットを合わせた容量よりもはるかに大きな仮想メモリを使用すると、パフォーマンスが低下する可能性があります。

SQL Server のメモリ アーキテクチャ

SQL Server では、メモリの確保と解放が必要に応じて動的に行われます。 通常、管理者が SQL Server に割り当てるメモリ量を指定する必要はありませんが、このオプションは一部の環境で必要になるので存在しています。

ディスクの読み書きはコンピューター操作の中でも特にリソースを消費するので、どのようなデータベース ソフトウェアでも、ディスク I/O を最小限に抑えることを主な設計目標としています。 SQL Server では、データベースから読み取ったページを保持するバッファー プールがメモリ内に構築されます。 SQL Server のコードの大部分はディスクとバッファー プールの間の物理的な読み書きの回数が最も少なくなるように記述されています。 SQL Server では次の 2 つの目標のバランスを取ることを目指しています。

  • システム全体のメモリ不足を防ぐため、バッファー プールが大きくなりすぎないようにする。
  • バッファー プールのサイズを最大にして、データベース ファイルの物理 I/O を最小限に抑える。

負荷の高いシステムでは、実行に大量のメモリを必要とする大きなクエリが必要最低限のメモリ量を確保できず、メモリ リソースの待機中にタイムアウト エラーが発生することがあります。 これを解決するには、 query wait オプションの値を増やします。 並列クエリの場合は、 max degree of parallelism オプションの値を減らすことを検討してください。

メモリ不足で負荷の高いシステムでは、クエリ プランにマージ結合、並べ替え、およびビットマップを使用したクエリが含まれていると、クエリがビットマップに必要な最低限のメモリ量を確保できなかった場合に、ビットマップが削除されることがあります。 この動作がクエリのパフォーマンスに影響を与える場合があります。そのために並べ替え処理がメモリに収まらなくなったときに、tempdb データベース内の作業テーブルの使用率が増加し、tempdb が増大する可能性があります。 この問題を解決するには、物理メモリを追加するか、より実行速度の速い別のクエリ プランを使用するようにクエリをチューニングします。

従来の (仮想) メモリ

すべての SQL Server エディションは、64 ビット プラットフォームで従来のメモリをサポートしています。 SQL Server プロセスは、x64 アーキテクチャ上のオペレーティング システムの最大の仮想アドレス空間にアクセスできます (SQL Server Standard Edition では最大 128 GB がサポートされます)。 IA64 アーキテクチャでは、制限は 7 TB でした (IA64 は SQL Server 2012 (11.x) 以降のバージョンではサポートされていません)。 詳細については、「Windows の メモリ制限」に関する記事をご覧ください。

アドレス ウィンドウ拡張機能 (AWE) メモリ

アドレス ウィンドウ拡張機能 (AWE) と AWE で必要なメモリ内のページのロック (LPIM) 特権を使用すると、仮想メモリが少ない状況の場合に SQL Server プロセス メモリの大部分を物理 RAM にロックしたままにすることができます。 これは、32 ビットと 64 ビットの両方の AWE 割り当てで起こります。 メモリのロックは、AWE メモリがメモリのページングを制御する Windows の仮想メモリ マネージャーを経由しないために発生します。 AWE メモリ割り当て API には、メモリ内のロック ページ (SeLockMemoryPrivilege) 権限が必要です。「AllocateUserPhysicalPages」の注意事項を参照してください。 したがって、AWE API を使用する主な利点は、システムのメモリ負荷がある場合に、ほとんどのメモリを RAM に保持することができることです。 SQL Server で AWE を使用できるようにする方法については、「Lock Pages in Memory オプションの有効化 (Windows)」を参照してください。

LPIM 権限が付与されている場合は、既定の 2,147,483,647 メガバイト (MB) のままにするのではなく、[max server memory (MB)] を特定の値に設定することを強くお勧めします。 詳細については、「サーバー メモリの構成オプション」および「メモリ内のページのロック (LPIM)」に関するページを参照してください。

LPIM が有効になっていない場合、SQL Server は従来のメモリの使用に切り替わり、OS メモリ不足の場合は [MSSQLSERVER_17890] エラー (errors-events/mssqlserver-17890-database-engine-error.md) がエラー ログに報告される可能性があります。 エラーは、次の例のようになります。

A significant part of SQL Server process memory has been paged out. This may result in a performance degradation. Duration: #### seconds. Working set (KB): ####, committed (KB): ####, memory utilization: ##%.

SQL Server 2012 以降のメモリ管理の変更

SQL Server の以前のバージョンでは、5 つの異なるメカニズムを利用してメモリが割り当てられていました。

  • SPA (Single-Page Allocator/単一ページ アロケータ)。SQL Server プロセスで 8 KB 以下のメモリ割り当てのみが含まれます。 構成オプションの max server memory (MB)min server memory (MB) によって、SPA が利用する物理メモリの上限が決められていました。 同時にバッファー プールが SPA のメカニズムであり、これが単一ページ割り当てを最も多く利用していました。
  • MPA (Multi-Page Allocator/複数ページ アロケータ)。8 KB より多くを要求するメモリ割り当て用。
  • CLR アロケータ。CLR 初期化中に作成される SQL CLR ヒープとそのグローバル割り当てを含む。
  • SQL Server プロセスの スレッド スタックのメモリ割り当て。
  • DWA (Direct Windows allocations/直接 Windows 割り当て)。Windows に直接行われるメモリ割り当て要求。 モジュールによって行われ、SQL Server プロセスに読み込まれる、Windows のヒープ使用量と直接仮想割り当てが含まれます。 このようなメモリ割り当ての例としては、たとえば、拡張ストアド プロシージャ DLL からの割り当て、オートメーション プロシージャ (sp_OA 呼び出し) で作成されたオブジェクト、リンク サーバー プロバイダーからの割り当てがあります。

SQL Server 2012 (11.x) 以降、SPA、MPA、CLR 割り当てがすべて統合され、"あらゆるサイズの" ページ アロケータになります。これは、構成オプションの max server memory (MB)min server memory (MB) によって制御されるメモリ上限に含まれます。 この変更によって、SQL Server メモリ マネージャーを通過するすべてのメモリ要件において、より正確にサイズを調整できるようになりました。

重要

SQL Server 2012 (11.x) 以降のバージョンにアップグレードしたら、現在の max server memory (MB)min server memory (MB) の構成を注意深く見直してください。 これは、SQL Server 2012 (11.x) 以降は、以前のバージョンに比べ、このような構成に含まれるメモリ割り当てが多くなっているためです。 これらの変更は、SQL Server 2012 (11.x) と SQL Server 2014 (12.x) の 32 ビット バージョンと 64 ビット バージョンの両方、および SQL Server 2016 (13.x) 以降のバージョンの 64 ビット バージョンに適用されます。

次の表は、メモリ割り当ての種類とそれを制御する構成オプションである max server memory (MB)min server memory (MB) についてまとめたものです。

メモリ割り当ての種類 SQL Server 2005 (9.x)、SQL Server 2008 (10.0.x)、および SQL Server 2008 R2 (10.50.x) SQL Server 2012 (11.x) 以降
単一ページ割り当て はい はい。"あらゆるサイズの" ページ割り当てに統合。
複数ページ割り当て いいえ はい。"あらゆるサイズの" ページ割り当てに統合。
CLR 割り当て いいえ はい
スレッド スタック メモリ いいえ いいえ
Windows からの直接割り当て いいえ いいえ

SQL Server は、最大サーバー メモリ設定を超えてメモリをコミットする可能性があります

SQL Server 2012 (11.x) 以降、SQL Server は、max server memory (MB) 設定に指定されている値よりも多いメモリを割り当てる場合があります。 そのような動作は、Total Server Memory (KB) の値が、max server memory (MB) によって指定される Target Server Memory (KB) の設定に既に到達しているときに発生することがあります。 メモリの断片化によって、複数ページ メモリ要求 (8 KB 超) の需要を満たすだけの連続した空き容量がない場合、SQL Server はメモリ要求を拒否せず、オーバーコミットを実行できます。

この割り当ての実行直後、バックグラウンド タスクのリソース モニターがすべてのメモリ コンシューマーに割り当てられたメモリを解放するよう信号を送り始め、Total Server Memory (KB) Target Server Memory (KB) 仕様を下回るようにします。 そのため、SQL Server のメモリ使用量が max server memory (MB) 設定を一時的に超えることがあります。 このような状況では、Total Server Memory (KB) パフォーマンス カウンター読み取り値が max server memory (MB) 設定と Target Server Memory (KB) 設定を超えます。

この動作は通常、次の操作中に観察されます。

  • 大規模な列ストア インデックス クエリ
  • 大規模な行ストアでのバッチ モード クエリ
  • 列ストア インデックスの (再) ビルド。大量のメモリを使用し、ハッシュ操作とソート操作を実行します。
  • 大量のメモリ バッファーを必要とするバックアップ操作。
  • 大量の入力パラメーターを格納する必要があるトレース操作。
  • 大きなメモリ許可要求

この動作が頻繁に発生する場合は、sSQL Server 2019 (15.x) で トレース フラグ 8121 を使用して、リソース モニターをより迅速にクリーンアップすることを検討してください。 SQL Server 2022 (16.x) 以降、この機能は既定で有効になり、トレース フラグ は無効になります。

SQL Server 2012 以降の memory_to_reserve への変更

以前のバージョンの SQL Server では、SQL Server メモリ マネージャーは、複数ページ アロケータ (MPA)CLR アロケータ、SQL Server プロセスのスレッド スタックのメモリ割り当て、直接 Windows 割り当て (DWA) で使用するために、プロセス VAS (Virtual Address Space/仮想アドレス空間) の一部を予約しました。 仮想アドレス空間のこの部分は、"Mem-To-Leave" または "non-Buffer Pool" 領域とも呼ばれています。

このような割り当てのために予約される仮想アドレス空間は、構成オプションの memory_to_reserve によって決定されます。 SQL Server で使用される既定値は 256 MB です。

"あらゆるサイズの" ページ アロケータは 8 KB を超える割り当ても処理するため、memory_to_reserve 値には複数ページ割り当てが含まれません。 この変更を除き、他のすべてはこの構成オプションと引き続き同じになります。

次の表は、特定の種類のメモリ割り当てが SQL Server プロセスの仮想アドレス空間の Memory_to_reserve 領域に該当するかどうかを示しています。

メモリ割り当ての種類 SQL Server 2005 (9.x)、SQL Server 2008 (10.0.x)、および SQL Server 2008 R2 (10.50.x) SQL Server 2012 (11.x) 以降
単一ページ割り当て いいえ いいえ。"あらゆるサイズの" ページ割り当てに統合。
複数ページ割り当て はい いいえ。"あらゆるサイズの" ページ割り当てに統合。
CLR 割り当て はい はい
スレッド スタック メモリ はい はい
Windows からの直接割り当て はい はい

動的メモリ管理

SQL Server データベース エンジンの既定のメモリ管理動作では、システムでメモリ不足を発生させることなく、必要な量のメモリを獲得します。 SQL Server データベース エンジンでは、Microsoft Windows の Memory Notification API を使用してこれを実現しています。

メモリを動的に使用する場合、SQL Server はシステムに定期的にクエリして、メモリの空き容量を確認します。 このようにメモリの空き容量を維持することによって、オペレーティング システム (OS) のページングが防止されます。 空きメモリが少ない場合、SQL Server は OS に対してメモリを解放します。 空きメモリが多い場合、SQL Server はより多くのメモリを割り当てることができます。 SQL Server によってメモリが追加されるのは、ワークロードが高いためにメモリを増やす必要がある場合だけです。アクティブでないサーバーの仮想アドレス空間のサイズは増えません。 SQL Server が動的メモリ管理を使用しているときに、タスク マネージャーとパフォーマンス モニターで使用可能なメモリが少しずつ減少している場合は想定される動作とし、メモリ リークとして認識されるべきではありません。

サーバー メモリの構成オプションは、SQL Server のメモリ割り当て、コンパイル メモリ、すべてのキャッシュ (バッファー プールを含む)、クエリ実行メモリ許可ロック マネージャー メモリ、CLR1 メモリ (基本的に、sys.dm_os_memory_clerks で見つかったメモリ クラーク) を制御します。

SQL Server 2012 (11.x) 以降、1 CLR メモリは max_server_memory 割り当ての下で管理されます。

次のクエリでは、現在割り当てられているメモリに関する情報を返します。

SELECT physical_memory_in_use_kb / 1024 AS sql_physical_memory_in_use_MB,
       large_page_allocations_kb / 1024 AS sql_large_page_allocations_MB,
       locked_page_allocations_kb / 1024 AS sql_locked_page_allocations_MB,
       virtual_address_space_reserved_kb / 1024 AS sql_VAS_reserved_MB,
       virtual_address_space_committed_kb / 1024 AS sql_VAS_committed_MB,
       virtual_address_space_available_kb / 1024 AS sql_VAS_available_MB,
       page_fault_count AS sql_page_fault_count,
       memory_utilization_percentage AS sql_memory_utilization_percentage,
       process_physical_memory_low AS sql_process_physical_memory_low,
       process_virtual_memory_low AS sql_process_virtual_memory_low
FROM sys.dm_os_process_memory;

スタック サイズ

スレッド スタック 1 のメモリ、CLR 2、拡張プロシージャ .dll ファイル、分散クエリで参照される OLE DB プロバイダー、 ステートメントで参照されるオートメーション オブジェクト、非 DLL で割り当てられるメモリは max server memory で制御されません

1 現在のホストで関連付けられている所与の CPU 数に対して計算される既定のワーカー スレッドについては、max worker threads (サーバー構成オプション) の構成方法に関する記事を参照してください。 SQL Server のスタックのサイズは次のようになります。

SQL Server アーキテクチャ OS アーキテクチャ スタック サイズ
x86 (32 ビット) x86 (32 ビット) 512 KB
x86 (32 ビット) x64 (64 ビット) 768 KB
x64 (64 ビット) x64 (64 ビット) 2,048 KB
IA64 (Itanium) IA64 (Itanium) 4,096 KB

SQL Server 2012 (11.x) 以降、2 CLR メモリは max_server_memory 割り当ての下で管理されます。

SQL Server は、メモリ通知 API QueryMemoryResourceNotification を使用して、いつ SQL Server Memory Manager がメモリの割り当てと解放ができるかを決定します。

SQL Server を起動すると、システムの物理メモリの量、サーバー スレッドの数、さまざまな起動パラメーターなど、いくつかのパラメーターに基づいてバッファー プール用の仮想アドレス空間のサイズが計算されます。 SQL Server では、計算された量のプロセス仮想アドレス空間をバッファー プール用に予約しますが、現在の負荷に必要な量だけ物理メモリを獲得 (コミット) します。

インスタンスでは、ワークロードのサポートに必要なメモリを獲得し続けます。 接続してクエリを実行するユーザーが増える、SQL Server はオンデマンドでより多くの物理メモリを取得します。 SQL Server インスタンスでは、max server memory (MB) の割当量に達するか、または OS が過剰なメモリ不足になったことを示すまで、物理メモリを獲得し続けます。獲得したメモリの量が min server memory 設定よりも多く、OS によって空きメモリの不足が示されると、メモリが解放されます。

SQL Server のインスタンスが動作しているコンピューター上で他のアプリケーションを起動すると、メモリを消費し、物理メモリの空き領域が SQL Server の目標よりも少なくなります。 SQL Server のインスタンスでは、メモリの消費を調整します。 他のアプリケーションが停止され、使用可能なメモリが増えると、SQL Server のインスタンスはメモリ割り当てのサイズを大きくします。 SQL Server は、数 MB のメモリの解放および獲得を毎秒行うことができるため、メモリ割り当ての変更に迅速に対応できます。

最小および最大サーバー メモリの効果

構成オプションの min server memorymax server memory によって、 データベース エンジンのバッファー プールとその他のキャッシュで使用されるメモリ量の上限と下限が決められます。 バッファー プールは、min server memory に指定されたメモリ容量をすぐには獲得しません。 バッファー プールは、初期化に必要なメモリのみで起動します。 SQL Server データベース エンジンのワークロードが増えるにしたがって、そのワークロードに対応するために必要なメモリを獲得し続けます。 バッファー プールは、min server memory で指定しされたメモリ容量に達するまでは獲得したメモリを解放しません。 メモリ容量が min server memory に達すると、バッファー プールは標準アルゴリズムを使用して、必要に応じてメモリ容量を獲得または解放します。 唯一の違いは、バッファー プールはそのメモリ割り当てを min server memory の値よりも下回るメモリ容量にはせず、max server memory (MB) の値を超えるメモリ容量は獲得しないということです。

Note

プロセスとしての SQL Server は、max server memory (MB) オプションで指定された容量を超えるメモリを獲得します。 内部コンポーネントも外部コンポーネントも、バッファー プール外にメモリ容量を割り当てることができます。この場合は、メモリ容量が余分に消費されますが、通常、SQL Server によって消費されるメモリ容量の最大部分は、バッファー プールに割り当てられたメモリ容量が占めます。

SQL Server データベース エンジンが獲得するメモリ容量は、そのインスタンスのワークロードに完全に依存します。 多くの要求を処理しない SQL Server インスタンスでは、min server memory が指定する値にまったく達しないこともあります。

min server memory と max server memory (MB) の両方に同じ値を指定した場合、SQL Server データベース エンジンに割り当てられたメモリがその値に達すると、SQL Server データベース エンジンはバッファ プール用のメモリの動的解放と取得を停止します。

他のアプリケーションが頻繁に停止または起動されるコンピュータ上で SQL Server のインスタンスが動作している場合、SQL Server のインスタンスによるメモリの割り当てと解放により、他のアプリケーションの起動時間が遅くなることがあります。 SQL Server が、1 つのコンピューター上で動作している複数のサーバー アプリケーションのうちの 1 つであるときも、SQL Server に割り当てるメモリ量をシステム管理者が制御しなければなりません。 このような場合には、min server memory オプションと max server memory (MB) オプションを使用して、SQL Server が使用するメモリ量を制御できます。 min server memorymax server memory は MB 単位で指定されます。 これらのメモリ構成の設定方法に関する推奨事項などの詳細については、「サーバー メモリの構成オプション」を参照してください。

SQL Server オブジェクトの仕様で使用されるメモリ

次の一覧で、SQL Server の各オブジェクトによって使用されるおおよそのメモリ量について説明します。 表示されている金額は概算であり、環境とオブジェクトの作成方法によって異なります。

  • ロック (ロック マネージャーにより保守管理): 64 バイト + 32 バイト (所有者あたり)
  • ユーザー接続: 約 (3 * network_packet_size + 94 KB)

ネットワーク パケット サイズは、アプリケーションと データベース エンジン間の通信に使用される表形式のデータ スキーム (TDS) パケットのサイズです。 既定のパケット サイズは 4 KB であり、network packet size 構成オプションによって制御されます。

複数のアクティブな結果セット (MARS) が有効になっている場合、ユーザー接続で使用されるメモリは、約 (3 + 3 * num_logical_connections) * network_packet_size + 94 KB になります。

min memory per query の効果

min memory per query 構成オプションでは、クエリの実行用に割り当てる最小メモリ容量 (KB 単位) を確定します。 これは、最小メモリ許可とも呼ばれます。 すべてのクエリは、実行を開始するためには、要求された最小メモリをセキュリティで保護できるようになるまで、または query wait サーバー構成オプションで指定された値を超えるまで、待機する必要があります。 このシナリオで累積される待機の種類は、RESOURCE_SEMAPHORE です。

重要

稼働率が非常に高いシステムでは特に、min memory per query サーバー構成オプションの値を高く設定しすぎないでください。そうしないと、次のような問題が発生する可能性があります。

  • メモリ リソースの競合が増加します。
  • 実行時に必要なメモリがこの構成より少ない場合でも、すべての単一クエリのメモリ量を増やすことで、コンカレンシーが低下します。

この構成の使い方の推奨事項については、「min memory per query サーバー構成オプションの構成」を参照してください。

メモリ許可に関する考慮事項

行モード実行の場合は、いかなる状況でも初期のメモリ許可を超過することはありません。 ハッシュ操作または並べ替え操作を実行するために、初期のメモリ許可より多くのメモリを必要とする場合、これらの操作はディスクへスピルします。 スピルするハッシュ操作は tempdb のワークファイルによってサポートされ、スピルするソート操作はワークテーブルによってサポートされます。

ソート操作中に発生するスピルは、Sort Warnings イベント クラスと呼ばれています。 ソートワーニングは、ソート操作がメモリに収まらないことを示します。 インデックスの作成を伴うソート操作は含まれません。クエリ内のソート操作 (SELECT ステートメントで使用される ORDER BY 句など) のみが含まれます。

ハッシュ操作中に発生するスピルは、Hash Warning イベント クラスと呼ばれています。 これらは、ハッシュ演算中にハッシュの再帰またはハッシュの中断 (ハッシュの保留) が生じたときに発生します。

  • 使用できるメモリ内にビルド入力が収まらないときに、ハッシュの再帰が発生します。その結果、入力が複数のパーティションに分割され、個別に処理されます。 複数のパーティションに分割されても使用可能なメモリ内に収まらない場合は、さらにサブパーティションに分割され、個別に処理されます。 この分割プロセスは、使用できるメモリ内に各パーティションが収まるようになるまで、または最大再帰レベルに到達するまで続きます。
  • ハッシュ演算が最大再帰レベルに到達するとハッシュの保留が発生し、パーティション分割された残りのデータを処理するための代替プランに移行されます。 これらのイベントが原因となって、サーバー内のパフォーマンスが低下する可能性があります。

バッチ モード実行の場合、初期のメモリ許可は既定では特定の内部しきい値まで動的に増加することができます。 この動的なメモリ許可メカニズムは、バッチ モードで実行されているハッシュまたは並べ替え操作のメモリ常駐実行を可能にするように設計されています。 これらの操作がまだメモリ内に収まらない場合は、ディスクへスピルされます。

実行モードの詳細については、「クエリ処理アーキテクチャ ガイド」を参照してください。

バッファー管理

SQL Server データベースの主な目的はデータの格納と取得であるため、データベース エンジンの主要な特性は頻繁なディスク I/O ということになります。 ディスク I/O 操作は多くのリソースを消費するうえ、完了するのに比較的長い時間がかかるので、SQL Server では I/O の効率を上げることに重点を置いています。 バッファー管理は、この効率向上を実現するための重要なコンポーネントです。 バッファー管理コンポーネントは 2 つのメカニズムから構成されています。1 つはデータベース ページに対するアクセスと更新を行うバッファー マネージャーで、もう 1 つはデータベース ファイルの I/O を削減するバッファー キャッシュ (バッファー プール) です。

SQL Server のディスク I/O の詳細な説明については、「SQL Server I/O の基礎」を参照してください。

バッファー管理のしくみ

バッファーはメモリ内の 8 KB のページで、データ ページやインデックス ページと同じサイズです。 したがって、バッファー キャッシュは 8 KB 単位のページに分割されます。 バッファー マネージャーは、データベース ディスク ファイルのデータ ページやインデックス ページをバッファー キャッシュに読み取って、変更されたページをディスクに書き戻すための機能を管理しています。 バッファー マネージャーが別のデータを読み取るためのバッファー領域を必要とするまで、そのページはバッファー キャッシュ内に残ります。 データに変更が加えられた場合だけ、そのデータがディスクに書き戻されます。 バッファー キャッシュ内のデータは、ディスクに書き戻す前に何度でも変更できます。 詳細については、「 ページの読み取り 」および「 ページの書き込み」をご覧ください。

SQL Server を起動すると、システムの物理メモリの量、構成されるサーバー スレッドの最大数、さまざまな起動パラメーターなど、いくつかのパラメーターに基づいてバッファー キャッシュ用の仮想アドレス空間のサイズが計算されます。 SQL Server では、この計算された量のプロセス仮想アドレス空間 (メモリ ターゲット) をバッファー キャッシュ用に予約しますが、現在の負荷に必要な量だけ物理メモリを獲得 (コミット) します。 sys.dm_os_sys_info カタログ ビューの committed_target_kbcommitted_kb の列に対してクエリを実行すると、メモリ ターゲットとして予約されているページ数と、バッファー キャッシュ内で現在コミットされているページ数をそれぞれ返すことができます。

SQL Server の起動からバッファー キャッシュがメモリ ターゲットを取得するまでの間隔を、割り当て増加といいます。 この間、読み取り要求によって、必要に応じてバッファーが使用されます。 たとえば、1 ページ 8 KB の読み取り要求では、1 つのバッファー ページが使用されます。 つまり、割り当て増加は、クライアント要求の数や種類によって異なります。 1 ページずつの読み取り要求を 8 ページ分の要求にまとめて変換することで (1 つのエクステントとします)、割り当て増加を高速化しています。 これにより、特に多くのメモリが搭載されたコンピューターでは、割り当て増加が非常に高速に完了します。 ページとエクステントの詳細については、「ページとエクステントのアーキテクチャ ガイド」を参照してください。

バッファー マネージャーはほとんどのメモリを SQL Server プロセスで使用するので、メモリ マネージャーと連携して他のコンポーネントでバッファーを使用できるようにします。 バッファー マネージャーは主に次のコンポーネントと対話します。

  • リソース マネージャー。全体的なメモリ使用量を制御します。32 ビット プラットフォームではアドレス空間の使用量を制御します。
  • データベース マネージャーおよび SQL Server オペレーティング システム (SQLOS)。低レベルのファイル I/O 操作を行います。
  • ログ マネージャー。先行書き込みログ記録を行います。

サポートされている機能

バッファー マネージャーは、次の機能をサポートしています。

  • NUMA (non-uniform memory access) に対応しています。 バッファー キャッシュ ページはハードウェア NUMA ノード間に分散されます。そのため、スレッドは外部メモリからではなく、ローカルの NUMA ノードに割り当てられているバッファー ページにアクセスすることができます。

  • ホット アド メモリをサポートしています。そのため、ユーザーはサーバーを再起動することなく物理メモリを追加できます。

  • 64 ビット プラットフォームの大きなページをサポートしています。 ページのサイズは、Windows のバージョンに固有です。

    Note

    SQL Server 2012 (11.x) より前のバージョンでは、SQL Server で大きいページを有効にするにはトレース フラグ 834 が必要です。

  • バッファー マネージャーは、動的管理ビューによって公開される追加の診断情報を提供します。 これらのビューを使用して、SQL Server に固有のさまざまなオペレーティング システム リソースを監視できます。 たとえば、sys.dm_os_buffer_descriptors ビューを使用すると、バッファー キャッシュ内のページを監視できます。

メモリ不足の検出

メモリ不足は、メモリの不足が原因で発生する状態であり、次の結果を招く可能性があります。

  • 余分な I/O の発生 (レイジー ライターの非常にアクティブなバック グラウンド スレッドなど)
  • 再コンパイルの比率が高くなる
  • クエリの実行時間が長くなる (メモリ許可待機が存在する場合)
  • 余分な CPU サイクルが発生する

この状況は、外部的な原因または内部的な原因によって引き起こされる可能性があります。 外部的な原因には次のようなものがあります。

  • 使用可能な物理メモリ (RAM) が不足しています。 これにより、システムは現在実行中のプロセスのワーキング セットをトリミングします。結果として、全体的に速度が低下する可能性があります。 SQL Server はバッファー プールのコミット ターゲットを削減し、内部キャッシュのトリミングを頻繁に開始する可能性があります。
  • 使用できる全体的なシステム メモリ (システムのページ ファイルを含む) が不足しています。 これにより、システムはメモリ割り当てを失敗する場合があります。現在割り当てられているメモリをページ アウトできないためです。

内部的な原因には次のようなものがあります。

  • SQL Server データベース エンジンがメモリ使用量の下限を設定する場合に外部メモリ不足に対応します。
  • max server memory 構成の値を手動で縮小することにより、メモリ設定の値が引き下げられました。
  • 内部コンポーネントによるいくつかのキャッシュ間のメモリ配分に変更が生じました。

SQL Server データベース エンジン では、動的メモリ管理の一環として、メモリ不足の検出および処理のために専用のフレームワークが実装されます。 このフレームワークには、リソース モニターと呼ばれるバックグラウンド タスクが含まれています。 リソース モニター タスクでは、外部および内部のメモリ インジケーターの状態が監視されます。 これらのインジケーターのいずれかの状態が変化すると、対応する通知が計算され、その通知がブロードキャストされます。 これらの通知は各エンジン コンポーネントからの内部メッセージであり、リング バッファーに格納されます。

次の 2 つのリング バッファーに、動的メモリ管理に関連する情報が保持されます。

  • メモリ不足が通知されているかどうかなど、リソース モニターのアクティビティを追跡するリソース モニター リング バッファー。 このリング バッファーには、RESOURCE_MEMPHYSICAL_HIGHRESOURCE_MEMPHYSICAL_LOWRESOURCE_MEMPHYSICAL_STEADY、または RESOURCE_MEMVIRTUAL_LOW の現在の状態に応じたステータス情報が含まれます。
  • 各 Resource Governor リソース プールのメモリ通知のレコードが含まれるメモリ ブローカー リング バッファー。 内部メモリ不足が検出されると、メモリの割り当てを行うコンポーネントに対して、メモリ不足を示す通知がオンになり、キャッシュ間でメモリのバランスをとるためのアクションがトリガーされます。

メモリ ブローカーは、コンポーネントごとにメモリの需要と消費量を監視し、収集した情報に基づいて、これらのコンポーネントの各々に対してメモリの最適な値を算出します。 Resource Governor リソース プールごとにブローカー セットがあります。 この情報は、使用量を必要に応じて拡大または縮小する各コンポーネントにブロードキャストされます。

メモリ ブローカーの詳細については、sys.dm_os_memory_brokers に関するページを参照してください。

エラー検出

データベース ページで 2 つ内いずれかのオプションのメカニズム (破損ページ保護チェックサム保護) を使用して、ページがディスクに書き込まれてから再び読み取られるまでの間、ページの整合性を保証できます。 これらのメカニズムによって、データ ストレージだけでなく、ハードウェア コンポーネント (コントローラー、ドライバー、ケーブルなど)、およびオペレーティング システムに至るまで、個々の正確性を検証するための独立した手段が可能になります。 この保護はディスクに書き込む直前にページに追加され、ディスクから読み取られた後で検証されます。

SQL Server は、チェックサム、破損ページ、またはその他の I/O エラーで読み取りに失敗した場合、その読み取りを 4 回再試行します。 いずれかの再試行で読み取りに成功した場合には、エラー ログにメッセージが書き込まれ、その読み取りを起動したコマンドは続行されます。 再試行が失敗した場合、コマンドは MSSQLSERVER_824 エラーで失敗します。

使用されている種類のページ保護は、ページが含まれているデータベースの属性です。 チェックサム保護は SQL Server 2005 (9.x) 以降のバージョンで作成されたデータベースの既定の保護です。 ページ保護のメカニズムはデータベースの作成時に指定するもので、ALTER DATABASE SET を使用して変更できます。 ページ保護の現在の設定を確認するには、 sys.databases カタログ ビューの page_verify_option 列、または DATABASEPROPERTYEX 関数の IsTornPageDetectionEnabled プロパティをクエリします。

Note

ページ保護の設定が変更されたとき、新しい設定がデータベース全体にすぐに反映されるわけではありません。 個々のページの出力時に、現在のデータベースの保護レベルがそのページに適用されます。 つまり、データベースはそれぞれ保護の種類が異なるページで構成されている場合があります。

破損ページ保護

破損ページ保護は、SQL Server 2000 (8.x) で導入されたもので、主に電源障害によるページ破損を検出する方法です。 たとえば、予期しない電源障害でページの一部だけがディスクに書き込まれた状態になったとします。 破損ページ保護が使用されているとき、ディスクへのページ書き込み時に、8 KB のデータベース ページ内の 512 バイトのセクターごとに、特定の 2 ビット署名パターンがデータベース ページ ヘッダーに格納されます。

そのページがディスクから読み取られるときに、ページ ヘッダーに保存されている各セクターの破損ビットと、実際のページ セクター情報とが比較されます。 書き込みが行われるたびに署名パターンとしてバイナリの 0110 が交互に設定されるので、セクターの一部だけがディスクに書き込まれたときを常に判別することが可能です。つまり、後でページが読み取られたときにビットが正しくない状態の場合、ページが不適切に書き込まれ、破損ページが検出されます。 破損ページ検出で使用されるリソースは最小限です。ただし、ディスクのハードウェア障害が原因で発生したすべてのエラーを検出できるわけではありません。 破損ページ検出の詳細については、「ALTER DATABASE の SET オプション (Transact-SQL)」を参照してください。

チェックサム保護

チェックサム保護は、SQL Server 2005 (9.x) から導入されたもので、今まで以上に強力なデータ整合性チェックを提供します。 チェックサムは各ページに書き込まれるデータから算出され、ページ ヘッダーに書き込まれます。 ページにチェックサムが書き込まれている場合は、そのページをディスクから読み取るたびにデータのチェックサムが再計算されます。そして、新しく計算されたチェックサムと、現在書き込まれているチェックサムが異なる場合は、エラー 824 が生成されます。 チェックサム保護はページの各バイトの影響を受けるので、破損ページ保護よりも多くのエラーをキャッチできますが、使用されるリソースがやや多くなります。

チェックサムが有効になっている場合、電源障害、欠陥のあるハードウェアやソフトウェアが原因で発生するエラーは、バッファー マネージャーがディスクからページを読み取るたびに検出できます。 チェックサム設定の詳細については、「ALTER DATABASE の SET オプション (Transact-SQL)」を参照してください。

重要

ユーザーまたはシステム データベースを SQL Server 2005 (9.x) 以降にアップグレードすると、 PAGE_VERIFY 値 (NONE または TORN_PAGE_DETECTION) が保持されます。 CHECKSUM の使用を強くお勧めします。 TORN_PAGE_DETECTION は、使用するリソースが比較的少なくて済み可能性がありますが、CHECKSUM の保護の最小限のサブセットを提供します。

Non-Uniform Memory Access を理解する

SQL Server は Non-Uniform Memory Access (NUMA) を認識しており、特殊な構成を行わなくても NUMA ハードウェアで適切にパフォーマンスを発揮します。 プロセッサのクロック速度や数が増加するにつれて処理能力が向上しますが、その一方で、向上した能力の活用に必要となるメモリの待機時間を減らすことが困難になります。 ハードウェア ベンダーはメモリの待機時間をなくすために、大容量の L3 キャッシュを搭載していますが、この解決策にも限界があります。 この問題に対する、拡張性に優れた解決方法が NUMA アーキテクチャです。

SQL Server は、アプリケーションを変更しなくても NUMA ベースのコンピュータを活用できるように設計されています。 詳細については、「ソフト NUMA (SQL Server)」を参照してください。

メモリ オブジェクトの動的パーティション

SQL Server では、メモリ オブジェクトと呼ばれるヒープ アロケーターを使用すると、データベース エンジンがヒープからメモリを割り当てることができます。 これらは sys.dm_os_memory_objects DMV を使用して追跡できます。

CMemThread とは、複数のスレッドから同時にメモリを割り当てることを可能にするスレッドセーフなメモリ オブジェクト型です。 追跡を正確に行うために、CMemThread オブジェクトは、同期コンストラクト (ミューテックス) に依存し、一度に 1 つのスレッドのみで重要な情報が確実に更新されるようになっています。

Note

CMemThread オブジェクト型は、データベース エンジン コード ベース全体でさまざまな割り当てに使用され、ノードごとまたは CPU ごとにグローバルに分割することができます。

ただし、ミューテックスを使用すると、多数のスレッドが同じメモリ オブジェクトから同時性の高い方法で割り当てられる場合に競合が発生する可能性があります。 したがって、SQL Server にはパーティション分割されたメモリ オブジェクト (PMO) という概念があり、各パーティションはそれぞれ 1 つの CMemThread オブジェクトによって表されます。 メモリ オブジェクトのパーティション分割は静的に定義され、作成後に変更することはできません。 メモリ割り当てパターンは、ハードウェアやメモリ使用量などの側面に大きく左右されるので、完全なパーティション分割パターンを事前に取得することは不可能です。

ほとんどの場合は、1 つのパーティションを使用するだけで十分ですが、シナリオによっては、高度にパーティション分割されたメモリ オブジェクトのみが回避できる競合が発生する可能性があります。 各メモリ オブジェクトをパーティション分割することは望ましくありません。パーティションが増えると他の非効率性が生じ、メモリの断片化が増す可能性があるからです。

Note

SQL Server 2016 (13.x) より前のバージョンでは、トレース フラグ 8048 を使用して、ノードベースの PMO を強制的に CPU ベースの PMO にすることができました。 注: SQL Server 2014 (12.x) SP2 および SQL Server 2016 (13.x) 以降では、この動作は動的であり、エンジンによって制御されます。

SQL Server 2014 (12.x) SP2 および SQL Server 2016 (13.x) 以降のバージョンでは、データベース エンジンが特定の CMemThread オブジェクトの競合を動的に検出し、そのオブジェクトをノードごと、または CPU ごとに基づく実装に昇格させることができます。 昇格すると、SQL Server プロセスが再開されるまで、PMO は昇格されたままになります。 CMemThread の競合は、sys.dm_os_wait_stats DMV 内に CMEMTHREAD の長い CMEMTHREAD 待機時間が存在すること、および sys.dm_os_memory_objects DMV 列のcontention_factorpartition_typeexclusive_allocations_count、および waiting_tasks_count を観察することで検出できます。