10

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

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

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

以下是附加信息:

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

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

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

4

3 回答 3

7

SqlBulkCopy 的错误处理功能非常有限,默认情况下它甚至不检查约束。

但是,它很快,真的很快。

如果您想解决重复键问题,并确定批次中哪些行是重复的。一种选择是:

  • 开始翻译
  • 抓住桌子上的一个 tabblockx 选择所有当前的“哈希”值并将它们夹在一个 HashSet 中。
  • 过滤掉重复项并报告。
  • 插入数据
  • 提交翻译

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

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

编辑

现在我有了更多的上下文,这是您可以解决的另一种方法:

  • 将批量插入临时表。
  • 启动可序列化的 tran
  • 选择目标表中已经存在的所有临时行...报告它们
  • 将临时表中的数据插入到真实表中,对散列执行左连接并包括所有新行。
  • 提交 tran

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

于 2009-06-17T01:05:04.163 回答
4

与已经建议的方法略有不同;执行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

于 2014-06-10T16:08:56.197 回答
1

注意:这是对 Sam 的回答的回顾,其中包含更多细节

感谢山姆的回答。由于评论的空间限制,我已将其放入答案中。

根据您的回答,我看到了两种可能的方法:

解决方案1:

  • 开始翻译
  • 通过执行“在目标表中选择哈希,其中哈希在(val1,val2,...)
  • 过滤掉重复并报告
  • 插入数据
  • 提交翻译

解决方案2:

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

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

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

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

于 2009-06-18T01:08:11.743 回答