主键重复怎么查
主键重复说明表的声明粒度被破坏:一行本应代表一个业务事件,却出现了多行。定位分三步——先用 GROUP BY 加 HAVING COUNT(1) > 1 找出重复键;再把重复组展开成明细行;最后对比差异字段(加载时间、来源系统、批次号)判断成因。只统计重复数量而不展开明细,只能知道有问题,判断不出是重跑叠加、双写还是关联放大,也就选不出正确的修复方式。
基本信息
| 适用 | Hive、Spark SQL、MySQL 8、Doris 等支持窗口函数与 CTE 的引擎 |
|---|---|
| 定位步骤 | 找重复键 → 展开明细 → 对比差异字段 |
| 关键线索 | 加载时间、来源系统、批次号、是否有重复分区 |
| 常见原因 | 重跑未覆盖、双写、关联放大、去重键缺失 |
| 修复方向 | 按分区覆盖重写并补自动化校验 |
典型使用场景
- 每日稽核发现订单表行数上涨,需要确认是主键重复还是业务正常增长
- 上游重跑后下游指标偏大,定位是否产生了重复明细
- 多源合并接入后出现同号多行,排查是双写还是分区未覆盖
- 关联维度表时误用了一对多关系,导致事实行被放大
- 迁移或数据回刷后核对粒度声明是否仍成立
重复键展开明细
重复键展开明细
-- 第一步:找重复键(建议用业务键组合,而非单列)
WITH dup AS (
SELECT order_id, item_no
FROM dwd_trade_order_detail_di
WHERE dt = '2026-10-11'
GROUP BY order_id, item_no
HAVING COUNT(1) > 1
)
-- 第二步:展开明细并对比差异字段
SELECT d.order_id, d.item_no, d.pay_amount, d.load_time, d.src_sys
FROM dwd_trade_order_detail_di d
JOIN dup ON d.order_id = dup.order_id AND d.item_no = dup.item_no
WHERE d.dt = '2026-10-11'
ORDER BY d.order_id, d.load_time;
-- 第三步:判断是否关联放大(同一批次的重复条数一致多为关联导致)
SELECT load_time, COUNT(1) AS cnt FROM dwd_trade_order_detail_di
WHERE dt = '2026-10-11' GROUP BY load_time ORDER BY cnt DESC LIMIT 10;重复成因对照
| 现象 | 常见成因 | 定位线索 | 处理方式 |
|---|---|---|---|
| 整批行数翻倍 | 重跑未覆盖分区 | load_time 有两个不同批次 | 按分区覆盖重写 |
| 零星同号多行 | 上游双写或补发 | src_sys 或渠道字段不同 | 与源端约定去重键 |
| 按维度汇总后偏大 | 关联一对多放大 | 明细行数正常、汇总偏大 | 改用维表去重或先聚合 |
| 特定分区重复 | 任务重试未清理临时区 | 重复仅出现在某天分区 | 先删分区再写入 |
同时检查多条业务键组合(订单号加明细号)比只查单列更接近真实粒度:很多表的唯一性来自组合键,单列本来就会重复。
把批量重跑造成的重复当偶发问题处理,而不补自动化校验,同一故障会在下次重跑时原样复现,且往往在指标已经对外发布之后才被发现。
修复优先级是先核对粒度声明,再改写数据:如果实际的唯一键是组合键而非单列,正确做法是更新表声明与校验规则,而不是硬把数据压成单列唯一。