我们有一个C#应用程序,用于解析文本文件中的数据.然后,我们必须根据文本文件中的信息更新sql数据库中的记录.将数据从应用程序传递到SQL服务器的最有效方法是什么?
我们当前使用分隔字符串,然后循环存储过程中的字符串以更新记录.我也在使用TVP(表值参数)进行测试.还有其他选择吗?
我们的文件包含数千条记录,我们希望解决方案花费最少的时间.
最佳答案 请不要使用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?
从某种角度来看,5万条记录甚至都不是“巨大的”.我一直在使用我在这里显示的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的SqlBulkCopy