2011-06-30 33 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 INSERT有相同的記憶。

所以我的問題是 - TVF是否更好地彌補了BULK(它是爲巨大的插入創建的),還是我在這裏錯過了一些東西。有沒有第三種選擇?

回答

3

當我真的需要最後一滴性能時,我使用SqlBulkCopy,這樣您可以跳過首先將所有內容放在磁盤上的開銷。

SqlBulkCopy接受您必須實現的IDataReader,但只能使用接口的幾種方法。我總是做的只是創建class MyBulkCopySource : IDataReader,單擊'實現接口'並將其提供給BulkCopy,以便查看被調用的方法。實現這一點,再試一次等​​等。你只需要實現四個中的三個,其餘的都不會被調用。

AFAIK這是將數據從C#程序中抽取到SqlDB的最快方法。

GJ

2
  • 使用SqlBulkCopy的
  • 從像每次30.000排塊多線程。
  • 不是爲了決賽桌,而是爲了一張臨時牌
  • 從哪裏複製過來,使用的連接設置沒有兌現鎖定。

這完全將最小的鎖定在最終表上。

+0

你確定關於多個線程嗎?你是否指自己的連接上有多個SBC?通常我會認爲瓶頸是網絡或磁盤驅動器。我認爲使用多線程會導致爭用。 – gjvdkamp

+0

Multipel線程使得多個SBC同時運行。我使用它來加載更大量的數據(6億以上),並使用3個線程加倍了我的吞吐量。在覈心表上,爭議較少的地方。鎖定時間很短,三個線程無論如何都使用單獨的臨時表實例;)始終保持數據流暢。 – TomTom