2017-01-16 16 views
3

同じデータベース内に同じ列構造のテーブルが2つあります:TableATableBです。同じデータベース内のあるテーブルから別のテーブルに大量のデータをコピーするにはどうすればよいですか?

TableAにはインデックスがありませんが、TableBにはクラスタ化されていないユニークインデックスがあります。

TableAは、2930万行のデータをTableBにコピーする必要があります。どちらも同じ構造を持っていたよう

が、私は

INSERT INTO TableB 
    SELECT * 
    FROM TableA; 

を試してみたそれは時間を実行してディスクを満たした巨大なログファイルを生成しました。その結果、ディスクの空き領域がなくなり、クエリが強制終了されました。

ログファイルを縮小できます。これらの多くの行のデータを別のテーブルに効率的にコピーするにはどうすればよいですか?

+1

これをチェックすると役立つことがあります。 http://dba.stackexchange.com/questions/99367/insert-into-table-select-from-table-vs-bulk-insert –

+1

2億9,000万行をコピーするには、これを分割したいと思うでしょう。各行にどれくらいのデータがあるかはわかりませんが、1つのステートメントでこれを行うと、エラーがあればロールバックできるようにすべてのデータをログに記録する必要があります。これをチャンクに分割するかBulkInsertを使用すると、トランザクションごとにあまりデータを必要としないため、ログの負荷を軽減できます。 –

+0

プライマリキー列を持っていますか?そうであればどのデータ型ですか? –

答えて

2

まず、行を挿入する前にTableBのインデックスを無効にしてください。あなたは、T-SQLを使用してそれを行うことができます。

ALTER INDEX IX_Index_Name ON dbo.TableB DISABLE; 

は、あなたの先テーブル上のすべての制約(外部キー、チェック制約、一意索引)を無効にしてください。

ロードが完了した後に再度有効化(および再構築)します。

は今、問題を解決するためのアプローチのカップルがあります:

  1. あなたはデータ損失のわずかなチャンスとOKする必要が:あなたが持っているINSERT INTO ... SELECT ... FROM ...構文を使用しますが、Bulk-にデータベースを切り替えます最初に記録されたリカバリモード(read before switching)。すでにバルクログまたはシンプルになっている場合は役に立ちません。
  2. 最初にデータをエクスポートすると、:BCPユーティリティを使用してデータをエクスポート/インポートできます。バッチでデータを読み込むことができます。 BCPユーティリティーhereの使用方法の詳細をお読みください。
  3. ファンシー、最初にデータをエクスポートして:あなたはROWS_PER_BATCHオプションを設定し、(BCPユーティリティを使用して)バイナリファイルにデータをエクスポートしようとしてBULK INSERTステートメントを使用してそれを読み込むことができ2012+ SQLで。一度に行ない、すべてのバッチで 挿入を実行する必要がありますいっぱいのログを防ぐために:
  4. 古い学校「私は気にしない」方法。データベース がフルリカバリモードで実行されている場合は、ログバックアップを のままにしておく必要があります。多分ジョブの頻度を上げようとしている場合もあります。

    にあなたが必要となり、あなたの行をバッチ・ロードWHILEあなたは内の識別子を持っている場合(単にバッチ負荷のために、 日々のものでそれらを使用しない)、次 のようなものがうまくいきますdbo.TableA 表:これは効果的に機能するために

    DECLARE @RowsToLoad BIGINT; 
    DECLARE @RowsPerBatch INT = 5000; 
    DECLARE @LeftBoundary BIGINT = 0; 
    DECLARE @RightBoundary BIGINT = @RowsPerBatch; 
    
    SELECT @RowsToLoad = MAX(IdentifierColumn) dbo.FROM TableA 
    
    WHILE @LeftBoundary < @RowsToLoad 
    BEGIN 
        INSERT INTO TableB (Column1, Column2) 
        SELECT 
         tA.Column1, 
         tB.Column2 
        FROM 
         dbo.TableA as tA 
        WHERE 
         tA.IdentifierColumn > @LeftBoundary 
         AND tA.IdentifierColumn <= @RightBoundary 
    
        SET @LeftBoundary = @LeftBoundary + @RowsPerBatch; 
        SET @RightBoundary = @RightBoundary + @RowsPerBatch; 
    END 
    

    あなたは本当にちょうどあなたが負荷を実行している だ時間dbo.TableA (IdentifierColumn)に インデックスを作成することを検討したいです。

関連する問題