【问题标题】:Write large amount or rows to a mssql database using c#使用 c# 将大量或行写入 mssql 数据库
【发布时间】:2013-02-19 21:23:41
【问题描述】:

我在使用 c# 应用程序将大量数据行提交到数据库 (sql 2008 R2) 的代码时遇到问题。

我现在正在创建一个相当大的 XML 文件(大约 30Mb),其中包含大约 40.000 行应该插入到数据库中。

从我作为变量传递给数据库的这个 xml 文档中,我有一个存储过程,它将从中读取数据并进行适当的插入或更新。

伪 c# 代码:

String xml = xmlWriter.ToString();
SqlCommand cmd = new SqlCommand("sp_CommitData", connection)
cmd.Variables.AddWithValue("@xml", xml);
SqlDataReader reader = cmd.ExecuteReader();
while(reader.Read())
{ 
 /* Read return data */
}

伪tsql代码:

INSERT INTO DataTable
xmldata.value('@uID','[uniqueidentifier]') AS [uID]
FROM<
@xml.nodes('/data/m/r') [xmldata](xmldata)  

这种方法过去对我来说效果很好,但现在数据对于这种方法来说似乎非常庞大......提交数据需要 3 分钟以上,而且时间很长。 :(

这一定是一个很常见的问题,你们在类似的情况下是怎么做的? 您对如何使用 c# 提交相当大量的数据有什么好的建议吗?该解决方案必须是线程安全的,所以我不太喜欢 bcp 或类似方法。

亲切的问候 画了

【问题讨论】:

  • 您使用的是 SQL Server 2008 吗?表值参数应该有很大帮助。
  • 如果你要插入大量数据我建议你看看SqlBulkCopy
  • 是否所有 40.000 行都在一个事务中?如果是这样,它们必须在一个事务中吗?
  • 是的,一个事务中有大约 40.000 行分布在三个表中,必须作为事务更新。

标签: c# .net tsql stored-procedures


【解决方案1】:

最快的方法是使用SqlBulkCopy,这将使用 SQL 的批量加载功能。

XML 方法的问题在于,您首先必须将行集/IEnumerable(您必须从什么开始?)转换为 XML,然后将其推送到网络上。 XML 是一种非常臃肿的格式,当您提到有很多行时,这很重要。

批量复制方法可以让您逐行流式传输,而无需将整个内容具体化(到内存或磁盘上),从而减少内存占用。

如果数据量很大,您可能希望先将其加载到临时表中(因此没有真实表的事务),然后将其插入(或Merge)到真实表中。

线程安全是什么意思?如果您希望此操作不阻塞客户端,您可以轻松地在后台线程上启动它。没有外部进程或任何您需要开始执行此操作的程序,它在进程内运行。

【讨论】:

  • 对SqlBulkCopy的一个评论是,为了优化性能,需要导入到堆(没有聚集键的表)并使用表锁。请参阅MSDNthis discussion thread 了解更多信息。
  • 是的,如果数据库很忙,我会先将它放在临时表中以防止锁定。
  • 我对线程安全的看法是,对这个服务的许多并发调用将向数据库发出保存。这些保存中的任何一个都不应阻止对其他调用的访问,而是允许服务并发执行调用。
【解决方案2】:

感谢您对此问题的意见。我已经开始查看 SqlBulkCopy 但过了一会儿就停止了,因为我需要一个存储过程来处理逻辑附近的数据。
鉴于我可能有许多并发线程到保存数据的服务,我无法用数据填充临时表,然后再从中读取内容。

然后我将注意力转向表值参数并在那里找到了我的答案。我有点惊讶我以前没有尝试过这个,因为它效果很好。在性能数据中,保存时间从大约 45 秒缩短到不到 5 秒!

感谢您为我指明了这个方向。

【讨论】: