SQL Server 2005中的CHECKSUM()冲突

Cad*_*oux 9 sql checksum sql-server-2005 hash-collision

我有一个5,651,744行的表,主键由6列(int x 3,smallint,varchar(39),varchar(2))组成.我希望使用此表和另一个共享此主键的表以及添加的另一列但具有37m行来提高性能.

在预期添加列以创建哈希键时,我进行了分析并发现了18,733次冲突.

SELECT  SUM(CT)
FROM    (
         SELECT HASH_KEY
               ,COUNT(*) AS CT
         FROM   (
                 SELECT CHECKSUM(DATA_DT_ID, BANK_NUM, COST_CTR_NUM,
                                 GL_ACCT_NUM, ACCT_NUM, APPN_CD) AS HASH_KEY
                 FROM   CUST_ACCT_PRFTBLT
                ) AS X
         GROUP BY HASH_KEY
         HAVING COUNT(*) > 1
        ) AS Y

SELECT  COUNT(*)
FROM    CUST_ACCT_PRFTBLT
Run Code Online (Sandbox Code Playgroud)

它差不多两倍 BINARY_CHECKSUM()

考虑到我所覆盖的目标空间的相对较小量,这看起来是否太高(.33%)?如果碰撞很高,那么在连接中加入这个制造的密钥是否有利于每行额外4个字节的成本,因为你仍然必须加入常规列来处理偶尔的碰撞?

HLG*_*GEM 7

我没有看到添加校验和的位置会让你得到任何级别的collisons.即使1次碰撞也太多,因为它会导致您加入错误的数据.如果你不能保证加入正确的记录,那么如果它提高性能但是数据完整性混乱则毫无意义.这似乎是财务数据,因此您最好确保您的查询不会返回错误结果.如果发生任何冲突,您实际上最终可能会记入借记或记入错误的帐户.

如果你选择这条路线,Marc是正确的,如果可能的话,你应该预先计算(添加一个必须发生在数百万记录表中的每个记录的计算,不太可能提高我的经验).可能如果您可以执行预先计算的列(并且您需要触发器以使其保持更新),那么您可能不需要连接到所有其他六列以确保没有冲突.那么可能你可能会有更好的表现.你所能做的只是测试你的理论.但请确保您没有任何碰撞.

您是否考虑使用代理键,然后在六个自然键字段上使用唯一索引?然后你可以加入代理键,这可能会提高性能.连接六列(一个varchar)而不是一个代理键是无效的.我从数据的大小中意识到,这可能比非生产系统更难重构,但实际上值得花时间来永久修复持久性性能问题.只有你可以说这是一个多么复杂的变化,以及将所有sps或查询更改为更好的连接有多难.但是,尝试可能是可行的.


Eri*_*ric 6

到目前为止,我看到的很多人都是因为微软自己的承认而遭遇了CHECKSUM大量的冲突.它甚至更糟糕,它有相当大的有意义的碰撞.MD5

如果你希望得到一个哈希列,可以考虑使用HASHBYTESSHA1指定. SHA1MD5or 相比,碰撞的意义要小得多CHECKSUM.因此,CHECKSUM永远不应该用来确定行是否唯一,而是快速检查两个值的保真度.因此,您的碰撞率应为0%HASHBYTES,除非您有重复的行(作为PK,不应该发生).

请记住,HASHBYTES将截断大于8000字节的任何内容,但是你的PK比那个(所有连接的)少得多,所以你不应该有任何麻烦.