多数の行を挿入する最速の方法は何ですか?


27

私はデータベースをステージングテーブルにロードします。このステージングテーブルから、外部キーを解決するために1-2回結合し、この行を最終テーブル(月ごとに1つのパーティションがある)に挿入します。3か月分のデータで約34億行あります。

これらの行をファイナルテーブルにステージングする最速の方法は何ですか?SSISデータフロータスク(ビューをソースとして使用し、高速ロードがアクティブになっている)またはInsert INTO SELECT ....コマンド?データフロータスクを試してみましたが、約5時間で約10億行(サーバー上の8コア/ 192 GB RAM)を得ることができ、非常に遅いと感じました。


1
パーティションは別々のファイルグループにありますか(また、異なる物理ディスク上のファイルグループにありますか)?
アーロンバートランド

3
非常に優れたリソースデータ読み込みパフォーマンスガイド。これは、TF610の有効化、BCP OUT / IN、SSISなどの使用など、実行可能な多くのパフォーマンス最適化に対応します。推奨事項に従って、環境でテストするだけです。
キンシャー

@Aaronはい、月ごとに1つのファイルグループ、12のsan lunが接続されているため、すべてのjanが1つのlunに移行します。
nojetlag 14

ええ、私は本当に「ディスクのセット」を意味し、おそらく飽和状態になる可能性のあるコントローラーにも言及できたでしょう。
アーロンバートランド

@Kinはガイドを見ましたが、時代遅れのようです。「SQL Serverの宛先は、Integration ServicesデータフローからSQL Serverにデータを一括ロードする最も速い方法です。この宛先は、ROWS_PER_BATCHを除くSQL Serverのすべての一括ロードオプションをサポートします」また、SSIS 2012では、パフォーマンスを向上させるためにOLE DB宛先を推奨しています。
nojetlag

回答:


25

1つの一般的なアプローチ:

  1. ターゲットテーブルのインデックス/制約を無効化/削除します。
  2. INSERT dbo.[Target] WITH (TABLOCKX) SELECT ...
  3. もちろん、JNKの功績により、n行のバッチで上記の操作を行うことができます。これにより、トランザクションログへの負担を軽減できます。もちろん、一部のバッチが失敗した場合は、そのバッチから開始するだけです。私はこれについてブログに書いています(削除に関しては同じ基本概念が適用されます):http : //www.sqlperformance.com/2013/03/io-subsystem/chunk-deletes
  4. ターゲットテーブルのインデックス/制約を再度有効化/再作成します(すべての操作に必要でない場合は、それらの一部を延期できます。ベースデータをすぐにオンラインにすることがより重要です)。

パーティションが論理的であるだけでなく物理的である場合、異なるプロセスに異なるパーティションを同時に設定することにより、ある程度の時間を得ることができます(もちろん、これはTABLOCK/を使用できないことを意味しますTABLOCKX)。これは、ソースが重複/ロックなどを伴わずに選択する複数のプロセスにも適しており、操作のその側をさらに遅くすることを前提としています(ヒント:宛先のパーティションスキームに適したソースにクラスター化インデックスを作成します)。

BCP OUT/のBCP INような、もっと原始的なものを考えることもできます。

これを支援するためにSSISにジャンプするかどうかはわかりません。おそらくいくつかの効率がそこにありますが、その努力が節約を正当化することを知りません。


2
データが並べ替えられていない場合、盲目的にインデックス(特にクラスタ化インデックス)を削除しないでください。インデックスを削除してクラスター化インデックスを再作成することは、大きなディスクスペースと膨大な時間の両方を消費する可能性があるため、大きな間違いです。私はそのような間違いを経験した最初の人ではありません。この記事sqlmag.com/t-sql/…の「プランB」の説明を参照してください。著者にも同じ問題がありました。
チャオ

10

SSISの観点から問題を見ると、これに時間がかかったのは、バッチ処理がなかったからだと思います。これにより、SSISパイプラインを埋める行が多くなりすぎ、結果としてSSISのパフォーマンスが低下する可能性があります。バッチ設定ごとに行を変更し、場合によっては最大挿入コミットサイズを変更する必要があります。これも何を設定するかは、SSISサーバーで使用可能なメモリ量に依存しますか?SQL Serverインスタンスのディスク速度は?これを行う最良の方法はテストです。たとえば、10,000を使用します。これにより、バッチがサーバーに10,000回送信されるため、パイプラインがいっぱいになりすぎず、このプロセスをより速く実行できます。これらの設定は、OLEDB宛先で設定されます。

OLEDB宛先

それが問題である場合は、@ AaronBertrandが提案するように実行する前後にSQL実行タスクを追加し、テーブルのインデックスまたは制約を削除/再追加することもできます。


1
DBA.SEの他の場所で、「高速ロード」が何を必要とするかについての優れた質問があります:dba.stackexchange.com/questions/141430/…
すべての取引のジョン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.