2011-06-30 35 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