【问题标题】:Preventing deadlock in "INSERT IF NOT EXISTS" in SSIS防止 SSIS 中“如果不存在则插入”中的死锁
【发布时间】:2013-11-05 16:57:09
【问题描述】:

我正在尝试将数据插入数据库,但首先我使用查找来检查每一行是否存在,类似于此处建议的方法: How to prevent SSIS from importing data from a file that already exist in database?

SELECT DISTINCT VALUES    // OleDb Source
         |
       LOOKUP             // If exists
         |                // No Match Output
  OLE DB DESTINATION      // Insert new records

我正在使用RetainSameConnection=True 在我的工作流程中启用事务。使用大约 10,000 行的默认缓冲区,当行传递到 OLE DB 目标时,目标 INSERT 将使用查找 SELECT 锁定。

我已经尝试过SET READ_COMMITTED_SNAPSHOT ON,它会起作用,但是现在查找期间的性能非常慢,我认为这是由于 RetainSameConnection 属性,我无法判断 SSIS 甚至使用了 READ COMMITTED SNAPSHOT隔离级别。我考虑过忽略目标上的失败,但我读到它会导致批量插入完全失败,而不是逐行失败。我也考虑过在所有读取中使用 NOLOCK,但它会将我的所有查找转换为 SQL 查询。

源数据库可能读取数百万行。 有没有更好的方法来做到这一点?

【问题讨论】:

  • 您为查找选择了什么缓存?您如何配置 ole db 目标?您的来源可以在内部有重复项吗?我看到您应用了DISTINCT,但是查找是否可以为同一集中的不同行生成相同的键?您的源与目标中的数据量是多少?

标签: sql-server ssis sql-server-2012


【解决方案1】:

这个问题正在进入一个领域,答案将更多地基于偏好和经验,而不仅仅是一种容易定义的方法。可能会有很多答案会显示可能对您有用的不同方法,但其中任何一个的基础都将基于几件事

  1. 减少在数据流任务预缓存期间保存在查找中的行数

    一般来说,在数据流开始执行之前填充所有查找的值,并根据查找的配置从源读取数据。如果您以这种方式配置了 SSIS,那么无论隔离级别如何,查找和将行插入到表中都不应存在任何争用。

    根据您上面所说的,我认为查找的性能可能不会因为您的配置而发生巨大变化,而是因为缓存到查找中的数据量随着每次执行而增加。

  2. 更改查找模式以使用不同的模式

    查找的最基本实现通常适用于大多数情况。但是,如果性能是包执行的重中之重,那么可能还有其他更理想的方法来实现相同的目标。我在博客中谈到的其中一个是指使用合并连接作为标准查找的替代方法。这可能不适合您的情况,因为我设计了这个特殊的策略来涵盖涉及大型数据集的极端案例,但希望它能给您一些想法。

    我在下面的链接中对该模式进行了相当详细的演练

    https://web.archive.org/web/20140819083150/http://bigdatabigdave.info/archive/2013/02/15/alternate-ssis-lookup-pattern-merge-join/

【讨论】:

  • 我可以看到一个合并连接替换了常规查找,但在上述情况下,我没有选择任何列,只是将它用于“如果不存在则插入”,我看不到它是怎么回事适用。
  • @WillEddins 除了添加一个额外的列之外,查找和现有查找在功能上没有区别。就方法而言,它们非常相似。此处仅将其作为替代查找模式的示例来说明这一点。
【解决方案2】:

我记得有一个地方他们将所有插入行都写到了一个原始文件中。然后有第二个数据流(在第一个数据流完成后)将原始文件记录插入到目标表中。

【讨论】:

    猜你喜欢
    • 2017-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-27
    • 2016-01-18
    • 1970-01-01
    相关资源
    最近更新 更多