web-dev-qa-db-ja.com

テーブルからテーブルへの一括挿入

A/B/Viewシナリオを実装しています。つまり、Viewtable Aを指し、table B =が更新されると、切り替えが発生し、テーブルAがロードされている間、ビューはテーブルBを指します。

切り替えは毎日行われます。更新する行は数百万行あり、ビューを見ているユーザーは数千人です。私はSQLServer2012を使用しています。

私の質問は次のとおりです。

  • 可能な限り最速の方法で別のテーブルからテーブルにデータを挿入するにはどうすればよいですか? (ストアドプロシージャ内)
  • BULK INSERTを使用する方法はありますか?または、通常の挿入/選択を使用して最も速い方法を使用していますか?
6
user1044169

SrcTableからDestTable_NewにColA、ColBを選択できます。 DestTable_Newがロードされたら、インデックスと制約を再作成します。

次に、DestTableの名前をDestTable_Oldに変更し、DestTable_Newの名前をDestTableに変更します。名前の変更は非常に迅速です。何かがうまくいかなかったことが判明した場合は、近くにある前のテーブルのバックアップもあります(DestTable_Old)。

このシナリオは、システムを24時間年中無休で実行する必要があり、毎日数千万行をロードする必要がある場合に一度実行しました。

2
Asok

SSISを使いたいと思います。

テーブルAをOLEDBソースにし、テーブルBをOLEDB宛先にします。トランザクションログをバイパスするので、DBの負荷を減らします。 T-SQLを使用してこれを行う唯一の方法(私が考えることができる)は、データベース全体のリカバリモデルを変更することです。これは、転送用のトランザクションだけでなく、トランザクションも保存されないことを意味するため、理想からはほど遠いものです。

SSIS転送の設定

新しいプロジェクトを作成し、データフロータスクをデザインサーフェスにドラッグします

Tool box menu

データフロータスクをダブルクリックすると、[データフロー]タブに移動します。次に、[データフローソース]メニューからOLE DBソースをドラッグアンドドロップし、[データフロー宛先]メニューからOLE DB宛先

Data flow sourcesData flow destinations

OLE DBソースをダブルクリックし、サーバーへの接続を設定し、ロードするテーブルを選択して[OK]をクリックします。OLE DBソースから宛先まで、宛先をダブルクリックします。接続マネージャー、宛先テーブル名、および列のマッピングを設定すると、準備が整います。

MSDNのOLE DBソースドキュメント

MSDNのOLE DB宛先ドキュメント

2
GarethD

あなたはすることができます

SELECT fieldnames
INTO DestinationTable
FROM SourceTable

いくつかの回答が示唆しているように、それは可能な限り高速である必要があります(再作成する必要のあるインデックスの数などによって異なります)。

ただし、ポインタをあるテーブルから別のテーブルに変更するには、同義語を使用することをお勧めします。それらは非常に透過的であり、私の意見では、ビューを更新したり、テーブルの名前を変更したりするよりもクリーンです。

2
Sylvia

質問が古いことは知っていますが、同じ質問に対する答えを探していたので、本当に役立つものは見つかりませんでした。はい、SSISアプローチは可能ですが、質問にはストアドプロシージャが必要でした。

嬉しいことに、元の質問が望んでいた解決策を(ほぼ)発見しました。 CLRSPでそれを行うことができます。

TableAからDataTableにデータを選択し、TableBをDestinationTableNameとしてSqlBulkCopyクラスのWriteToServer(DataTable dt)メソッドを使用します。

唯一のわずかな欠点は、CLRプロシージャがSqlBulkCopyを使用するために外部アクセスを使用する必要があり、コンテキスト接続では機能しないため、アクセス許可と接続文字列を少しいじる必要があることです。でもねえ!完璧なものはありません。

1
user6638270

INSERT... SELECT...BULK INSERTとほぼ同じように機能します。 @GarethDが言うように、SSISを使用することもできますが、table1からtable2に行をコピーするだけの場合は、非常に複雑になる可能性があります。

大量のデータをコピーする場合は、トランザクションログに注意してください。大量の挿入を行うと、非常に速く膨張する可能性があります。回避策の1つは、挿入するデータを「チャンク化」することです。これは、たとえば、一度に100,000行または10,000行のみを処理する挿入ステートメントをループします(行の幅、つまりパスあたりのMB数によって異なります)。

(不思議なことに、ビューをリセットするためにALTER VIEWを実行していますか?過去/現在/次/スワップセットをサポートするために4つのテーブルと4つのビューが必要でしたが、私は一度同様のことをしました。)

0
Philip Kelley

あなたは単にこのようにすることができます

    select * into A from B Where [criteria]

これにより、基準に基づいてBからデータが選択され、列が同じであるか、*の代わりに列名を指定できる場合は、Aに挿入されます。

0
Furqan Hameedi