首页 > 代码库 > 校验函数,哈希冲突比你想象的多

校验函数,哈希冲突比你想象的多

在SQL Server 2012,有2个校验函数:check_sum 和 binary_check,在一些Data Table中,如果存在多个字符串字段,并且字符串非常长,在比较字符串是否相同时,使用校验函数,将其转换成 int 类型,能够提高数据比较的速度。但是不要忽略 CSDN 官方文档的Caution:使用校验函数,有时不能探测到数据的更新,除非Application能够容忍偶尔的丢失更新。一旦将校验函数用于实际的项目中,你会发现,不是偶尔,而是经常会发生探测不到数据更新的异常:

BINARY_CHECKSUM(*) will return a different value for most, but not all, changes to the row, and can be used to detect most row modifications.

However, there is a small chance that the checksum will not change. For this reason, we do not recommend using CHECKSUM to detect whether values have changed, unless your application can tolerate occasionally missing a change.

由于存在侥幸心理,在项目中使用了校验函数对字符串字段进行比较,代码大致如下:url,why 和 description 字段都是挺长的字符串字段,特别是description,平均长度是1163字符。

;merge target as t using source as s     on t.id=s.idwhen matched     and binary_checksum(t.url,t.why,t.description)            <>binary_checksum(s.url,s.why,s.description)....

大多数情况下,函数工作正常,但是,常在河边走,哪能不湿鞋,在一个周末,领导一个短信,我回来加班了,校验函数不能探测出更新的数据,导致数据同步出现问题,对ScoreCard和绩效影响较大,必须及时修改。

如图,Source 和 target 的Description 字段不一致,但是校验函数:binary_check(url,description,why) 返回的值是相同的,痛定思痛,为了避免以后的数据更新被异常丢失,决定在ETL中不再使用校验函数,而是直接使用字符串进行比对。

技术分享

校验函数对长字符串产生的校验值质量不是很高,那对短的字符串了?经过多次尝试,发现校验函数在短的字符串上更容易出现更新丢失的情况,鉴于校验函数的这些缺点,强烈建议不要在项目中使用校验函数。直接使用字符串进行比较,保证万无一失,相比数据更新出错,数据同步稍稍慢点,更能被容忍。

引用《校验函数:checksum 和 binary_checksum》:

在比较长的字符串时,直接比较会比较慢,使用校验和比较速度会比较高,但是 binary_checksum 和 checksum 产生的校验和的质量比较低,建议不要再项目中使用校验函数。当字符串比较短时,很大可能产生Hash 冲突,例如:下面的脚本返回两行数据,每行的两个column结果相同,相比较而言,使用 checksum 比 binary_checksum效果更好。

--database collation is  SQL_Latin1_General_CP1_CI_ASselect checksum(Nus‘,NFL‘,NLand O Lakes‘),checksum(Nus‘,NFL‘,NLand O‘‘ Lakes)select binary_checksum(Ngb‘,Nc6‘,Nbude‘),binary_checksum(Nno‘,N‘‘,Nmyre‘)

 

校验函数,哈希冲突比你想象的多