大型 SQL 插入 TVF 与 BULK 插入
从 C# 应用程序插入巨大数组(10M 元素)的最快方法是什么?
到目前为止,我使用的是批量插入。 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 - 330 秒(写入磁盘 + 插入) TVF - 185s
当然,这是由于写入开销造成的,但我不知道 BULK insert 是否有内存中的等效项。
所以我的问题是 - TVF 是否比 BULK(为大量插入而创建)更好,还是我在这里遗漏了一些东西。还有第三种选择吗?
What is the fastest way to insert a huge array (10M elements) from a C# application?
Till now, I used bulk insert. C# app generates a large textual file and I load it with BULK INSERT
command . Out of curiosity I wrote a simple user defined CLR table value function.
[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);
}
And this query:
INSERT INTO my_table SELECT data FROM dbo.getArray('x');
Works almost 2 times faster than bulk equivalent. The exact results are:
BULK - 330s (write to disk + insert)
TVF - 185s
Of course, this is due to write overhead, but I don't know if BULK insert have any in memory equivalent.
So my question is - is TVF better compering to the BULK (which is created for huge inserts), or am I missing something here. Is there any third alternative?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当我确实需要时,我使用 SqlBulkCopy最后的性能下降,这样您就可以跳过首先将其全部放入磁盘的开销。
SqlBulkCopy 接受您必须实现的 IDataReader,但只接受该接口的几个方法。我总是做的只是创建
类 MyBulkCopySource : IDataReader
,单击“实现接口”并将其按原样提供给 BulkCopy 以查看调用哪个方法。实现它,再试一次等等。您只需要实现其中四个中的三个,其余的永远不会被调用。据我所知,这是将数据从 C# 程序泵入 SqlDB 的最快方法。
国杰
I use a SqlBulkCopy when I really need the very last drop of performance, that way you can skip the overhead of first putting it all on disk.
The SqlBulkCopy accepts an IDataReader that you have to implement, but only a few methods of the interface. What I always do is just create the
class MyBulkCopySource : IDataReader
, click 'Implement interface' and feed it to the BulkCopy as is to see wich method gets called. Implement that, try again etc. You only need to implement three of four of them, the rest never gets called.AFAIK this is the fastest way to pump data from a C# program into a SqlDB.
GJ
这完全在茶几上设置了最小的锁定。
This totally puts the smallest locking on the end table.