SqlBulkCopyerror handling/继续错误

我试图将大量数据插入SQL服务器。 我的目标表有一个名为“Hash”的唯一索引。

我想用SqlBulkCopy替换我的SqlDataAdapter实现。 在SqlDataAapter中有一个名为“ContinueUpdateOnError”的属性,当设置为true时,adapter.Update(table)将插入所有可能的行并使用RowError属性标记错误行。

问题是我如何使用SqlBulkCopy尽可能快地插入数据,同时跟踪哪些行被插入以及哪些行没有(由于唯一索引)?

以下是其他信息:

  1. 该过程是迭代的,通常按计划重新设定。

  2. 源表和目标表可能很大,有时可能有数百万行。

  3. 尽管可以首先检查哈希值,但每行需要两个事务(首先从目标表中选择哈希,然后执行插入)。 我认为在adapter.update(table)的情况下,检查RowError比检查每行的哈希命中要快。

SqlBulkCopy具有非常有限的error handlingfunction,默认情况下它甚至不检查约束。

但是,它速度快,真的非常快。

如果要解决重复键问题,请确定批处理中哪些行是重复的。 一种选择是:

  • 开始转
  • 在表格上抓一个tablockx选择所有当前的“Hash”值并将它们放入HashSet中。
  • 过滤掉重复项并报告。
  • 插入数据
  • commit tran

如果要插入大型集合并且表中初始数据的大小不是太大,则此过程将有效。

您能否请扩展您的问题以包括问题的其余部分。

编辑

现在我在这里有更多的上下文是你可以采取的另一种方式:

  • 将批量插入放入临时表中。
  • 启动serializable tran
  • 选择目标表中已有的所有临时行…报告它们
  • 将临时表中的数据插入到真实表中,在哈希上执行左连接并包括所有新行。
  • 提交tran

这个过程在往返旅行中非常轻松,并且考虑到你的规格应该最终真的很快;

与已经提出的方法略有不同; 执行SqlBulkCopy并捕获抛出的SqlException

  Violation of PRIMARY KEY constraint 'PK_MyPK'. Cannot insert duplicate key in object 'dbo.MyTable'. **The duplicate key value is (17)**. 

然后,您可以从ID 17(第一个重复的记录)中删除源中的所有项目。 我在这里做的假设适用于我的情况,可能不适合你的情况; 即复制是由上载过程中由于SQL /网络错误导致的先前失败的SqlBulkCopy完全相同的数据引起的。

注意:这是对Sam的回答的回顾,稍微详细一些

感谢Sam的回答。 由于评论的空间限制,我已经把它放在了答案中。

从你的答案中得出我看到两种可能的方法:

解决方案1:

  • 开始转
  • 通过“在目标表中选择哈希值来获取所有可能的”哈希“值,其中哈希值为(val1,val2,…)
  • 过滤掉重复和报告
  • 插入数据
  • commit tran

解决方案2:

  • 创建临时表以镜像目标表的模式
  • 批量插入临时表
  • 启动可序列化的事务
  • 获取重复的行:“从tempTable中选择hash,其中tempTable.hash = destinationTable.hash”
  • 报告重复的行
  • 将temp表中的数据插入目标表:“select * into destinationTable from temptable left join temptable.hash = destinationTable.hash where destinationTable.hash is null”
  • 提交tran

既然我们有两种方法,那么归结为哪种方法最优化? 两种方法都必须检索重复的行和报告,而第二种方法需要额外的:

  • 临时表创建和删除
  • 再一个sql命令将数据从临时表移动到目标表
  • 取决于哈希冲突的百分比,它还会通过网络传输大量不必要的数据

如果这些是唯一的解决方案,在我看来,第一种方法获胜。 你们有什么感想? 谢谢!