SQLサーバーでのインデックス再構築の速度を改善する


9

大量のデータを空のデータベースにインポートしています。開始する前に、一意でない非クラスター化インデックスをすべて無効にして、インポートのパフォーマンスを向上できるかどうかを確認しました。

ここで、インデックスを再度有効にしたいと思います。これを最適化するために何かできることがあるかどうか疑問に思っています。

再構築する必要がある100を超えるテーブルとほぼ2,000のインデックスがあります。データベースのサイズは200GBです。

私が実行しているスクリプトの重要なセクションは次のとおりです。

declare c_toggle_index cursor FORWARD_ONLY READ_ONLY for
    select  'alter index ' + QUOTENAME(i.name) + ' on ' + o.name + ' rebuild'
    from    sys.indexes as i
    Inner Join sys.objects o
    On o.object_id = i.object_id
    Where o.is_ms_shipped = 0
    And i.index_id >= 1
    and i.type > 1
    and i.is_disabled = 1

インデックスの変更ステートメントにONLINE = OFFを設定することを検討しましたが、インデックスが最初は無効になっているので、この設定が効果があるかどうか確信が持てませんでした。また、SORT_IN_TEMPDB = ONの設定も検討しましたが、tempdbファイルはデータベースの.mdfファイルと同じドライブ上にあるため、これを行うことにも利点はないと想定しました。

再構築スクリプトを実行しているときに、CXPACKET待機タイプがたくさんあることに気付きました。なぜそうなるのか、それが対処すべき問題であるのか、本当にわかりません。

関連する可能性のある最後のポイントの1つは、データベースへのデータのインポート以外に、サーバー全体が現在非アクティブになっていることです。考慮または心配する他のユーザーアクティビティはありません。私の唯一の懸念は、可能な限り短い時間でデータベースにデータをインポートすることです。


3
唯一の懸念がインポート時間であると言うとき、インポートの開始からインデックスの再有効化の終了までの時間を意味しますか?その場合は、インポート中はインデックスを有効のままにしておく必要があります。200GBのデータに対して2,000のインデックスは、多くのインデックスのように思えます。おそらく、インデックスの使用DMVを見て、削除できるものがあるかどうかを確認する必要があります。
Max Vernon

1
明確にするために、同じ200GBのインポートを1回ではなく繰り返し行う必要がありますか?
Jon Seigel 2013

1
インポートは1回だけで十分ですが、時間の制限された大きなプロセスの一部として、現在そのプロセスをテストして、そのウィンドウ内に収まるようにしています。@MaxVernonインデックスを有効のままにしておくのが最も速い方法であるとお考えのようですが、通常はインデックスを無効にしてデータをインポートし、インデックスを再度有効にした方が速いことを読んで驚いています。これはサードパーティのデータベースなので、インデックスを削除したり変更したりすることは実際には不可能です。
ポール2013

3
はい。CXPACKET待機について:インデックスは自身を再構築し、インデックスを再構築します(インデックスが再構築されている場合でも)。これらのスキャンは並列処理を使用できます。これらの待機について心配する必要はありません。おそらく並列処理が役立つでしょう。
Jon Seigel 2013

回答:


10

このシナリオで最適なインポートパフォーマンスを実現するには、次の3つが必要です。

  1. 最小限のログが記録されたベーステーブルインサート
  2. 最小限のログが記録された非クラスター化インデックスのビルド
  3. 物理的な読み取りを回避する

最小限のロギング

非クラスター化インデックスなしで空のクラスター化テーブルへの最小限のログに記録された挿入を実現するには、以下が必要です。

  1. SIMPLEまたはBULK_LOGGEDデータベース復旧モデルを使用する
  2. テーブルロックと順序付けされた入力の指定(例TABLOCKORDERヒント)

サイドノート:

トレースフラグ610が有効になっている場合、非クラスター化インデックスを持つクラスター化テーブルへの最小限のログの挿入を実現することもできます。非クラスター化インデックスの挿入が最小限のログに記録されるかどうかは、クエリオプティマイザーによって選択されるクエリプランによって異なります。

クエリプランは、非クラスタ化インデックスのために別々の反復子を使用した場合 イテレータが有するDMLRequestSortにプロパティセットをtrue、非クラスタ化インデックスインサートは最小記録されます、他の条件が先に満たされ述べられました。

非クラスター化インデックスを個別に構築する

これを行う利点は次のとおりです。

  1. クラスター化インデックスの挿入は、TF 610を有効にせずに最小限のログに記録できます
  2. CREATE INDEX 復旧モデルがそうでない場合、最小限のログ FULL

物理的な読み取りを回避する

理想的には、インポートされるデータは、別のマシン、または少なくともデータベースのホストに使用されているものとは別の物理ストレージに保存されます。

データベースサーバーには、最大のベーステーブルをキャッシュに保持するのに十分なメモリが必要です。また、非クラスター化インデックスを構築するときに必要な並べ替え操作のために十分なメモリが必要です。

良いパターンは、ベーステーブルを高速に読み込み(最小限のログのクラスター化インデックスの読み込み)、データページがキャッシュされている間にそのテーブルのすべての非クラスター化インデックスを構築することです。

質問では、ベーステーブルが最初に読み込まれ、次に非クラスター化インデックスが作成されるプロセスの概要を示します。カーソル定義でORDER BY、少なくとも同じテーブルで非クラスター化インデックスのビルドをグループ化する使用していません

考えられる結果は、非クラスター化インデックスが非決定的な順序で構築されるため、さまざまなテーブルのデータページがキャッシュに繰り返し読み込まれ、その後破棄されることです。

繰り返される物理読み取りのコストは、非クラスター化インデックスを個別に構築することによって得られる最小限のロギングの利点を完全に支配します。これにより、既存のインデックスを持つテーブルの読み込みが高速になることがわかりました(特定のテーブルのすべての非クラスター化インデックスが次のテーブルに進む前に維持されるため)。

概要

インポートプロセスは、一度に1つのテーブルを一括ロードするように修正する必要があります。これは、次のテーブルに進む前に、テーブルをロードしてすべての非クラスター化インデックスを構築することを意味します。SQL Serverインスタンスは、最大のテーブルを保持するのに十分なメモリが必要同時に、最大の非クラスタ化インデックスのソートを実行します。

非クラスター化インデックスがすでに配置されているテーブルにデータをロードする前に、TF 610を有効にすることできます。これは通常、前の方法ほど高速ではありませんが、十分高速である可能性があります。

詳細については、以下を参照してください。

データ読み込みパフォーマンスガイド

最小限に記録できる操作

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.