【问题标题】:Binary_Checksum Vs HashBytes functionBinary_Checksum 与 HashBytes 函数
【发布时间】:2017-04-03 11:20:21
【问题描述】:

我有一个复杂的查询,它使用了很多二进制校验和函数,当我用一些测试数据对两个不同的记录进行测试时,它实际上返回了相同的校验和值。请在下面找到我使用的测试数据

SELECT BINARY_CHECKSUM(16   ,'EP30461105',1) AS BinaryCheckSumEx UNION ALL
SELECT BINARY_CHECKSUM(21   ,'EP30461155',1) AS BinaryCheckSumEx

现在我正在尝试将 HASHBYTES 函数与“MD5”算法一起使用,我可以确定获得唯一记录,但现在我担心的是,在当前查询中,我使用“校验和”值加入我的 '合并'语句以查找新记录。由于“HashBytes”返回给我 Varbinary 数据类型,当我用“HashByte”字段替换连接条件时,我可以预期多少性能开销。

SELECT HASHBYTES('MD5', CONCAT(Col1,Col2,Col3,Col4,..))

此外,我需要为多个列创建散列,在这种情况下,我需要一个额外的 Concat 函数,这会对我的性能产生额外的开销。

【问题讨论】:

  • 标记您正在使用的 dbms。该功能是特定于产品的。
  • 校验和不是加密哈希,对于唯一标识数据没有用处。还要考虑concat('abc', 'd')concat('a', 'bcd') 的哈希值是一样的。
  • 您是否肯定没有散列的查询 - 即可以优化和利用索引的查询实际上比散列和比较效率低?
  • @AlexK。我很确定,当连接返回相同的值时,我不会期望多列的这种连接情况。
  • @AlexK。我们尝试使用哈希值或校验和值的主要原因是在合并语句中使用它来查找是否创建了任何新记录(基于目标表中的组字段)。如果我切换到 HashBytes,我必须将连接条件字段从“int”更新为“varbinary”,这对我的性能有多大影响是我的查询。

标签: sql sql-server-2012 database-performance checksum hashbytes


【解决方案1】:

以下是选项:

  1. 使用哈希索引作为 VARBINARY

  2. 使用 BINARY_CHECKSUM 和 CHECKSUM

    • 这很好,但问题是校验和重复的可能性很高,而且当您使用 Google 搜索时,您会发现很多人都对此有疑问。

但是,校验和不会改变的可能性很小。 因此,我们不建议使用 CHECKSUM 来检测是否 除非您的应用程序偶尔可以容忍,否则值已更改 错过了一个变化。考虑改用 HashBytes。当一个 MD5 哈希 算法被指定,HashBytes 返回的概率 两个不同输入的相同结果远低于 校验和。

来源:https://msdn.microsoft.com/en-us/library/ms189788(v=SQL.100).aspx

  1. 将 HASBYTES 转换为 BIGINT 并在其上有索引
    • 这不是个好主意

我也会小心将散列值转换为 BIGINT 鉴于 BIGINT 只有 8 个字节,但所有散列算法 - 甚至 MD5 -- 大于 8 字节(MD5 = 16 字节,SHA1 = 20,SHA2_256 = 32 和 SHA2_512 = 64)。并转换大于 8 字节的二进制值 到 BIGINT 会悄悄地截断这些值。因此,您会失去准确性和 增加误报的发生率。以下查询显示 这种行为:

SELECT CONVERT(BIGINT, 0xFFFFFFFFFFFFFF),      --  7 bytes = 72057594037927935
       CONVERT(BIGINT, 0xFFFFFFFFFFFFFFFF),    --  8 bytes = -1
       CONVERT(BIGINT, 0xFFFFFFFFFFFFFFFFFF),  --  9 bytes = -1
       CONVERT(BIGINT, 0xFFFFFFFFFFFFFFFFFFFF) -- 10 bytes = -1

来源:https://dba.stackexchange.com/questions/154945/index-maintenance-for-varbinary

  1. 将 HASHBYTES 转换为 VARCHAR 并在其上有索引
    • 这是不错的选择
    • 您有两种选择:​​i>

a) 如果您使用的是 SQL 2008 或更高版本

SELECT CONVERT(NVARCHAR(32),HashBytes('MD5', CONTENT),2)

b) 如果您使用的是 SQL 2005

SELECT SUBSTRING(master.dbo.fn_varbintohexstr(HashBytes('MD5', CONTENT)), 3, 32)

PS:如果您想知道应该使用哪种哈希算法:

MD5 = 16 bytes
SHA1 = 20 bytes
SHA2_256 = 32 bytes
SHA2_512 = 64 bytes

来源:https://blogs.msdn.microsoft.com/sqlsecurity/2011/08/26/data-hashing-in-sql-server/

对于您的第二个问题,您应该使 Hash 列 PERSISTED,以避免对运行每个查询的影响。

【讨论】:

  • 关于 #1:使用哈希索引作为 VARBINARY - 如果使用 BINARY 会怎样? ... Hashbytes 返回固定大小的结果,因此 binary(16) 足以获得 MD5 哈希结果。它不会比上面列出的任何选项都表现得更好吗?
  • 第二点的来源是CHECKSUM函数。不应该链接到BINARY_CHECKSUM吗?也许您提到的“重复的可能性很高”的警告也需要相应更新。
  • @user2286046 您好,感谢您的评论。相同的逻辑适用于 BINARY_CHECKSUM 。只是谷歌binary_checksum duplicates我更新了第二个选项来澄清
  • 如果我错了,请纠正我,但如果你提到this article,我认为他们错了。他们将BINARY_CHECKSUM 用于nvarchar 类型,但this official article 中明确提到了这一点:BINARY_CHECKSUM supports any length of type varbinary(max) and up to 255 characters of type nvarchar(max). 因此,BINARY_CHECKSUMvarbinary 的有效选项。
  • @user2286046 基于您发送的linkHowever, this change isn't guaranteed, and so to detect whether values have changed, we recommend use of BINARY_CHECKSUM only if your application can tolerate an occasional missed change
猜你喜欢
  • 2015-07-31
  • 2010-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-08
  • 1970-01-01
相关资源
最近更新 更多