2011-06-30 8 views
4

C#アプリケーションから巨大な配列(10M要素)を挿入する最も速い方法は何ですか?大きなSQL挿入TVF対BULK挿入

これまで、バルクインサートを使用しました。 C#アプリケーションは大きなテキストファイルを生成し、BULK INSERTコマンドでロードします。私は、好奇心のために単純なユーザー定義のCLRテーブル値関数を書きました。

[SqlFunction(Name = "getArray", FillRowMethodName = "FillRow")] 
     public static IEnumerable getArray(String name) 
     { 
     return my_arrays[name]; // returns the array I want to insert into db 
     } 

     public static void FillRow(Object o, out SqlDouble sdo) 
     { 
      sdo = new SqlDouble((double)o); 
     } 

そして、このクエリ:

INSERT INTO my_table SELECT data FROM dbo.getArray('x'); 
のほぼ2倍高速バルク同等以上ワークス

。正確な結果は以下のとおりです。

BULK - 330S(ディスク+インサートに書き込み) TVF - もちろん185S

を、このオーバーヘッド書くことが原因ですが、私はもしBULKインサートを知りませんメモリ内の任意のものを持つ。

私の質問は - TVFがBULK(巨大な挿入物のために作成されています)に適合しているか、ここで何か不足していますか? 3番目の選択肢はありますか?

答えて

3

私は本当に最後のパフォーマンス低下が必要なときにSqlBulkCopyを使用します。その方法では、最初にすべてをディスクに置くオーバーヘッドをスキップできます。

SqlBulkCopyは、実装する必要があるIDataReaderを受け入れますが、インターフェイスのメソッドはわずかです。私が常にやっているのは、class MyBulkCopySource : IDataReaderを作成して、[インターフェイスの実装]をクリックして、BulkCopyにフィードを送って、メソッドが呼び出されるようにします。それを実装して、もう一度やり直してください。あなたは4つのうちの3つを実装する必要があります。残りは決して呼び出されません。

AFAIKこれは、C#プログラムからSqlDBにデータを転送する最も速い方法です。

GJ

2
  • 使用SqlBulkCopy
  • 30.000行毎時間のようなブロックを持つ複数のスレッドから。
  • 最終テーブルではなく一時テーブル
  • ロックを尊重しない接続設定を使用してコピーします。

これは、完全に最小のロックをエンドテーブルに置きます。

+0

複数のスレッドはありますか?あなたは、それぞれ独自の接続で複数のSBCを意味しますか?通常、私はボトルネックがネットワークまたはディスクドライブのいずれかであると考えます。私は複数のスレッドを使用すると競合につながると思います。 – gjvdkamp

+0

複数のSBCが同時に実行されるように、マルチペルスレッド。これを使用して大量のデータ(600万以上)をロードし、3つのスレッドを使用してスループットを2倍にしました。それが重要視される競合が少なくなる - コアテーブル上。ロック時間は低く、3つのスレッドは別々の一時テーブルインスタンスを使用します;)常にデータを流し続けます。 – TomTom