web-dev-qa-db-ja.com

大量の行を挿入する最も速い方法は何ですか?

私はデータベースをステージングテーブルにロードするデータベースを持っています。このステージングテーブルから、いくつかの外部キーを解決するために1-2の結合を行い、この行をファイナルテーブル(月に1つのパーティションを持つ)に挿入します。 3か月分のデータが約34億行あります。

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

28
nojetlag

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にジャンプすることを知りません。おそらくそこにはいくつかの効率がありますが、努力が節約を正当化することを私は知りません。

26
Aaron Bertrand

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

OLEDB Destination

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

10
Zane