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

在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.id
when 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中不再使用校验函数,而是直接使用字符串进行比对。

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

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

--database collation is  SQL_Latin1_General_CP1_CI_AS
select 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‘)
时间: 2025-01-02 02:52:04

校验函数,哈希冲突比你想象的多的相关文章

处理哈希冲突的闭散列方法-线性探测

说到哈希冲突,就必须谈到哈希函数了. 什么时候哈希函数 哈希冲突函数hv(i),用于在元素i发生哈希冲突时,将其映射至另一个内存位置. 什么是哈希冲突 哈希冲突即关键字不同的元素被映射到了同一个内存位置,包括由同义词冲突和非同义词冲突. 处理哈希冲突的方法很多,这里浅谈一下处理哈希冲突的闭散列方法: 线性探测 如下图所示 在上图中,这里key取8. 实现线性探测代码: #pragma once #include<string> enum Status { EXIST, EMPTY, DELET

一次电话Java面试的问题总结(JDK8新特性、哈希冲突、HashMap原理、线程安全、Linux查询命令、Hadoop节点)

面试涉及问题含有: Java JDK8新特性 集合(哈希冲突.HashMap的原理.自动排序的集合TreeSet) 多线程安全问题 String和StringBuffer JVM 原理.运行流程.内部结构 Linux 查询含有某字符串内容的命令grep 查询进程.GC状态.杀死进程 Hadoop五种节点介绍 -----------------------------------------------------------------------------------------------

校验函数:常在河边走,哪能不湿鞋

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

哈希冲突的处理【闭散列方法-线性探测和二次探测】

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构.也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列函数,存放记录的数组叫做散列表. 给定表M,存在函数Hash(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数Hash(key)为哈希(Hash) 函数. 构造哈希表的两种方法 1.直接定址法--取关键字的某个线性函数为散列地

算法学习 - HashTable开放地址法解决哈希冲突

开放地址法解决哈希冲突 线性开放地址法 线性开放地址法就是在hash之后,当发现在位置上已经存在了一个变量之后,放到它下一个位置,假如下一个位置也冲突,则继续向下,依次类推,直到找到没有变量的位置,放进去. 平方开放地址法 平方地址法就是在hash之后,当正确位置上存在冲突,不放到挨着的下一个位置,而是放到第2^0位置,假如继续冲突放到2^1的位置,依次2^3... 直到遇到不冲突的位置放进去. 双散列开放地址法 双散列同上,不过不是放到2^的位置,而是放到key - hash(key, tab

处理哈希冲突的线性探测法

哈希表,是根据关键字(Key value)而直接访问在内存存储位置的数据结构.也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度.这个映射函数称做散列函数,存放记录的数组称做散列表.(摘自维基百科) 对不同的关键字可能得到同一散列地址,即k1!=k2,而f(k1)=f(k2),这种现象称为碰撞(英语:Collision),也叫哈希冲突. 处理哈希冲突的方法有很多种: 闭散列法 开链法(哈希桶) 素数表 字符串哈希算法 在这里我们讨论最简单的闭散

哈希桶处理哈希冲突

哈希桶:哈希桶就是盛放不同key链表的容器(即是哈希表),我们可以把每个key的位置看作是一个指针,该指针所指向的位置里放了一个链表,可以认为是指针数组,故该方法也叫开链式. 相比闭散列,哈希桶提高了空间利用率:在实现哈希表时,常见的方法是线性探测.二次探测,这两个算法的具体实现可以查看我的博客.但是这两个算法有一个共同点就是:空间利用率低.为什么这么说呢?线性探测.二次探测的高效性很大程度上要取决于它的载荷因子,载荷因子即:存放关键字个数 / 空间大小. 通过查阅资料,我发现,使用素数做除数可

哈希冲突

两个不同的Key,得到相同的hash值,而一个下标只能存放一个Key,这就产生了哈希冲突(这里的Key和hashMap原理key-value中的key是不同的,key-value是一对值,而Key是独立的一个值),冲突后Key就必须通过别的方法找到属于自己的存放位置. 开放定址法 根据增量不断地往后找可以存放当前Key的位置,增量的取法: 线性取值,1,2,3....这样,也就是从冲突位置不断往后找下一个可以存放的位置 二次取值,1,4,9....这样,也就是从冲突位置不断往后找x的二次方的下标

【数据结构】处理哈希冲突的开链法(哈希桶)算法实现

实现哈希表时,我们常见的方法是线性探测.二次探测,这两个算法也很简单.若有兴趣,可以查看我的博客.但是,这两个算法有一个共同点就是:空间利用率低.为什么这么说呢?线性探测.二次探测的高效性很大程度上要取决于它的载荷因子,载荷因子即:存放关键字个数/空间大小. 通过查阅资料,我发现,使用素数做除数可以减少哈希冲突(具体原因不详,大师专研的,发现很好用,就在这里分享给大家).见下: ----素数表 // 使用素数表对齐做哈希表的容量,降低哈希冲突 const int _PrimeSize = 28;