什么是更新数千条记录的最有效方法

时间:2015-02-04 21:50:21

标签: c# sql sql-server

我们有一个C#应用程序,用于解析文本文件中的数据。然后,我们必须根据文本文件中的信息更新sql数据库中的记录。将数据从应用程序传递到SQL服务器的最有效方法是什么?

我们当前使用分隔字符串,然后遍历存储过程中的字符串以更新记录。我也在使用TVP(表值参数)进行测试。还有其他选择吗?

我们的文件包含数千条记录,我们希望解决方案花费最少的时间。

2 个答案:

答案 0 :(得分:2)

请不要使用DataTable因为只是浪费CPU和内存而没有任何好处(除了可能熟悉之外)。在回答以下问题时,我已经详细介绍了一种非常快速和灵活的方法,这与以下问题非常类似:

How can I insert 10 million records in the shortest time possible?

该答案中显示的示例仅适用于INSERT,但可以轻松调整以包含UPDATE。此外,它一次性上传所有行,但也可轻松调整为X数量的记录设置计数器,并在传入许多记录后退出IEnumerable方法,并且一旦没有更多记录,则关闭文件。这将需要将文件指针(即流)存储在静态变量中以继续传递给IEnumerable方法,以便它可以在下一次的最近位置被提前并拾取。我有一个这个方法的工作示例,如下面的答案所示,虽然它使用SqlDataReader作为输入,但技术是相同的,只需要很少的修改:

How to split one big table that has 100 million data to multiple tables?

从某种角度来看,50k的记录甚至还不接近"巨大的"。我一直在使用我在这里显示的400万行文件的方法上传/合并/同步数据,并且打了几千万行(或更多行)。


的事情:

  • 使用DataTable:正如我所说,如果您只是为了与TVP一起使用它,那就是浪费CPU,内存和时间。
  • 同时进行1次更新(如问题评论中所示):这太疯狂了。关系数据库引擎经过大量调整,可以最有效地使用集合,而不是单例操作。 50k插入物甚至不比每个100行的500个插入物更有效。单独进行只是保证了桌面上的更多争用,即使只是行锁(它是100k锁定+解锁操作)。可能比升级到表锁的单个50k行事务更快(正如Aaron所提到的那样),但这就是为什么你以较小的批量进行,只要小而不是指1行;)。
  • 任意设置批量大小。保持在5000行以下有助于减少锁定升级的可能性,但不要只选择200.尝试几种批量(100,200,500,700,1000)并尝试每次几次。您将看到最适合您系统的内容。只需确保批量大小可通过 app.config 文件或其他方式(数据库中的表,注册表设置等)进行配置,以便无需重新部署代码即可对其进行更改
  • SSIS(功能强大,但非常笨重,无法调试)

有效的东西,但不像正确完成的TVP那样灵活(即传递返回IEnumerable<SqlDataRecord>的方法)。这些都没问题,但为什么要将记录转储到临时表中,只是为了在内联时将它们解析到目的地?

  • BCP / OPENROWSET(BULK ...)/ BULK INSERT
  • .NET&#39; SqlBulkCopy

答案 1 :(得分:0)

在我看来,最好的方法是创建一个临时表,然后使用SqlBulkCopy插入到临时表(https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy%28v=vs.110%29.aspx),然后只需根据临时表更新表。

根据我的测试(使用Dapper和LINQ),作为批量或批量更新比仅创建临时表并向服务器发送命令以基于临时表更新数据花费的时间更长。这个过程更快,因为SqlBulkCopy以快速方式本地填充数据,其余部分在SQL服务器端完成,经过较少的计算步骤,此时的数据驻留在服务器端。