首页 > 代码库 > 校验函数,哈希冲突比你想象的多
校验函数,哈希冲突比你想象的多
在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(N‘us‘,N‘FL‘,N‘Land O Lakes‘),checksum(N‘us‘,N‘FL‘,N‘Land O‘‘ Lakes‘)select binary_checksum(N‘gb‘,N‘c6‘,N‘bude‘),binary_checksum(N‘no‘,N‘‘,N‘myre‘)
校验函数,哈希冲突比你想象的多