在SSIS中查找更新的记录 - 要哈希还是不哈希?

时间:2016-06-17 15:49:04

标签: ssis

我正在使用SSIS将数据从DB2数据库中的表迁移到我们的SQL Server数据库。我从中提取数据的表包含了相当数量的数据 - 少于100,000条记录;但是,它也有46列。

我只想更新需要更新的行,因此我得出结论,我可以使用查找转换并检查所有46列并重定向“无匹配”以在SQL表上更新。或者,在我在数据任务流开始时读取数据后,我可以对数据集中的每一行进行散列,然后,在确定行是否相等时,稍后使用散列值作为比较。 / p>

我的问题是:哪条路线更好?我喜欢哈希,但我不确定这是否是最好的选择。有没有人有他们想分享的任何智慧珍珠?

1 个答案:

答案 0 :(得分:5)

为什么不两者?

一般来说,在进行增量加载时我们会寻找两件事:这是否存在?如果它存在,它是否已更改。如果只有一列,那就很简单了。当要检查的列很多时,这就变得非常痛苦,尤其是当您使用SSIS映射所有这些列和/或必须处理担心NULL时。

我通过作弊来解决多列问题 - 我在所有表中创建了两列:HistoricalHashKey和ChangeHashKey。历史哈希键将是所有业务键。更改哈希键是所有其他材料列(我将排除审计列之类的内容)。我们不会直接在哈希列中存储连接值。相反,“我们将数学中的东西用于它”并应用称为SHA-1的散列算法。该算法将获取所有输入列并返回20字节输出。

使用这种方法有三个注意事项。您必须每次以相同的顺序连接列。这些将区分大小写。尾随空间非常重要。就是这样。

在表中,您可以将两列添加为二进制(20)NOT NULL。

设置

您的控制流程看起来像这样

Control Flow

并且您的数据流如此

Data Flow

OLESRC增量数据

(假设我来自Adventureworks2014,Production.Product)我将使用SQL Server 2012+中的CONCAT函数,因为它将所有数据类型提升为字符串并且是NULL安全的。

SELECT
    P.ProductID
,   P.Name
,   P.ProductNumber
,   P.MakeFlag
,   P.FinishedGoodsFlag
,   P.Color
,   P.SafetyStockLevel
,   P.ReorderPoint
,   P.StandardCost
,   P.ListPrice
,   P.Size
,   P.SizeUnitMeasureCode
,   P.WeightUnitMeasureCode
,   P.Weight
,   P.DaysToManufacture
,   P.ProductLine
,   P.Class
,   P.Style
,   P.ProductSubcategoryID
,   P.ProductModelID
,   P.SellStartDate
,   P.SellEndDate
,   P.DiscontinuedDate

,   P.rowguid
,   P.ModifiedDate

-- Hash my business key(s)
,   CONVERT(binary(20), HASHBYTES('MD5',
            CONCAT
            (
            -- Having an empty string as the first argument
            -- allows me to simplify building of column list
                ''
            ,   P.ProductID
            )
        )
    ) AS HistoricalHashKey

-- Hash the remaining columns
,   CONVERT(binary(20), HASHBYTES('MD5',
            CONCAT
            (      
                ''
            ,   P.Name
            ,   P.ProductNumber
            ,   P.MakeFlag
            ,   P.FinishedGoodsFlag
            ,   P.Color
            ,   P.SafetyStockLevel
            ,   P.ReorderPoint
            ,   P.StandardCost
            ,   P.ListPrice
            ,   P.Size
            ,   P.SizeUnitMeasureCode
            ,   P.WeightUnitMeasureCode
            ,   P.Weight
            ,   P.DaysToManufacture
            ,   P.ProductLine
            ,   P.Class
            ,   P.Style
            ,   P.ProductSubcategoryID
            ,   P.ProductModelID
            ,   P.SellStartDate
            ,   P.SellEndDate
            ,   P.DiscontinuedDate
            )
        )
    ) AS ChangeHashKey
FROM
    Production.Product AS P;

LKP检查存在

此查询将从我们的参考表中撤回存储的HistoricalHashKey和ChangeHashKey。

SELECT
    DP.HistoricalHashKey
,   DP.ChangeHashKey
FROM
    dbo.DimProduct AS DP;

此时,比较HistoricalHashKeys以确定行是否存在是一件简单的事情。如果我们匹配,我们希望将ChangeHashKey拉回到我们的数据流中。按照惯例,我将此lkp_ChangeHashKey命名为与源ChangeHashKey区分开来。

CSPL变更检测

条件分割也被简化了。两个Change Hash键匹配(无更改)或不更改(已更改)。那个表达式是

ChangeHashKey == lkp_ChangeHashKey

OLE_DST StagedUpdates

不是使用OLE DB命令,而是创建一个专用表来保存需要更新的行。 OLE DB命令在发布单例更新命令的幕后不能很好地扩展。

SQL执行基于集的更新

数据流完成后,需要更新的所有数据都将在我们的临时表中。此执行SQL任务只是更新我们业务键上的现有数据匹配。

UPDATE
    TGT
SET
    Name = SRC.name
,   ProductNumber = SRC.
FROM
    dbo.DimProduct AS TGT
    INNER JOIN
        Stage.DimProduct AS SRC
        ON SRC.HistoricalHashKey = TGT.HistoricalHashKey;
        -- If clustered on a single column and table is large, this will yield better performance
        -- ON SRC.DimProductSK = TGT.DimProductSK;

来自评论

为什么我使用专用的INSERTUPDATE语句,因为我们有闪亮的MERGE?除了不容易记住语法之外,SQL Server实现可以有一些...... unintended consequences。它们可能是角落 ish 的情况,但我宁愿不用我提供的解决方案遇到它们。明确的INSERT和UPDATE语句为我提供了我想要并在我的解决方案中需要的精细控制。我喜欢SQL Server,认为它是一个很棒的产品,但是他们奇怪的语法加上已知的错误使我无法在任何地方使用MERGE,只有认证考试。