2009-08-28 20 views
1

同じデータベースサーバー上にDB1とDB2という2つのデータベースがあります。私はDB2のTable1とDB2のTable2を持っています。現在、select *にinsertを使用してTable2からTable1にすべてのデータを転送しています(Table1は空です。私の目的はTable2からTable1へのデータのコピーを作成することです)。テーブル構造は、(GUID型の)クラスタ化ID列とXMLバイナリ(varbinary)データ列です。SQL Serverの選択と挿入問題

私の現在の問題は、メモリ消費量が非常に高いことです。メモリ消費量を減らすための良いアイデアはありますか?私の大まかな考え方は、小さなトランザクションをいくつか初期化し、各トランザクションから部分的なデータを挿入することです。

VSTS 2008 + C#+ ADO.Net + SQL Server 2008 Enterpriseを使用しています。良いソリューションやリファレンスサンプルはありますか?

メモリ不足例外の原因となる現在のコードです。私はADO.Net SQLBulkCopy機能を使用しています。

namespace BulkCopyTable 
{ 
    public class CopyData 
    { 
     string _sourceConnectionString; 
     string _destinationConnectionString; 

     public CopyData(string sourceConnectionString, 
         string destinationConnectionString) 
     { 
      _sourceConnectionString = 
         sourceConnectionString; 
      _destinationConnectionString = 
         destinationConnectionString; 
     } 

     public void CopyTable(string table) 
     { 
      using (SqlConnection source = 
        new SqlConnection(_sourceConnectionString)) 
      { 
       string sql = string.Format("SELECT * FROM [{0}]", table); 

       SqlCommand command = new SqlCommand(sql, source); 

       source.Open(); 
       IDataReader dr = command.ExecuteReader(); 

       using (SqlBulkCopy copy = 
         new SqlBulkCopy(_destinationConnectionString)) 
       { 
        copy.DestinationTableName = table; 
        copy.WriteToServer(dr); 
       } 
      } 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      CopyData copier = new CopyData(ConfigurationSettings.AppSettings["source"], ConfigurationSettings.AppSettings["destination"]); 
      Console.WriteLine("Begin Copy"); 
      copier.CopyTable(ConfigurationSettings.AppSettings["Table"]); 
      Console.WriteLine("End Copy"); 
      return; 
     } 
    } 
} 

答えて

1

バッチサイズを設定して、管理可能な部分にまとめることができると思います。

Bulk copy batch size

チェック他の技術のために、このバルクデータをロードするホワイトペーパー: Bulk load

+0

ありがとうございましたJasonHorner、1.バルクバッチサイズをご確認します。私が1Mレコードを持っていて、バッチサイズを500Kに設定した後、最初の500Kバッチを挿入した後、SQL Serverは、最初から再起動以外の後半の500Kバッチを挿入することになります。 2.バルクロードのドキュメントは非常に素晴らしいです!しかし、それはSQL Server 2000、より新しいSQL Serverバージョンの関連ドキュメントです。 – George2

+1

はいそれは、別々のトランザクションとして各バッチをコミットします。 これは http://blogs.msdn.com/sqlcat/archive/2009/02/12/the-data-loading-performance-guide-now-available-from-msdn.aspx 私は考えてみてくださいほとんどの場合、古い素材はまだ有効です。 – JasonHorner

+0

ありがとう!本当にクールな文書。私はより多くのテストを行い、ここでフィードバックをします。 :-) – George2

2

BCPユーティリティを試すことができます。

これは、必要に応じてProcessクラスを使用してC#で実行できます。

+0

ありがとうskalburgi、私は現在、SQLの一括コピーを使用していると私はそれがBCPと同じにするべきだと思いますか? http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.aspx 一度に一括コピーを実行して、すべてのデータをソーステーブルからコピー先にコピーすると、メモリエラー。プロセスを複数のサブプロセスに分割するためのアイディア私はいくつかのサブプロセスに分割すると、メモリ消費量を減らすのに役立つと思いますか? – George2

+1

Table1からGUID範囲を選択した実行に分割するのはどうですか?例えば を(あなたはランダムな分布を持っていると仮定すると): スタート:00000000-0000-0000-0000-0000000000 終了:AAAAAAAA-AAAAAAAA-AAAA-AAAAAAAAAA – skalb

+0

こんにちはskalburgiを、1.私のGUIDは、任意の良い、ランダムであります分割するアイデア? :-( 2。csvファイルからバルク挿入をBCPでテーブルに挿入しました。バルク挿入を使用してテーブルから別のテーブルに挿入することはできますか? – George2

2

これは1回の仕事ですか?その場合は、DTSまたはSSISを使用できます。
がない場合は、フレームワーク

EDITにSQLBulkCopy &関連するクラスを使用することができた場合、以下を参照してください。私はあなたのコード&がWriteToServerのを呼び出す前にBatchSizeプロパティを使用して提案することができました。

+0

このクラスを使用しようとしましたが、メモリが不足しています。 SQLの一括コピーで作業を分割するためのアイデア? – George2

+1

コードを送信してください。また、メモリが不足した場所や時間を追加してください。 – shahkalpesh

+0

元の返信に自分のコードを掲載しました。任意のアイデアは、この問題を解決する方法をより少ないメモリを使用するように? – George2

1

ソーステーブルの各行をステップ実行し、フェッチされた行ごとに「insert-into-select」を設定すると、メモリの使用量は少なくなりますか? BOLには、カーソルを踏んだ例がたくさんあります。


更新:(コメントはBOLの記事から、私はほんの数名のまわりに変更されている)

-- // Declare the variables to store the values returned by FETCH. 
DECLARE @id uniqueidentifier, @xml varbinary(4000) 

DECLARE myCursor CURSOR FOR 
SELECT id, xml FROM Table1 

OPEN myCursor 

-- // Perform the first fetch and store the values in variables. 
-- // Note: The variables are in the same order as the columns 
-- // in the SELECT statement. 

FETCH NEXT FROM myCursor 
INTO @id, @xml 

-- // Check @@FETCH_STATUS to see if there are any more rows to fetch. 
WHILE @@FETCH_STATUS = 0 
    BEGIN 

    -- // Do something with your values! 
    INSERT INTO db2..Table2 (id, xml) SELECT @id, @xml 

    -- // This is executed as long as the previous fetch succeeds. 
    FETCH NEXT FROM myCursor 
    INTO @id, @xml 

    END 

CLOSE myCursor 
DEALLOCATE myCursor 
:ここではFETCHにBOL T-SQLリファレンスから変更/ Iがコピー例です
+0

私はカーソル、リファレンスサンプルを設定するあなたの考えが好きですか? – George2

+1

私は答えを更新しました – Funka

+1

これはメモリの消費は少なくなりますが、かなりの時間がかかります。 – HLGEM