通过Dapper批量插入比逐行插入行慢

时间:2017-01-16 11:06:04

标签: .net sql-server dapper batch-insert

我正在使用Dapper将数据从实时源插入到Sql Server中,所以我关心性能。最近,我发现了一些奇怪的事。
开箱即用,如果你给Dapper一个集合和一个插入查询,它会触发每个元素的insert语句。我的测试表明,我可以通过这种方式在1秒内插入大约1800个具有12个字段的对象(仅计算connection.Execute(...)运行时间。
现在,我没有在Dapper中找到批量插入功能并实现了我自己的(构造参数列表和SQL查询)。之后,我发现我只能在大约3秒钟内插入一个批次(限制为1000行)(再次,只计算connection.Execute(...)次来电。 因此,这使得我的批处理几乎慢6倍比在单独的查询中发送每一行。有人可以向我解释一下吗?我以为人们使用批量操作来加快这个过程 我想最多插入时间为1秒。 我使用本地网络上的Sql Server 2012 Standard。我插入的表只在主键上有聚簇索引(bigint字段),没有非聚簇索引和触发器。
我可以发布代码,但没有什么特别的

2 个答案:

答案 0 :(得分:2)

如果您希望获得最佳性能,我不确定您使用Dapper Execute扩展方法的原因。

以最佳性能插入的最佳免费方式是直接使用SqlBulkCopy类。

免责声明:我是该项目的所有者Dapper Plus

该项目为以下操作提供了简便的支持:

  • BulkInsert
  • BulkUpdate
  • BulkDelete
  • BulkMerge

示例:

// CONFIGURE & MAP entity
DapperPlusManager.Entity<Order>()
                 .Table("Orders")
                 .Identity(x => x.ID);

// CHAIN & SAVE entity
connection.BulkInsert(orders)
          .AlsoInsert(order => order.Items);
          .Include(x => x.ThenMerge(order => order.Invoice)
                         .AlsoMerge(invoice => invoice.Items))
          .AlsoMerge(x => x.ShippingAddress);   

答案 1 :(得分:0)

理想的批处理大小可能因服务器而异,关键因素是日志记录,这将影响插入资源的密集程度以及在看到性能下降之前批量生成的大小。

快速插入/更新的关键是确保您满足最小日志记录的要求,请查看此Microsoft White Paper。不要惊慌 - 你不需要阅读所有内容 - 查看描述满足'最小日志记录'的条件的表格(你需要与你的DBA交谈)。

一旦你获得了尽可能少的日志记录,那么你需要查看SPOOLS的执行计划,如果一个批处理开始假脱机到Tempdb,那么你将会出现急剧减速。关键是要使批处理足够小以保留在缓冲区(RAM)中。但是可用的缓冲区空间量将取决于其他进程。

注意:TABLOCK与TABLOCKX不同。