目标
脏重复数据住在“完全相同”与“完全不同”之间的地带。三 元组相似度能覆盖这片地带,但没打标签就定的阈值等于拿数据掷硬币。一百对手工标注的已知重复与已知不同对,能把阈值从玄学变成一张可读的取舍表:错过多少重复对、误杀多少真实行,一目了然,由承担错误成本的人来选行。
步骤要点
- 先做归一化:小写、去标点、剥 Inc/LLC/Ltd 等法律后缀,让完全等价的写法先免费合并。
- 用 pg_trgm 的 similarity 生成 a.id < b.id 的候选对,按分数降序查看,观察真实重复与相似不同交织的分数带。
- 手工标注一百对样本建标签表,对若干候选阈值做扫描统计,输出每个阈值的捕获率与误合并数,选定位点。
- 在单事务里合并:先写合并日志(幸存者、被并者、分数),再把子表外键重指到幸存者,最后停用而非删除被并行。
- 审计结果:统计合并数与最大幸存组,给评审者一份最高风险合并的抽查队列,确认无误后宣布完成。
排错提示
相似度对词序敏感漏掉“Smith John”与“John Smith”,加一列词拆排序再拼接的变体,取两种分数的最大值;同名不同公司是字符串度量的盲区,把地区或电话并入配对键,让标签集教阈值哪些字段必须一致;下周发现合并错了也不慌,合并日志加停用策略让回退机械化:子行重指回、账号重新激活,全部发生在新的有日志事务里。
适用边界
模糊阈值承载业务判断,不同的错误成本配不同的切点,标签集让这件事显式;相似度只到字符串层,跨系统身份还是要靠实体键或已有 id。
代码示例
-- Threshold sweep on 100 labeled pairs
-- cutoff caught_dups false_merges
-- 0.45 97% 11 <-- too aggressive
-- 0.55 92% 2 <-- chosen
-- 0.70 61% 0 <-- too timid
-- Merge with an audit trail, deactivate instead of delete
INSERT INTO dedupe_merge_log (survivor_id, absorbed_id, score)
SELECT a.id, b.id, similarity(a.norm, b.norm)
FROM accounts a JOIN accounts b ON a.id < b.id
WHERE similarity(a.norm, b.norm) >= 0.55;