7

ビューから入力する必要があるいくつかの大きなテーブル (188m 行と 144m 行) がありますが、各ビューには数億行が含まれています (疑似次元でモデル化されたデータをフラットな形式にまとめます)。各テーブルのキーは、列の複合バイトが 50 を超えています。データがテーブルにある場合は、sp_rename を使用して別の新しいテーブルを作成することをいつでも考えることができますが、それは実際にはオプションではありません。

単一の INSERT 操作を行うと、そのプロセスは膨大な量のトランザクション ログ スペースを使用し、通常はファイルを作成し、DBA に多くの面倒を引き起こします。(もちろん、これはおそらく DBA が処理/設計/アーキテクトするべき仕事です)

SSIS を使用して、バッチ コミットを使用して宛先テーブルにデータをストリーミングできます (ただし、サーバー上で SSIS パッケージを実行することは許可されていないため、データをネットワーク経由で送信する必要があります)。

プロセスを複数の INSERT 操作に分割して、何らかのキーを使用して行を異なるバッチに分散し、ループを実行する以外に何かありますか?

4

6 に答える 6

7

ビューには、一意の識別子/候補キーの種類がありますか? その場合、次を使用してそれらの行を作業テーブルに選択できます。

SELECT key_columns INTO dbo.temp FROM dbo.HugeView;

(それが理にかなっている場合は、ログ アクティビティがプライマリ データベースに干渉するのを防ぐために、おそらく SIMPLE 復旧モデルを使用して、このテーブルを別のデータベースに配置することをお勧めします。これにより、生成されるログはいずれにせよはるかに少なくなり、ディスク領域が全体的に不足していることが問題の場合に備えて、再開する前に他のデータベースを参照してください)。

次に、一度に 10,000 行を挿入し、その間にログをバックアップして、次のようなことを行うことができます。

SET NOCOUNT ON;

DECLARE
    @batchsize INT,
    @ctr INT,
    @rc INT;

SELECT
    @batchsize = 10000,
    @ctr = 0;

WHILE 1 = 1
BEGIN
    WITH x AS
    (
        SELECT key_column, rn = ROW_NUMBER() OVER (ORDER BY key_column)
        FROM dbo.temp
    )
    INSERT dbo.PrimaryTable(a, b, c, etc.)
        SELECT v.a, v.b, v.c, etc.
        FROM x
        INNER JOIN dbo.HugeView AS v
        ON v.key_column = x.key_column
        WHERE x.rn > @batchsize * @ctr
        AND x.rn <= @batchsize * (@ctr + 1);

    IF @@ROWCOUNT = 0
        BREAK;

    BACKUP LOG PrimaryDB TO DISK = 'C:\db.bak' WITH INIT;

    SET @ctr = @ctr + 1;
END

それは私の頭の中ですべてなので、カット/ペースト/実行しないでください。しかし、一般的なアイデアはそこにあると思います。詳細 (およびループ内でログ/チェックポイントをバックアップする理由) については、sqlperformance.com の次の投稿を参照してください。

データベースとログのバックアップを定期的に行っている場合は、ログ チェーンを最初からやり直すために、おそらく完全なバックアップを取得する必要があることに注意してください。

于 2009-10-21T17:35:15.700 に答える
5

データを分割して、カーソルループにデータを挿入できます。これは、SSISバッチ挿入とほぼ同じです。ただし、サーバー上で実行されます。

create cursor ....
select YEAR(DateCol), MONTH(DateCol) from whatever

while ....
    insert into yourtable(...)
    select * from whatever 
    where YEAR(DateCol) = year and MONTH(DateCol) = month
end
于 2009-10-21T17:23:43.640 に答える
2

ピクシーダストはありません。

転送される実際のスキーマに関する詳細を知らなくても、一般的な解決策は、説明したとおりです。処理を複数の挿入に分割し、キーを追跡します。これは一種の疑似コード T-SQL です。

create table currentKeys (table sysname not null primary key, key sql_variant not null);
go

declare @keysInserted table (key sql_variant);
declare @key sql_variant;
begin transaction
do while (1=1)
begin
    select @key = key from currentKeys where table = '<target>';
    insert into <target> (...)
    output inserted.key into @keysInserted (key)
    select top (<batchsize>) ... from <source>
    where key > @key
    order by key;

    if (0 = @@rowcount)
       break; 

    update currentKeys 
    set key = (select max(key) from @keysInserted)
    where table = '<target>';
    commit;
    delete from @keysInserted;
    set @key = null;
    begin transaction;
end
commit

並列バッチを許可してキーを分割したい場合は、さらに複雑になります。

于 2009-10-21T17:30:06.527 に答える
1

BCP コマンドを使用してデータをロードし、Batch Size パラメーターを使用できます。

http://msdn.microsoft.com/en-us/library/ms162802.aspx

2段階のプロセス

  • ビューからテキスト ファイルへの BCP OUT データ
  • バッチ サイズ パラメータを使用して、テキスト ファイルからテーブルへの BCP IN データ
于 2009-10-21T17:29:21.957 に答える
1

これは古き良きBCPの仕事のように見えます。

于 2009-10-21T17:29:34.543 に答える