数仓分层是什么
数仓分层指把数据加工过程按「离源远近」切成若干层,每层只做固定类型的事:ODS 贴源保留原始数据,DWD 做清洗与标准化,DWS 按主题做轻度汇总,ADS 面向报表输出结果。分层的价值不在层数本身,而在于把「变更」和「复用」隔离开:上游源表字段改动只需动 ODS 与 DWD,下游复用同一份汇总,不必各自重算。落地方式通常是库/目录隔离,或统一用表名前缀区分(ods_ / dwd_ / dws_ / ads_)。
分层解决什么问题
分层针对三个具体问题:一是复用,多张报表都要的同一份汇总只算一次;二是隔离,源系统改字段时只影响最靠近源的那一层;三是回溯,指标异常时能逐层比对中间结果,定位到是哪一步出错。层与层之间靠调度串行起来,ODS 完成后才跑 DWD,同层内的多个任务可以并行,这也是分层能压缩整体调度窗口的原因。
基本信息
| 典型分层 | ODS / DWD / DWS / ADS,可加 DIM、DWT |
|---|---|
| 落地形式 | 独立库、目录,或表名前缀 |
| 调度依赖 | 层间串行,同层内并行 |
| 适用规模 | 中大型离线数仓;小团队可合并为三层 |
分层职责对照
| 层 | 粒度 | 典型表 | 主要动作 |
|---|---|---|---|
| ODS | 与源表一致 | ods_order | 只落地与去重,不改语义 |
| DWD | 一行一事 | dwd_trade_order_di | 清洗、标准化、关联维度代理键 |
| DWS | 主题+维度组合 | dws_trade_store_day | 轻度聚合,按主题日/月汇总 |
| ADS | 指标结果 | ads_sale_board_day | 面向报表与接口,可直接查询 |
典型使用场景
- 新建数仓时先定分层与命名:层和前缀定下来再建库建表,避免后期大规模改名
- 排障时定位问题在哪一层:贴源表有值而 DWD 无值,说明清洗条件或过滤写错
- 评估变更影响面:只改 ODS 解析逻辑时,从分层依赖图直接圈出受影响的下游链路
- 拆分重复计算:多张报表都要的同一份汇总下沉到 DWS,供多方引用
- 控制存储成本:明细留在 DWD/DWS 按生命周期归档,ADS 只保留结果表
常见误用与后果
| 现象 | 后果 |
|---|---|
| DWD 里做聚合、ADS 里关联明细 | 复用度归零,指标口径散落在各张报表里 |
| ADS 表被其他 ADS 引用做二次加工 | 口径层层传递,改一张报表牵动另一张 |
| ODS 里做清洗或改字段语义 | 失去与源系统对账能力,数据问题无法回溯 |
| 层数堆到六层以上 | 链路变长、调度串行时间拉长,收益低于维护成本 |
目录与命名示例
目录与命名示例
# 目录式:每层一个库或目录
ods/trade_order/ 保留源表字段,不做业务过滤
dwd/trade_order_di/ 一行一单,清洗与标准化
# 前缀式:同库内用表名前缀区分
ods_order / dwd_trade_order_di / dws_trade_store_day / ads_sale_board_day层数按团队与工具取舍:小团队用 ODS + DWD + ADS 三层也能跑通;引入 DIM 层放公共维度、DWT 层放主题宽表都是常见扩展。判断某层该不该存在的标准是——它是否有人直接依赖,且依赖者确实不需要更细的粒度;答不上来就是多余的层。
分层与调度的关系
分层要靠调度落地:ODS 任务完成后才触发 DWD,DWD 完成后再触发 DWS,同层内的任务彼此没有依赖,可以并行铺开。检验分层是否真生效,看一眼依赖图就够——如果存在反向引用(DWD 依赖 ADS 的产物),说明加工位置并没有被约束住,分层只是命名好看。
分层流于形式比不分层更糟:表面有分层命名,实际 DWD 做聚合、ADS 关联明细,复用度归零,还白多了一次落表和一轮调度耗时。