数据仓库与ETL:数据分层设计、ETL流程设计、数据一致性保障
数据仓库和ETL,说白了就是策略落地的「后勤保障」。你策略再牛,分析再准,数据源头是脏的、乱的、算不对的,那一切都是白搭。我见过太多团队在策略复盘时吵得面红耳赤,最后发现是数据口径对不上——这种坑,踩一次就够了。
这一章,我们就来聊聊怎么把数据仓库搭结实,把ETL流程理顺畅,让数据一致性不再是玄学。
数据分层设计:为什么不能一把梭?
很多刚入行的同学喜欢「一把梭」——从业务库直接拉数据,算完指标就出报表。短期看确实快,但三个月后你就会发现:
- 业务字段改了,报表全崩
- 指标口径变了,历史数据对不上
- 新需求来了,得从头跑一遍全量数据
我个人习惯的分层方式是四层结构:ODS、DWD、DWS、ADS。每一层解决一个核心问题。
| 分层 | 全称 | 核心职责 | 数据粒度 |
|---|---|---|---|
| ODS | 操作数据存储层 | 原样接入业务数据,不做任何清洗 | 与业务库一致 |
| DWD | 明细数据层 | 清洗、去重、标准化,保留最细粒度 | 单笔事务/事件 |
| DWS | 汇总数据层 | 按主题做轻度聚合,如日/周/月汇总 | 维度+时间粒度 |
| ADS | 应用数据层 | 面向具体业务场景,直接供报表/策略使用 | 按需求定制 |
我的经验:ODS层一定要保留原始数据的「快照」。我曾经遇到过一次业务库误删数据,幸好ODS层保留了7天前的全量快照,才把损失降到最低。别省那点存储,关键时刻能救命。
ETL流程设计:别让数据「卡」在半路
ETL(Extract-Transform-Load)是数据仓库的「血管」。设计得好,数据流顺畅;设计得烂,每天凌晨都在报警。
我一般把ETL流程拆成三个阶段来设计:
1. 抽取(Extract)
抽取阶段最容易出问题的是「增量 vs 全量」的选择。我的建议是:
- 全量抽取:数据量小(百万级以下)或业务表没有时间戳的场景
- 增量抽取:数据量大且有明确的时间戳或自增ID
- CDC(变更数据捕获):对实时性要求高,或者不想给业务库太大压力
避坑指南:我曾经遇到过增量抽取时,业务库的更新时间戳被运维改了格式,导致连续3天数据漏抽。从那以后,我强制要求所有增量抽取任务必须加「数据量波动监控」——如果今天抽取的行数比昨天少了50%以上,自动告警并暂停任务。
2. 转换(Transform)
转换是ETL的核心,也是最容易出「暗坑」的地方。我总结了三个必须注意的点:
- 空值处理:不要默认空值就是0。有些场景空值代表「未知」,有些代表「无意义」,处理方式完全不同
- 数据标准化:比如日期格式、货币单位、编码规则,必须在DWD层统一
- 业务逻辑校验:比如订单金额不能为负、用户年龄不能超过150岁——这些规则要写在转换逻辑里,而不是靠下游去发现
3. 加载(Load)
加载阶段的核心是「幂等性」。说白了,就是同一个任务跑两次,结果必须一样。我常用的策略是:
- 全量覆盖:先清空目标分区,再写入新数据
- 增量合并:使用MERGE或UPSERT语法,避免重复数据
- 分区交换:先写入临时表,校验通过后再交换分区
-- 分区交换示例(Hive SQL)
-- 1. 先写入临时分区
INSERT OVERWRITE TABLE dwd_orders PARTITION (dt = '2024-01-15_tmp')
SELECT * FROM ods_orders WHERE dt = '2024-01-15';
-- 2. 校验数据量
-- 如果校验通过,执行分区交换
ALTER TABLE dwd_orders EXCHANGE PARTITION (dt = '2024-01-15_tmp')
WITH TABLE dwd_orders PARTITION (dt = '2024-01-15');
-- 3. 删除临时分区
ALTER TABLE dwd_orders DROP PARTITION (dt = '2024-01-15_tmp');
核心原则:ETL流程必须支持「重跑」。不要因为一次失败就导致数据永久性损坏。分区交换、临时表、事务机制,都是你的护身符。
数据一致性保障:从「差不多」到「精确」
数据一致性是数据仓库的「底线」。你想想看,如果策略团队基于不一致的数据做决策,那跟闭着眼睛开车有什么区别?
我常用的保障手段有三层:
第一层:源头校验
在ETL入口处做「数据质量门禁」。比如:
- 记录数波动检测(与历史均值对比)
- 关键字段空值率检测
- 主键唯一性检测
第二层:过程对账
每一层ETL跑完后,自动执行对账脚本。比如:
- ODS到DWD:行数是否一致?关键指标(如总金额)是否匹配?
- DWD到DWS:聚合后的汇总值,与明细层手动聚合是否一致?
第三层:端到端校验
这是最后一道防线。我会在ADS层保留一些「基准查询」,每天自动跑一遍,与预期结果对比。比如:
- 「昨日全平台GMV」与财务系统对账
- 「本月新增用户数」与用户中心对账
我的习惯:每个ETL任务结束后,都会写一条「数据质量报告」到监控表。报告内容包括:源表行数、目标表行数、空值率、异常值数量、处理耗时。这样出了问题,一眼就能看出是哪个环节挂了。
一张图看懂数据仓库分层与ETL流程
下面这张图,是我自己项目里常用的数据架构。你可以把它当成一个「模板」,根据自己业务调整。
数据一致性保障的「三板斧」
最后,我把自己常用的三个保障手段整理成了一张表,方便你对照检查:
| 保障手段 | 触发时机 | 检查内容 | 失败处理 |
|---|---|---|---|
| 数据量波动检测 | ETL任务启动前 | 源表行数与历史均值对比 | 波动超过阈值则暂停任务 |
| 分层对账 | 每层ETL完成后 | 行数、关键指标、主键唯一性 | 不一致则回滚并告警 |
| 端到端基准校验 | 每日ADS层生成后 | 核心指标与财务/业务系统对账 | 不一致则标记数据不可用 |
最后提醒一句:数据一致性不是「一次性」的事,而是「每天」的事。别等到策略复盘时才发现数据对不上——那时候,锅已经甩不出去了。