Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql-批量加密哈希生成_Sql_Sql Server_Query Optimization - Fatal编程技术网

Sql-批量加密哈希生成

Sql-批量加密哈希生成,sql,sql-server,query-optimization,Sql,Sql Server,Query Optimization,我们正在尝试在我们的ETL过程中实现变更检测 所以我们决定使用 SET a.[HASH] = (SELECT master.dbo.fn_varbintohexsubstring(0, HashBytes('md5', (SELECT TOP 1 * FROM customer_demographics_staging b WHERE b.customer_no = a.customer_no FOR XML RAW)), 1, 0)) FROM cus

我们正在尝试在我们的ETL过程中实现变更检测

所以我们决定使用

SET a.[HASH] = (SELECT 
                    master.dbo.fn_varbintohexsubstring(0, HashBytes('md5', (SELECT TOP 1 * FROM customer_demographics_staging b WHERE b.customer_no = a.customer_no FOR XML RAW)), 1, 0))
FROM customer_demographics_staging a
对于一个有700k条记录和大约140列的表(我们还没有确定更改的列),查询运行了大约半个小时,然后我们取消了它


不管怎样,除了减少查询数量,我们还可以改进这一点吗

有几件事。如果
散列
列的数据类型是
varbinary(20)
,则无需将MD5散列转换为字符串;只需存储散列字节。不过,为了达到这个目的,如果您想使用加密哈希来检测更改,我会使用内联表值函数来获取它。下面是我使用AdventureWorks拼凑的一个示例:

ALTER TABLE [HumanResources].[Employee] ADD [Hash] VARBINARY(20) NULL;
GO
CREATE FUNCTION dbo.CalculateHash(@EmployeeID AS INT)
RETURNS TABLE
AS
    RETURN

    SELECT e.[BusinessEntityID], HASHBYTES('md5', (
        SELECT *
        FROM [HumanResources].[Employee] AS [e2]
        WHERE [e2].[BusinessEntityID] = e.[BusinessEntityID]
        FOR XML RAW
    )) AS [Hash]
    FROM [HumanResources].[Employee] AS [e]
    WHERE [e].[BusinessEntityID] = @EmployeeID

go
SELECT TOP 10 [e].*, ch.[Hash]
FROM [HumanResources].[Employee] AS [e]
CROSS APPLY dbo.[CalculateHash]([e].[BusinessEntityID]) AS [ch]
GO

也就是说,如果是我的话,我根本不会为MD5操心,只使用
CHECKSUM()
函数(可能作为表中的持久计算列)。它支持以本机方式获取多个列(因此不会产生将行序列化为XML的开销)。

与[Ben Thul]已经说过的一样,我也倾向于依赖于
二进制校验和()
,因为它易于使用。 我同意这个函数返回8字节的“但是一个int”,而例如MD5将返回一个两倍于字节数的varbinary(16),这样你就得到了“结果空间”的平方(而不是双精度!),这意味着你最终发生冲突的机会要小得多。但偏执狂我想补充一点,即使如此,MD5值的精确匹配并不意味着您也有相同的(输入)值

老实说,我使用该函数只是为了消除差异。如果校验和(或散列)的结果不同,则可以100%确定值也不同。如果它们是相同的,那么您仍然应该检查源值的整体,以查看是否没有“假匹配”

您的用例似乎是另一种方式:您希望通过删除相同的用例来找到不同的用例,并通过只查看哈希代码来缩短后者。老实说,我不喜欢这种方法,因为您可能会遇到冲突,导致暂存表中的“已更改”记录获得与旧记录完全相同的哈希值,从而在复制更改时被忽略。再说一次,机会非常小,但正如我所说,在这个问题上,我是偏执狂=)

如果您希望继续沿着这条路走下去,请注意:

  • HashBytes
    仅支持8000字节的输入。考虑到XML语法增加的开销,您可能会在处理这140列时遇到麻烦
  • 在将
    HashBytes
    的结果写入表之前,我看不出有任何(好的)理由将其转换为其他内容
  • 虽然XML的
    速度非常快,但是
    CONCAT
    是否也同样快,同时会产生“更小”的结果(参见第1点)?我同意,它带来了它自己的一系列问题,比如当field1、field2、field3是“hello”时,“world”将产生与“hello”、“world”相同的结果,你可以通过
    CONCAT
    -同时处理每个字段的
    LEN()。。。不确定我们还剩下多少收益=)
  • 我猜您已经有了它,但是在staging表中的
    customer\u no
    字段上是否有索引,最好是唯一的和聚集的

看起来真不错。我会试一试,让你知道。关于校验和的使用,文档中提到,当值更改时,校验和可能不会更改,因此对于更改检测来说并不理想。这是我们的第一个选择。我认为这只是一个CYA,因为任何哈希算法都会有冲突(包括MD5)。您还可以向表中添加
rowversion
列,并完全跳过计算。rowversion将无法工作,因为我们正在使用ssis从oracle数据库提取数据。感谢您提出的非常有效的观点。实际上,我们决定使用concat,并限制要跟踪的列数(同时确保每次都保持顺序)。我们不使用LEN,而是对每一列进行分隔。我们将放弃对varchar的转换,转而使用原始字节,因为它被多次提升。