返回知识库
数据质量测试实战:从数据流转到数据质量保障
从源系统一路追到报表、BI与AI应用,证明每一次抽取、转换、加载和汇总都没有让业务事实走样。
12 个章节SQL + 数据仓库金融 / BI / AI 数据链路
🧭
为什么需要 ETL 测试
页面正确,不代表数据可信用户看到一行数据,背后可能经过五层加工
业务数据通常要经过源数据库、抽取任务、清洗转换、数据仓库、接口与缓存,最后才出现在页面、报表或AI应用中。任何一层出错,都可能让最后的数字看起来合理、实际上却是错的。
业务系统→
ODS 原始数据层→
DWD 明细数据层→
DWS 汇总数据层→
ADS 应用数据层→
报表 / BI / AI应用
各层职责与测试重点
| 层级 | 主要职责 | 测试关注 |
|---|---|---|
| 业务系统 | 订单、客户、贷款、合同等原始业务数据 | 源数据是否完整、时间和状态是否可信 |
| ODS 原始层 | 按源结构落地,尽量保留原貌 | 抽取数量、批次、重复、缺失、原始快照 |
| DWD 明细层 | 清洗、标准化、补充业务维度 | 字段映射、类型转换、空值和异常处理 |
| DWS 汇总层 | 按主题聚合形成可复用指标 | 口径、时间窗口、去重、关联和聚合结果 |
| ADS 应用层 | 为报表、BI、风控或AI提供数据 | 最终指标与业务规则、页面、接口是否一致 |
ETL 测试的目标
- 数据没有无故丢失、重复或被错误过滤。
- 字段、类型、金额精度和业务状态转换正确。
- 明细、汇总、接口与页面使用同一指标口径。
- 跑批失败、重复执行和迟到数据都能被安全处理。
- 异常可追溯到具体批次、规则、业务键和数据层。
🔄
ETL 三个阶段
Extract / Transform / Load每个阶段分别测什么
| 阶段 | 作用 | 测试重点 |
|---|---|---|
| Extract 抽取 | 从数据库、文件、接口或消息获取数据 | 是否漏抽、重抽、错批次;时间范围和水位线是否正确 |
| Transform 转换 | 清洗、计算、关联、去重、标准化 | 业务规则、边界、空值、异常值和精度是否正确 |
| Load 加载 | 把结果写入目标表或数据集市 | 数量、字段、主键、分区、重复加载和失败恢复 |
抽取
验证“该来的都来了,而且只来一次”。重点关注时间窗口、水位线、连接失败和断点恢复。
转换
验证“业务规则没有把数据加工错”。重点关注边界、空值、精度、关联和异常分流。
加载
验证“正确结果落到正确位置”。重点关注主键、分区、提交事务和重复跑批。
🗺️
先建立字段 Mapping
没有映射表,就没有可执行测试字段映射表示例
| 源字段 | 转换规则 | 目标字段 | 质量规则 |
|---|---|---|---|
| loan_order.customer_id | 原值传递 | dwd_loan.cust_id | 非空;必须存在于客户维表 |
| loan_order.loan_amount | 分转元,保留2位小数 | dwd_loan.asset_amount | DECIMAL;金额不可为负 |
| loan_order.overdue_days | > 90 标记为不良 | dwd_loan.asset_status | 边界90与91分别验证 |
| loan_order.created_at | 转换为业务时区日期 | dwd_loan.biz_date | 跨日、夏令时和空值规则明确 |
Mapping 表至少包含
- 源系统、源表、源字段与数据类型。
- 过滤条件、转换公式、字典映射和默认值。
- 目标表、目标字段、主键、分区和精度。
- 空值、异常值、重复值与无关联数据的处理方式。
- 规则负责人、需求版本和生效日期。
🔍
ETL 六类核心校验
数量只是第一步核心验证矩阵
| 检查项 | 验证目标 | 常用方法 |
|---|---|---|
| 数量一致性 | 源数据经过合法过滤后与目标数量相符 | count(*)、按批次/分区分组对账 |
| 字段映射 | 源字段正确写入目标字段 | 逐字段抽样、全量差异查询 |
| 转换逻辑 | 业务计算和分类正确 | 等价类、边界值、异常值 |
| 唯一性 | 主键或业务键没有重复 | count(*) 与 count(distinct key) |
| 完整性 | 必填字段和关联数据齐全 | NULL率、孤儿记录、缺失维度 |
| 聚合准确性 | 总额、数量、比率与明细一致 | sum、count、group by、反向下钻 |
SQL / 对账基础
-- 按业务日期核对源数据量
select count(*)
from loan_info
where created_at >= '2026-08-09 00:00:00'
and created_at < '2026-08-10 00:00:00';
-- 核对目标批次数量、唯一键和金额控制总额
select
count(*) as row_count,
count(distinct loan_id) as unique_count,
sum(asset_amount) as control_amount
from dwd_loan
where biz_date = '2026-08-09';数量不一致时不要直接判Bug
源表100000条、目标表99998条,只能证明存在2条差异。还要结合合法过滤、去重、异常分流和软删除规则,定位是抽取失败、转换过滤还是加载失败。
🧪
数据转换逻辑测试
ETL 测试的核心转换规则用例设计
| 类型 | 测试数据 | 预期 |
|---|---|---|
| 正常值 | 贷款金额 500000,逾期 30 天 | 金额正确,资产状态为正常 |
| 边界值 | 逾期 90 天、91 天 | 90 天不误判;91 天按规则进入不良 |
| 空值 | 逾期天数为 NULL | 按约定置默认值、进入异常表或拒绝处理 |
| 非法值 | 金额为负数、日期格式错误 | 不能静默写入正常目标表 |
| 精度 | 金额换算、利率和比例计算 | 小数位、舍入方式与财务口径一致 |
| 编码 | 中英文、特殊字符、身份证号前导零 | 不乱码、不截断、不丢前导零 |
不良资产规则示例
规则:逾期天数大于90天时,资产状态标记为 BAD。
SQL / 差异检查
select loan_id, overdue_days, asset_status
from dwd_loan
where (overdue_days > 90 and asset_status <> 'BAD')
or (overdue_days <= 90 and asset_status = 'BAD');测试原则
- 从业务规则反推输入,不只抽查生产数据。
- 每个比较符号都测试边界两侧和边界本身。
- 金额、利率和比例明确精度与舍入方式。
- 异常数据必须有去向:拒绝、默认、隔离或告警,不能静默消失。
♻️
增量同步、幂等与重跑
生产事故高发区增量任务必须覆盖的场景
| 场景 | 执行方式 | 核心断言 |
|---|---|---|
| 首次全量 | 目标为空,执行完整批次 | 所有合法历史数据只加载一次 |
| 正常增量 | 新增、更新、删除各准备一条 | 只处理水位线后的变化 |
| 重复跑批 | 同一批次再次执行 | 结果不重复,控制总额不变化 |
| 中途失败重跑 | 加载50%后模拟失败 | 从断点恢复或安全重跑,不漏不重 |
| 迟到数据 | 昨天业务日期的数据今天才到 | 按规则回补正确分区并更新汇总 |
| 乱序更新 | 旧版本晚于新版本到达 | 不会用旧状态覆盖新状态 |
水位线测试
- 起始时间是否包含边界,结束时间是否排除下一批次。
- 时间字段使用创建时间、更新时间还是业务日期。
- 时区转换、跨日、月末和节假日跑批是否正确。
- 水位线推进必须与任务提交成功保持一致。
幂等的判断标准
同一批次执行一次和执行多次,最终业务结果必须相同。不能只看任务返回成功,还要核对行数、唯一键、金额总额、版本号和下游汇总是否保持不变。
🧩
关联、聚合与指标口径
数字对上,还要口径对上关联测试
- inner join 是否错误丢弃无匹配数据。
- left join 是否因一对多关系放大数据量。
- 维表缺失时使用默认值、异常表还是拒绝加载。
- 历史维度是否按业务时间匹配正确版本。
聚合测试
- sum、count、distinct、平均值的分母和去重口径。
- 自然日、账务日、滚动窗口和累计值的时间范围。
- 明细向上汇总与指标向下钻取结果一致。
- 空集合、负数冲正和撤销记录处理正确。
SQL / 孤儿记录与关联放大
-- 目标事实表中找不到客户维度的记录
select f.loan_id, f.cust_id
from dwd_loan f
left join dim_customer d on f.cust_id = d.cust_id
where d.cust_id is null;
-- 检查关联后业务键是否被意外放大
select loan_id, count(*) as joined_rows
from dws_customer_loan
group by loan_id
having count(*) > 1;📊
把ETL校验升级为数据质量体系
从一次测试变成持续监控六个数据质量维度
| 维度 | 含义 | 参考指标 |
|---|---|---|
| 完整性 | 必填字段不缺失、数据批次齐全 | NULL率、应到/实到批次数 |
| 唯一性 | 业务主键不重复 | 重复键数量 |
| 准确性 | 值符合真实业务事实 | 金标样本正确率、对账差异 |
| 一致性 | 不同层、不同系统表达同一事实 | 跨表、跨系统差异率 |
| 及时性 | 数据在SLA内可用 | 延迟、跑批完成时间 |
| 有效性 | 格式、范围、枚举符合规则 | 非法值率、异常表数量 |
质量阈值要分层
- P0:资金、余额、贷款本金等控制总额必须零差异。
- P1:关键字段完整率、唯一率必须达到明确阈值。
- P2:非关键描述字段允许少量异常,但要进入趋势监控。
- 任何阈值都要有业务负责人和处置动作,不能只展示红绿灯。
数据血缘
当ADS报表数字错误时,必须能反查到DWS聚合、DWD明细、ODS原始记录和源系统。测试报告应记录表级、字段级血缘以及对应规则版本,避免只知道“数字错了”,不知道从哪一层开始查。
🛠️
ETL 测试流程
先理解链路,再写SQL1. 梳理链路
- 确认数据源、加工层、目标表和最终消费方。
- 画出数据流转图,标注任务依赖与事实来源。
- 明确全量、增量、实时或批处理方式。
2. 分析规则
- 建立字段Mapping与指标口径表。
- 确认过滤、去重、关联、聚合和异常处理。
- 标记资金、权限、合规等高风险字段。
3. 设计数据
- 正常、边界、异常、重复、迟到和乱序数据。
- 为每条数据分配可追踪业务键与批次号。
- 记录期望落层和最终指标。
4. 执行与复测
- 任务前记录源数据快照和控制总额。
- 任务后逐层核对数量、字段、规则和汇总。
- 修复后使用同一批数据重跑并验证幂等。
🏦
金融AI交付案例:不良资产数据链
OCR + ETL + 业务规则银行贷款数据→
合同 / OCR识别→
结构化字段→
资产明细表→
风险聚合→
清收策略 / AI分析页面
贯穿验证
- OCR准确性:合同金额、客户、日期和编号与原件一致。
- 结构化入库:类型、精度、必填字段和重复合同处理正确。
- 风险规则:逾期天数、贷款余额和担保信息计算正确。
- 控制总额:源贷款余额、DWD资产余额、报表总额零差异。
- 页面与AI:展示指标来自正确版本的数据,AI引用的资产事实可追溯。
高风险场景
- OCR把500000识别为50000,格式合法但金额错误。
- 同一合同重复上传,导致资产金额重复累计。
- 迟到的还款数据没有回补,风险等级长期偏高。
- 旧维度数据覆盖新客户状态,导致清收策略错误。
- AI分析使用过期ADS快照,却没有展示数据时间。
这类测试本质上是 AI数据质量测试 + ETL测试 + 业务规则测试。模型输出是否可信,首先取决于进入模型的数据是否可信。
🤖
ETL 测试自动化
规则配置化,差异可追踪建议目录结构
etl-tests/
mappings/ # 字段映射与规则配置
queries/ # 源、目标、差异SQL
fixtures/ # 正常、边界、异常测试数据
checks/ # 数量、唯一性、完整性、控制总额
runners/ # 批次执行与任务状态轮询
reports/ # 差异明细和质量报告适合自动化的检查
- 按批次核对源、过滤、目标数量。
- 唯一键、必填字段、枚举和数值范围。
- 金额、数量和余额控制总额。
- Mapping规则和差异SQL回归。
- 重复跑批、断点重跑和迟到数据回补。
- 质量阈值越界时阻断或告警。
自动化边界
脚本擅长发现差异,不擅长决定差异是否符合业务。指标口径变化、监管规则和异常数据处置仍需要产品、数据开发与测试共同确认。
✅
报告模板与检查清单
让每次跑批都有证据ETL 测试报告
| 项目 | 记录内容 |
|---|---|
| 批次信息 | 任务名、批次号、业务日期、代码与规则版本 |
| 对账结果 | 源数量、过滤数量、目标数量、差异数量与控制总额 |
| 质量结果 | 完整性、唯一性、准确性、一致性、及时性指标 |
| 异常明细 | 业务键、源值、目标值、规则、错误类型与关联日志 |
| 测试结论 | 通过、不通过、有条件通过及风险说明 |
| 可追溯证据 | SQL、数据快照、任务日志、血缘、截图和复测结果 |
测试前
- 数据链路与事实来源明确
- Mapping和口径已评审
- 批次、水位线与SLA明确
- 测试数据可追踪
测试中
- 逐层记录数量和控制总额
- 转换边界与异常分流已验证
- 增量、重跑、迟到数据已覆盖
- 差异保留业务键和日志
测试后
- 目标与消费端结果一致
- 质量阈值全部达标
- 失败数据可重放和复测
- 高风险规则进入持续监控