新表上线发现数据错了——你怎么一步步查出来的?
本文目录
先说结论
数据问题排查的黄金流程:先定位范围(是全表错还是局部错)→ 再定位环节(ODS / DWD / DWS / ADS 哪一层错)→ 最后定位原因(代码 / 口径 / 上游)。倒着查、一层一层剥。
80% 的数据错是三类原因:上游字段含义变了(业务方改了没通知你)、JOIN 漏了维度(没按日期关联)、去重没做对(主键理解错了)。
排查时先不要改代码。先看数据、看日志、看上下游,确认根因之前不要动 SQL。很多人一上来就改代码,越改越乱。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
面试进行到 35 分钟左右,话题会拐到『生产问题处置』。面试官最爱问的第一道题:『新表上线之后发现数据不对,你怎么查?』这题不是考知识,是考流程感——一个老手的排查流程和一个新手的乱翻 SQL,面试官一眼就能分出来。能讲出『一个系统化的排查路径』就能拿到 8 分以上。
业务场景:某元宇宙社交应用的『虚拟礼物总额暴涨 300%』事件
我在某元宇宙社交应用上线过一张礼物打赏的 DWS 表,上线第二天早上业务方炸了——当日礼物总额从平时的 200 万美元暴涨到 800 万美元。产品经理以为我们在庆祝活动数据,一看没活动,反过来质疑数据错了。我花了 40 分钟从头查到尾,定位到问题。
-- Step 1: 确认问题范围(全表 vs 局部)
SELECT dt, SUM(amount_usd)
FROM dws_gift_daily
WHERE dt >= '2024-03-10'
GROUP BY dt ORDER BY dt;
-- 结果:只有 03-15 当天暴涨,历史正常
-- 推断:不是口径错,是当天数据异常
-- Step 2: 按维度拆解(国家/礼物/用户)
SELECT country, SUM(amount_usd)
FROM dws_gift_daily WHERE dt = '2024-03-15'
GROUP BY country ORDER BY 2 DESC;
-- 结果:印尼暴涨 600 万(平时 10 万)
-- 推断:印尼有问题
-- Step 3: 追到上游明细
SELECT uid, SUM(amount_usd)
FROM dwd_gift_detail
WHERE dt = '2024-03-15' AND country = 'ID'
GROUP BY uid ORDER BY 2 DESC LIMIT 10;
-- 结果:某一个用户打赏了 500 万美元
-- 明显不正常,查 ODS 原始数据
-- Step 4: ODS 原始数据比对
SELECT uid, raw_amount, currency, amount_usd
FROM ods_gift_raw
WHERE dt = '2024-03-15' AND uid = 'XXX';
-- 发现:ODS 里是 5 亿印尼盾(约 3.2 万美元)
-- 问题:货币转换的汇率表用错了
最终根因:DWD 层的货币换算用了固定汇率表 dim_fx_rate,上游财务同学当天修改了印尼盾汇率(小数点错位),没通知我们下游。我们的 ETL 照旧跑,把 1 印尼盾按 100 美元算,结果一个用户的打赏被放大了 150 倍。
段落一:步骤一——先定位范围
拿到『数据不对』的报错第一件事是搞清楚『哪里不对』。用三个维度拆:时间维度、业务维度、指标维度。
Plain
时间维度:是今天错还是历史都错?
→ 今天错:可能是今天的 ETL 或上游有问题
→ 历史都错:可能是逻辑 bug 或口径理解错了
业务维度:是全部维度错还是某一个维度错?
→ 全部错:计算逻辑 / JOIN 维度 / 引擎问题
→ 某一个错:上游数据 / 该维度的特殊处理
指标维度:是一个指标错还是多个指标错?
→ 一个错:那个指标的计算逻辑有问题
→ 多个错:底层 DWD 或 ODS 有问题
经验:很多人遇到问题直接看 SQL,应该先看数据。SQL 写得对但数据错是最常见的情况——数据质量问题不是代码问题,是上下游协作问题。
段落二:步骤二——顺着数据链路一层层比对
数据链路通常是 ODS → DWD → DWS → ADS。哪一层开始错的,就是根因所在层。比对方式是 COUNT 和 SUM。
-- 四层数据一致性检查模板
SELECT 'ODS' AS layer, COUNT(*) cnt, SUM(amount) amt
FROM ods_gift_raw WHERE dt = '${bizdate}'
UNION ALL
SELECT 'DWD', COUNT(*), SUM(amount_usd)
FROM dwd_gift_detail WHERE dt = '${bizdate}'
UNION ALL
SELECT 'DWS', NULL, SUM(amount_usd)
FROM dws_gift_daily WHERE dt = '${bizdate}'
UNION ALL
SELECT 'ADS', NULL, SUM(amount_usd)
FROM ads_gift_dashboard WHERE dt = '${bizdate}';
-- 正常的输出应该是:
-- ODS cnt = DWD cnt(没丢数据)
-- DWD SUM = DWS SUM = ADS SUM(口径一致)
-- 哪一层和上一层数据不一致,根因就在那一层
段落三:步骤三——定位到具体根因
链路定位到哪一层错之后,看那一层的 SQL 逻辑,重点看四个点:
| 检查点 | 具体内容 | 典型问题 |
|---|---|---|
| 去重 | 是否做了去重,主键是不是真的唯一 | 把非唯一键当主键做去重 |
| JOIN 条件 | JOIN 的键、类型(LEFT/INNER)、是否按日期关联 | 漏写 AND a.dt = b.dt,LEFT 变 INNER |
| 过滤条件 | WHERE 的时间 / 业务过滤条件 | 漏了 WHERE dt,全表扫 |
| 字段来源 | 字段是从哪个上游来的、有没有经过转换 | 汇率 / 币种 / 时区转换出错 |
段落四:步骤四——根因确认后的处置
根因找到不是结束,还要做四件事:止血、修数、补丁、复盘。
Plain
数据事故处置 SOP(我总结的流程):
1. 止血(10 分钟内):
- 暂停错误数据对外输出(下掉看板、停订阅)
- 通知业务方『数据异常,正在排查』
2. 修数据(1-4 小时):
- 根据根因决定回刷范围(一天?一周?)
- 准备修复 SQL,和另一个人 review 再跑
- 跑的过程中监控输出
3. 补丁(1 天内):
- 修复根因(代码 bug 或协作流程)
- 加 DQC 校验,防止同类事故
4. 复盘(3 天内):
- 写事故报告(时间线 / 根因 / 影响 / 改进)
- 改进项 owner 和 deadline 明确到人
面试高频追问
追问一:你怎么判断是你的代码错还是上游数据错?
两个方法:(1)数据回溯——如果前几天的数据用同一套代码是对的,那就大概率是上游今天的数据变了;(2)最小重现——用一个简单的 SQL 直接从 ODS 原始数据算一遍对比。如果 SQL 重算对、你的 DWD 错,那是代码问题;如果 SQL 重算也错,那是上游数据问题。这招能 90% 定位边界。
追问二:业务方一直在催,你怎么平衡『快速给答案』和『查准根因』?
我的节奏是 10 分钟内给一个『初步结论』(比如『发现印尼数据异常,疑似汇率问题,正在进一步核实』),然后 1 小时内给准确根因。业务方要的是『有人在管』的确定感,不是秒级答案。但永远不要在根因不明时猜——猜错了你后面的声誉都会扣分。
追问三:你们公司有没有数据质量监控系统?
我现在这边有 DQC 系统(DataWorks 自带 + 一些自研规则),校验分三类:(1)完整性——行数波动、非空;(2)唯一性——主键唯一;(3)业务一致性——核心指标环比阈值。DQC 挂了和任务挂了是同级告警。但 DQC 只能防已知的错误模式,那次汇率事件 DQC 没抓到——因为金额总值在阈值内(只是单个用户异常),这也是我加了一条『单用户 TOP 异常检测』规则的原因。
实战踩坑:一个配置文件引发的事故
我还踩过一次类似的坑,在某短剧出海公司:上游广告回传数据的字段含义改了——原来 `revenue` 是美元,新版本变成了当地币种 + `currency` 字段标识。上游同事以为加了 `currency` 字段就是往前兼容,没通知我们。我们的 DWD 照旧把 `revenue` 当美元算,导致海外广告 ROI 看板当天虚高 3 倍。
教训:上下游 schema 变更必须有强制通知机制。这个故事在第 13 篇 Schema 变更防御会讲防御方案。
总结
新表数据错排查题的高分答案有三个要点:(1)结构化的四步流程(范围 → 环节 → 根因 → 处置);(2)SQL 比对一致性的具体手法;(3)一个真实事故的完整故事。最忌讳『我一般 print 一下看看』这种无章法的回答——面试官看的是你有没有系统化的排障能力。
下一篇:『T+1 任务突然跑到了 T+2——你怎么排查?』——生产问题第二道,考察对调度延迟和数据到达时效性的理解。
你遇到过最离谱的『数据错了』是什么场景?是代码错、上游错、还是口径分歧?
关注「Wood聊大数据」| 9年大数据老兵,聊技术、聊职场、聊成长