2017-11-09 7 views
0

私はアプリケーションに大量のレコードをロードしています(100万+)。処理には、すべてがメモリに格納されている必要があります。DataTableを使用するよりも速くSqlBulkCopyを使用できますか?

その後、すべての(変更された)レコードを空のテーブルにダンプします。

レコードの読み込みにはほんの数秒しかかからず、MyRecordという大きな配列で終わります。

SqlBulkCopyを使用して保存するのにも数秒かかります。

しかしSqlBulkCopyは(私は信じている)DataTableを必要 - とDataTableに私のレコードをロードすると遅いです -

dataTable.Rows.Add(myRecord.Name, myRecord.Age, ....) 

を使用して、毎分約7500の記録この中間のステップを実行するより高速な方法はありますか?

+0

は、あなたが見たことがありhttps://stackoverflow.com/questions/13722014/insert-2-million-rows-into-sql-server-faster(そこにいる人は100万行/秒を請求しています)あなたのDataTableは、インデックス、キー、式の列、制約、他のテーブルとの関係などを持っていますか、それとも簡単なことができますか? –

+0

私のデータテーブルは完全にシンプルですが、余分なものがない文字列、intおよびdatetimeフィールド – NibblyPig

+0

彼の例は新しい行を作成してデータを追加しています。これは私がやっていることです。私はなぜあなたがそれをする必要がないときに反射を使用しているのか分かりません。 – NibblyPig

答えて

4

遅延は、すべてをDataTableにバッファリングしてからサーバーに送信する必要があるために発生します。パフォーマンスを向上させるには、レコードをSqlBulkCopy immediatellyに送信し、クラスに独自のバッファリングとバッチ処理を使用させる必要があります。

SqlBulkCopyはIDataReaderと共に使用できます。すべてのADO.NETデータリーダーがこのインターフェイスを実装しているので、データリーダーから読み取ったデータをSqlBulkCopyにプッシュできます。

オブジェクトのIEnumerableがあると仮定すると、FastMemberパッケージのMarc GravelのObjectReaderを使用して、IEnumerableの上にIDataReaderを作成できます。このデータリーダーは一度ない負荷すべてを行い、そのSqlBulkCopyまでキャッシュされたデータは、それを要求しません:

コピーマルク砂利の例:

IEnumerable<SomeType> data = ... 

using(var bcp = new SqlBulkCopy(connection)) 
using(var reader = ObjectReader.Create(data, "Id", "Name", "Description")) 
{ 
    bcp.DestinationTableName = "SomeTable"; 
    bcp.WriteToServer(reader); 
} 
+0

これは非常にクールな音、私は間違いなくそれを与えるでしょう – NibblyPig

0

問題の内容がわかりません。以下のプログラムは1秒未満で実行されます。私は、遅い速度がデータの読み取りとDataTableへの書き込みではないと思われます。

 static void Main(string[] args) 
     { 
      DataTable dt = new DataTable(); 
      dt.Columns.Add("Col A", typeof(int)); 
      dt.Columns.Add("Col B", typeof(string)); 
      dt.Columns.Add("Col C", typeof(int)); 
      dt.Columns.Add("Col D", typeof(string)); 
      dt.Columns.Add("Col E", typeof(int)); 
      dt.Columns.Add("Col F", typeof(string)); 
      dt.Columns.Add("Col G", typeof(int)); 
      dt.Columns.Add("Col H", typeof(string)); 
      dt.Columns.Add("Col I", typeof(int)); 
      dt.Columns.Add("Col J", typeof(string)); 

      DateTime begin = DateTime.Now; 

      for (int i = 0; i < 7500; i++) 
      { 
       dt.Rows.Add(new object[] { 
        i + 10000, "b", i + 20000, "d", i + 30000, "f", i + 40000, "h", i + 50000, "i" 
       }); 
      } 

      DateTime end = DateTime.Now; 

      Console.WriteLine((end - begin).ToString()); 

      Console.ReadLine(); 
     } 
関連する問題