オンライン インデックス操作の動作原理
このトピックでは、オンライン インデックスの操作中に存在する構造を定義し、これらの構造に関連した利用方法について説明します。
オンライン インデックスの構造
インデックス DDL (データ定義言語) の操作中に同時ユーザー操作を可能にするために、オンライン インデックスの操作中に、ソースと既存のインデックス、ターゲット、クラスタ化インデックス向けの一時マッピング インデックスなどの構造が使用されます。
ソースと既存のインデックス
ソースとは、元のテーブルまたはクラスタ化インデックス データです。既存のインデックスとは、ソース構造に関連付けられた任意の非クラスタ化インデックスです。たとえば、オンライン インデックス操作によって、関連付けられた 4 つの非クラスタ化インデックスを含むクラスタ化インデックスが再構築される場合、ソースは既存のクラスタ化インデックスで、既存のインデックスは非クラスタ化インデックスです。
同時実行ユーザーは、選択、挿入、更新、および削除の各操作に、既存のインデックスを使用できます。既存のインデックスを使用する操作には、トリガや参照整合性制約による、一括挿入や暗黙の更新が含まれます (一括挿入は、サポートされますが、お勧めしません)。クエリや検索では、すべての既存のインデックスを使用できます。つまり、クエリ オプティマイザでは既存のインデックスが選択され、必要に応じて、それをインデックス ヒントに指定できます。
ターゲット
ターゲットとは、作成または再構築される、新しいインデックス (または、ヒープ) です。ユーザーによるソースへの挿入、更新、削除の各操作は、インデックス操作中、SQL Server データベース エンジンによってターゲットに適用されます。たとえば、オンライン インデックス操作によってクラスタ化インデックスが再構築される場合、ターゲットは再構築されるクラスタ化インデックスです。データベース エンジンでは、クラスタ化インデックスが再構築されるときは、非クラスタ化インデックスは再構築されません。
SELECT ステートメントの処理中には、インデックス操作がコミットされるまでターゲット インデックスは検索されません。内部的には、インデックスは書き込み専用に設定されます。
一時マッピング インデックス
クラスタ化インデックスを作成、削除、または再構築するオンライン インデックス操作では、一時マッピング インデックスも必要になります。基になるテーブルの行が更新または削除されるときに、構築される新しいインデックスのどのレコードを削除するかを決めるために、同時実行トランザクションによってこの一時インデックスが使用されます。新しいクラスタ化インデックス (またはヒープ) と同じ手順で、この非クラスタ化インデックスが作成されます。また、個別の並べ替え操作は必要ありません。同時実行トランザクションでは、挿入、更新、削除の各操作のすべての一時マッピング インデックスもメンテナンスされます。
オンライン インデックスでの処理
インデックスが設定されていないテーブル (ヒープ) にクラスタ化インデックスを作成する場合など、単純なオンライン インデックス操作中は、ソースとターゲットは準備、構築、最終工程の 3 つのフェーズで処理されます。
次の図に、初期クラスタ化インデックスをオンラインで作成する処理を示します。ソース オブジェクト (ヒープ) には、他のインデックスはありません。各フェーズでのソースとターゲットの利用状況が示されています。また、同時実行ユーザーによる選択、挿入、更新、削除の各操作についても示されています。準備、構築、最終工程の各フェーズは、フェーズで使用されるロック モードと共に示されています。
ソース構造での処理
次の表に、インデックス操作と対応するロック操作の各フェーズ中に、ソース構造に関係する処理を一覧します。
フェーズ |
ソースでの処理 |
ソースのロック |
---|---|---|
準備 非常に短いフェーズ |
新しい空のインデックス構造を作成するための、システム メタデータの準備。 テーブルのスナップショットが定義されます。つまり、トランザクションレベルの読み取りの一貫性を提供するために、行のバージョン管理が使用されます。詳細については、「行のバージョン管理に基づく分離レベルについて」を参照してください。 ごく短期間、ソース上での同時実行ユーザーの書き込み操作がブロックされます。 複数の非クラスタ化インデックスの作成を除き、同時実行 DDL 操作は許可されません。 |
テーブルで S (共有) * IS (インテント共有) INDEX_BUILD_INTERNAL_RESOURCE** |
構築 メイン フェーズ |
一括読み込み操作で、データのスキャン、並べ替え、マージが行われ、ターゲットに挿入されます。 同時実行ユーザーの選択、挿入、更新、削除の各操作は、既存のインデックスと新しく構築されるインデックスの両方に適用されます。 |
IS (インテント共有) INDEX_BUILD_INTERNAL_RESOURCE** |
最終工程 非常に短いフェーズ |
コミットされていないすべての更新トランザクションは、このフェーズが始まる前に完了している必要があります。取得したロックによっては、このフェーズが完了するまでのごく短期間、新しいユーザーによる読み取りトランザクションや書き込みトランザクションはすべてブロックされます。 ソースをターゲットに置き換えるために、システム メタデータが更新されます。 必要に応じて、ソースが削除されます。たとえば、クラスタ化インデックスを再構築したり、削除した後などにはソースが削除されます。 |
INDEX_BUILD_INTERNAL_RESOURCE** 非クラスタ化インデックスを作成する場合、テーブルで S (共有)。* ソース構造 (インデックスやテーブル) が削除される場合、SCH-M (スキーマ変更)。* |
* インデックス操作は、テーブルに S ロックまたは SCH-M ロックを取得する前に、コミットされていない更新トランザクションが完了するまで待機します。
** リソース ロック INDEX_BUILD_INTERNAL_RESOURCE により、インデックス操作の実行中に、ソースと既存の各構造で同時実行 DDL 操作を実行できなくなります。たとえばこのロックにより、同じテーブルで 2 つのインデックスの再構築を同時実行できなくなります。このリソース ロックは Sch-M ロックと関連付けられていますが、データ操作ステートメントを実行できなくすることはできません。
上記の表は、1 つのインデックスに関係するオンライン インデックス操作の構築フェーズ中に 1 つの共有 (S) ロックが取得されることを示しています。クラスタ化インデックスや非クラスタ化インデックスが構築されるときは、構築フェーズ中に 1 つのオンライン インデックス操作 (たとえば、1 つ以上の非クラスタ化インデックスを含むテーブルでの最初のクラスタ化インデックスの作成中など) で、短期間 2 つの共有 (S) ロックが取得された後、長期間 IS ロックが取得されます。最初に、クラスタ化インデックスの作成のために 1 つの S ロックが取得され、クラスタ化インデックスの作成完了時に、非クラスタ化インデックスの作成のために 2 番目の S ロックが短期間取得されます。非クラスタ化インデックスが作成された後、オンライン インデックス操作の最終フェーズまで、S ロックが IS ロックにダウングレードされます。
ターゲット構造での処理
次の表に、インデックス操作と対応するロック操作の各フェーズ中に、ターゲット構造に関係する処理を一覧します。
フェーズ |
ターゲットでの処理 |
ターゲットのロック |
---|---|---|
準備 |
新しいインデックスが作成され、書き込み専用に設定されます。 |
IS (インテント共有) |
構築 |
ソースからデータが挿入されます。 ソースに適用されたユーザーの変更 (挿入、更新、削除) が適用されます。 この処理は、ユーザーが意識することはありません。 |
IS (インテント共有) |
最終工程 |
インデックス メタデータが更新されます。 インデックスが、読み取りと書き込みが可能な状態に設定されます。 |
共有 (S) または SCH-M (スキーマ変更) |
インデックス操作が完了するまでは、ユーザーによって実行された SELECT ステートメントがターゲットにアクセスすることはありません。
準備フェーズと最終工程フェーズが完了した後は、プロシージャ キャッシュに格納されたクエリ プランと更新プランは無効になります。後続のクエリでは、新しいインデックスが使用されます。
オンライン インデックス操作に関係するテーブルで宣言されたカーソルの有効期間は、オンライン インデックス フェーズによって制限されます。更新カーソルは各フェーズで無効になります。読み取り専用カーソルは、最終工程フェーズの後にのみ無効になります。