优秀的编程知识分享平台

网站首页 > 技术文章 正文

数据迁移中使用哈希函数做相等性校验

nanyue 2025-07-23 17:17:04 技术文章 4 ℃

问题

数据迁移是个常见任务,其中最为棘手的是数据合并,即不存在的进行新增,存在的如果发生更新则进行修改(未更新则不修改),不存在的删除。这个任务在构建数据仓库ETL的过程中变得尤为重要。

办法

  1. 如果数据源支持CDC(数据变更捕获)那解决办法显而易见。(本篇不做介绍)

  2. 全量删除然后新增。(不好的办法,缺点是性能低下,要额外处理数据仓库维度代理键的生成问题,会产生大量不必要的事务日志)

  3. 数据源中有last_update_date等类似字段。使用这个字段判断是否数据被修改。(实际情形很多数据源不具有这个字段,本篇也不做介绍)

  4. 使用精确的逐个字段的比对方法。(本篇重点介绍,主要针对修改数据的同步)

举例子来说明

先创建一个Staging表,用于原始数据暂存



在创建一个真实表,用于存放同步以后的数据。(代码类似,不再赘述)



然后我们修改了Staging_Test表中的数据来模拟数据发生了变更


现在我们来同步Test表的数据,这里有些偷懒的办法就是只要Key是想等的整行都进行更新。但这种做法有个很大的问题,如果数据量成百上千万,这些数据每次同步时候可能只有几百条数据进行了更新,那下面的代码将产生不必要的海量事务日志,如果在一个并发读取量较大的场景下,会导致表锁,影响读取性能。


负责任的程序员会进行一个小改进,在链接条件里面增加每一个字段的对比,如果有值发生了更改才执行更新。这避免了无脑更新,但是如果这个表的字段非常多,拼写这种字段对比的代码很无趣,同时也存在性能问题,这段代码的执行速度会显著下降。



我们想继续改进这段代码,我们想到可以使用哈希函数来对多个字段值生成一段唯一的哈希码,用这个码来取代逐个的字段对比。因为哈希函数的特点就是任何一点更改就会导致生成的哈希码发生变化。当然我现在使用的SQL代码进行演示,所以也会使用SQL里面的哈希函数,以SQLServer为例,能够生成哈希码的函数有两种,CHECKSUM,HASHBYTES。 因为CHECKSUM在微软官方文档中写明不能保证其唯一性,所以在数据对比更新场景下,最好是不用。我们采用唯一性更高的HASHBYTES函数。



总结

  • 使用多列的值组合来生成哈希值简化了列对比逻辑,同时提升了性能。因为HASHBYTES只能接受单个varchar,nvarchar值,所以拼接的无聊代码还是存在,有的人为了复用这个逻辑写了自定义函数调用表的元数据来拼接这段代码,最终使用动态SQL拼接方式来进行目标表的更新。

  • CHECKSUM可以用在较低长度的字段值校验上,因为他容量小,产的的哈希值可能发生碰撞,即不同的值生成相同的哈希值。这样在要求精度较高的数据仓库比对时就不适用。HASHBYTES可以选择不同算法,MD2、MD4、MD5、SHA、SHA1 或 SHA2 哈希值。虽然MD5已经不推荐,但他的容量有128位(2的128次方),碰撞可能性满足数据校验应该是足够了。

  • 数据对比、完整性校验只是哈希值使用的其中的一个场景。还可以为长的可变内容的值生成哈希索引,提高检索效率。

最近发表
标签列表