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规范……

如果您的数据流未分类以开始或目标是堆,那么我上面的点是静音。

但是,实现最低限度的日志记录仍然是体面性能的必要条件。