web-dev-qa-db-ja.com

なぜCREATE INDEX ... WITH ONLINE = ONは、数分にわたってテーブルへのアクセスをブロックするのですか?

既存のテーブルがあります:

_CREATE TABLE dbo.ProofDetails
(
    ProofDetailsID int NOT NULL 
        CONSTRAINT PK_ProofDetails 
        PRIMARY KEY CLUSTERED IDENTITY(1,1)
    , ProofID int NULL
    , IDShownToUser int NULL
    , UserViewedDetails bit NOT NULL 
        CONSTRAINT DF_ProofDetails_UserViewedDetails 
        DEFAULT ((0))
);
_

このテーブルには150,000,000行があります。システムは24時間365日稼働しているため、定期的に発生するメンテナンスウィンドウはありません。

テーブルにインデックスを追加したいのですが、SQL ServerのEnterpriseエディションでは、テーブルへの書き込みアクセスをブロックせずにそれを実行できるはずです。私が使用したコマンドは:

_CREATE INDEX IX_ProofDetails_ProofID_Etc 
ON dbo.ProofDetails (ProofID, IDShownToUser)
INCLUDE (UserViewedDetails)
WITH (ONLINE=ON
    , ALLOW_ROW_LOCKS=ON
    , ALLOW_PAGE_LOCKS=ON
    , FILLFACTOR=100
    , MAXDOP=4
);
_

SSMSでステートメントを単独で実行しました。 F5。 1分以上実行された後、他のセッションをブロックし始めました。他のセッションをブロックできないため、すぐに_CREATE INDEX_コマンドをキャンセルしました。

最初の1分間は、_CREATE INDEX_コマンドをブロックしているものは何もありませんでした。_sys.dm_exec_requests_は、CXPACKETの待機タイプのプロセスを示しています-もちろんです。操作が並列化されているので、それは悪いことではないと思います。

_sys.dm_exec_requests_の出力を調べる時間はあまりありませんでした。クエリ_WHERE session_id = xxx_から返された行は1つだけでした。ブロックされたセッションがターゲットテーブルに行を挿入しようとしました。

ロックの持続時間はわかりませんが、ステートメントの開始から約2分後にステートメントの実行をキャンセルしたことを除きます。その時点で約1分間ブロックが発生していました。

WITH (ONLINE=ON)の実装を誤解していますか?または、他に知っておく必要があることはありますか?

サーバーはかなり頑丈なマシンであり、2つのクアッドコアXeon E5-2643 3.3Ghzプロセッサー、192GB RAM、およびSAN 5,000+ iopsに対応できるストレージ。CPUは通常20%未満、= RAMは、ほとんどがSQL Serverによって93%使用されています。WindowsServer 2012とSQL Server 2012だけで、他に何も実行されていません。

24
Max Vernon

Online = onでインデックスを作成する場合、インデックス作成プロセスは、インデックスオブジェクト自体を作成するときにブロックしませんが、プロセスの終わり近くになると、実際に実行するために一定期間スキーマ変更ロック*を取得しますテーブルにインデックスを追加します。このロックタイプは、ロックが解放されるまですべての外部操作をブロックします。これにより、ブロックの問題が発生する可能性があります。

* Sch-Mロックは、他のすべての場合に必要ですが、新しい非クラスター化インデックスのオンライン構築には必要ありません。新しい非クラスター化インデックスでは、準備フェーズで必要だったのと同じように、最終フェーズではテーブルレベルの共有ロックのみが必要です。

詳細については、このホワイトペーパーを参照してください。

SQL Server 2005のオンラインインデックス操作

質問のコメントで Mushtaq Mohammed が示唆しているように、次も参照してください:

ユニコーン、レインボー、オンラインインデックス操作Paul Randal

25
steoleary