Binary_Checksum与HashBytes函数

Pra*_*azz 5 sql checksum database-performance sql-server-2012 hashbytes

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

SELECT BINARY_CHECKSUM(16   ,'EP30461105',1) AS BinaryCheckSumEx UNION ALL
SELECT BINARY_CHECKSUM(21   ,'EP30461155',1) AS BinaryCheckSumEx
Run Code Online (Sandbox Code Playgroud)

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

SELECT HASHBYTES('MD5', CONCAT(Col1,Col2,Col3,Col4,..))
Run Code Online (Sandbox Code Playgroud)

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

DaN*_*eSh 5

以下是选项:

  1. 在散列上使用索引作为VARBINARY

  2. 使用BINARY_CHECKSUM和CHECKSUM

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

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

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

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

考虑到BIGINT只有8个字节,但所有哈希算法-甚至是MD5-都大于8个字节(MD5 = 16个字节,SHA1 = 20,SHA2_256 = 32和SHA2_512),我也将谨慎地将哈希值转换为BIGINT = 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
Run Code Online (Sandbox Code Playgroud)

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

  1. 将HASHBYTES强制转换为VARCHAR并在其上建立索引
    • 这是不错的选择
    • 您有两种选择:

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

SELECT CONVERT(NVARCHAR(32),HashBytes('MD5', CONTENT),2)
Run Code Online (Sandbox Code Playgroud)

b)如果您使用的是SQL 2005

SELECT SUBSTRING(master.dbo.fn_varbintohexstr(HashBytes('MD5', CONTENT)), 3, 32)
Run Code Online (Sandbox Code Playgroud)

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

MD5 = 16 bytes
SHA1 = 20 bytes
SHA2_256 = 32 bytes
SHA2_512 = 64 bytes
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

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

对于第二个问题,应将Hash列设为PERSISTED,以避免对运行每个查询产生影响。