SqlBulkCopy性能
我正在努力提高批量负载的性能; 100多万条记录+每日。
我把它移到了使用IDatareader
接口来代替数据表,并且确实获得了显着的性能提升(每分钟500,000条记录)。 目前的设置是:
- 用于解析分隔文件的自定义缓存读取器。
- 将流读取器包装在缓冲流中。
- 一个自定义对象读取器类,它枚举对象并实现
IDatareader
接口。 - 然后
SqlBulkCopy
写入服务器
大部分性能瓶颈直接在SqlBulkCopy.WriteToServer
。 如果我对该过程进行unit testing,但仅排除WriteToServer
该过程大约在1分钟内返回。 WriteToServer
还需要15分钟+。 对于unit testing,它位于我的本地计算机上,因此数据库存在相同的驱动器,因此不必通过网络复制数据。
我正在使用堆表(没有索引;聚集或非聚集;我已经玩过各种批量大小而没有性能上的重大差异)。
有必要减少加载时间,所以我希望有人可能现在可以从这个开局中挤出更多的血液。
为什么不直接使用SSIS?
无论如何,如果你从解析到IDataReader进行了一次treaming,你已经走在了正确的道路上。 要优化SqlBulkCopy本身,您需要将注意力转向SQL Server。 关键是最少记录的操作。 您必须阅读这些MSDN文章:
- 批量导入中最小日志记录的先决条件 。
- 优化批量导入性能 。
如果您的目标是B-Tree(即聚簇索引表),那么不能声明性能批量插入的最重要原则之一,即排序输入行集。 这很简单,ADO.Net SqlClient没有等效的SSPROP_FASTLOADOPTIONS -> ORDER(Column)
(OleDb)。 由于引擎不知道数据已经排序,因此它会在计划中添加一个排序运算符,除非它溢出,否则不会那么糟糕。 为避免溢出,请使用小批量(~10k)。 看看我原来的观点:所有这些只是在SSIS中设置的选项和点击,而不是挖掘OleDB MSDN规范……
如果您的数据流未分类以开始或目标是堆,那么我上面的点是静音。
但是,实现最低限度的日志记录仍然是体面性能的必要条件。