跳到主要内容

08.数仓分层:ODS/DWD/DWS/ADS/DIM

数仓分层是数据仓库最基础也最容易「照猫画虎」的设计。本文讲清每一层到底干什么、为什么要这么分,以及分层后每张表该怎么设计。

很多人搭数仓,第一步就是套一个 ODS/DWD/DWS/ADS 的分层模板,但被追问「DWD 和 DWS 到底有什么区别」「ADS 能不能直接读 ODS」时,就答不上来了。

分层不是形式主义。分对了,数据可复用、口径可统一、出了问题能快速定位;分错了,就是给自己挖一堆维护的坑。


一、为什么要分层:分层的根本目的​

在讲每层之前,先搞清楚「为什么非要分层」这个根本问题。

目的说明不分层的后果
解耦上层不依赖下层的具体实现源表改个字段,所有下游全炸
复用清洗/加工逻辑沉淀在中间层同样的 JOIN 逻辑写几十遍
口径统一同一指标只在固定层算一次活跃用户 3 个版本,报表对不上
数据质量脏数据在底层拦截,不进上层脏数据直接喂给报表
可追溯出问题能逐层定位数万行 SQL 无从查起

一句话:分层是为了「让每一层只做一件事,且只做一次」。这是 数据仓库建模原则 里「公共逻辑下沉」的架构化表达。


二、经典分层架构:一张图看清​

主流数仓(阿里/美团/字节等)基本都采用「四层 + 一个维度层」的结构:

┌─────────────────────────────────────────────────────────┐
│ ADS 应用数据服务层 │
│ 「面向具体应用/产品/报表的定制结果」 │
│ 例:大盘 GMV 日报、用户留存看板、指标看板 │
├─────────────────────────────────────────────────────────┤
│ DWS 汇总数据层(主题宽表) │
│ 「按主题轻度汇总,形成宽表,服务公共指标」 │
│ 例:用户日汇总宽表、商品日汇总、订单日汇总 │
├─────────────────────────────────────────────────────────┤
│ DWD 明细数据层 │
│ 「清洗、标准化后的明细数据,贴近业务过程」 │
│ 例:订单明细、支付明细、浏览明细(含维度退化字段) │
├─────────────────────────────────────────────────────────┤
│ ODS 操作数据层(贴源层) │
│ 「与源系统几乎一致,只做最小加工」 │
│ 例:业务库订单表原样同步 │
└─────────────────────────────────────────────────────────┘
▲
DIM 维度层(横向贯穿)
用户、商品、地区、时间等维度表

数据流向:ODS → DWD → DWS → ADS,逐层加工;DIM 层是「公共维度」,横向被 DWD/DWS/ADS 引用。


三、ODS:贴源层,只做「原样落地」​

3.1 职责​

ODS(Operational Data Store)是数据进仓的第一站,目标是把源系统的数据「原样」搬进来,尽量不做加工。

3.2 设计规范​

  • 结构与源表几乎一致,只加少量管理字段(如 etl_time 入仓时间、dt 分区)
  • 只做最小清洗:去空格、补默认值,不做业务逻辑
  • 保留全量历史,通常按天分区,全量或增量同步
-- ODS 层:订单表原样同步,只加分区字段
CREATE TABLE ods_order (
order_id STRING COMMENT '订单号',
user_id STRING COMMENT '用户ID',
amount DECIMAL(18,2) COMMENT '订单金额',
status STRING COMMENT '订单状态',
etl_time STRING COMMENT '入仓时间'
) COMMENT '操作数据层-订单表'
PARTITIONED BY (dt STRING)
STORED AS PARQUET;

ODS 的核心价值是**「保留现场」**:不管后面怎么加工,原始数据都在,出问题能回溯到源。


四、DWD:明细层,做「清洗 + 标准化」​

4.1 职责​

DWD(Data Warehouse Detail)是清洗、标准化后的明细数据,贴近业务过程,是数仓真正的「事实明细」。

4.2 设计规范​

  • 按业务过程建模,一张表对应一个业务过程(下单、支付、退款分开建)
  • 做字段标准化:类型统一、枚举码表化、空值语义化
  • 退化维度下沉:订单号、发票号这类无属性维度直接放明细层
  • 遵循维度建模,保留事实表的粒度,见 事实表完全指南
-- DWD 层:下单明细,清洗 + 标准化 + 退化维度
CREATE TABLE dwd_trd_order_item (
order_item_id STRING COMMENT '订单明细ID',
order_no STRING COMMENT '订单号(退化维度)',
user_id STRING COMMENT '用户ID',
product_id STRING COMMENT '商品ID',
shop_id STRING COMMENT '店铺ID',
region_id STRING COMMENT '地区ID',
order_amount DECIMAL(18,2) COMMENT '下单金额',
item_qty INT COMMENT '购买数量'
) COMMENT '交易域-下单明细层'
PARTITIONED BY (dt STRING)
STORED AS PARQUET;

五、DWS:汇总层,做「主题宽表」​

5.1 职责​

DWS(Data Warehouse Summary)是按主题轻度汇总的宽表,把常用的维度预 JOIN 进来,服务公共指标,避免每个应用都重复算一遍。

5.2 设计规范​

  • 按主题聚合:用户、商品、订单、流量等主题各建一套汇总表
  • 形成宽表:把高频维度打进来,下游查询免 JOIN,见 宽表设计全指南
  • 保留可复用的公共指标,但不做面向具体报表的定制
-- DWS 层:用户日汇总宽表(预 JOIN 用户维度 + 预聚合行为)
CREATE TABLE dws_usr_user_1d (
user_id STRING COMMENT '用户ID',
city STRING COMMENT '所在城市(维度冗余)',
level STRING COMMENT '会员等级(维度冗余)',
order_cnt_1d BIGINT COMMENT '当日下单数',
order_amount_1d DECIMAL(18,2) COMMENT '当日下单金额',
pay_cnt_1d BIGINT COMMENT '当日支付数'
) COMMENT '用户域-用户日汇总宽表'
PARTITIONED BY (dt STRING)
STORED AS PARQUET;

六、ADS:应用层,做「定制结果」​

6.1 职责​

ADS(Application Data Service)是面向具体应用、产品、报表的定制结果,是分层的最顶层,直接给看板、接口、业务方消费。

6.2 设计规范​

  • 面向具体业务场景:大盘日报、留存看板、某个专题的指标
  • 可以直接读取 DWD/DWS,但不应穿透到 ODS
  • 口径必须可落地为「表 + 字段 + 过滤条件 + 聚合方式」
-- ADS 层:大盘 GMV 日报(面向具体报表)
CREATE TABLE ads_trd_gmv_daily (
dt STRING COMMENT '日期',
gmv DECIMAL(18,2) COMMENT '成交总额',
order_cnt BIGINT COMMENT '订单数',
pay_cnt BIGINT COMMENT '支付订单数',
pay_rate DECIMAL(9,4) COMMENT '支付转化率'
) COMMENT '应用层-大盘GMV日报';

七、DIM:维度层,做「公共一致性维度」​

7.1 职责​

DIM(Dimension)层存放跨业务共享的一致性维度:用户、商品、地区、时间等。它是「横向贯穿」的一层,被各层事实表引用。

7.2 设计规范​

-- DIM 层:用户维度(拉链表,保留历史)
CREATE TABLE dim_user_zip (
user_id STRING COMMENT '用户ID',
city STRING COMMENT '所在城市',
level STRING COMMENT '会员等级',
start_date STRING COMMENT '生效日期',
end_date STRING COMMENT '失效日期,9999-12-31 表示至今有效',
is_current INT COMMENT '是否当前有效'
) COMMENT '维度层-用户拉链表';

八、分层命名规范(一图速查)​

国内数仓普遍按「层级前缀 + 主题域 + 主体 + 粒度 + 频率」命名:

层前缀示例含义
ODSodsods_order贴源订单表
DIMdimdim_user_zip用户维度拉链表
DWDdwddwd_trd_order_item交易域下单明细
DWSdwsdws_usr_user_1d用户域日汇总
ADSadsads_trd_gmv_daily应用层大盘日报

看到表名就能判断它属于哪一层、什么主题、什么粒度——这是 数据仓库建模原则 里「命名是契约」的落地。


九、常见坑点​

  1. 分层过多——有的团队分 7、8 层,每层都有维护成本,最终谁都不清楚数据经过了什么。详见 数仓分层的常见误区
  2. 上层穿透下层——ADS 直接读 ODS,绕过清洗逻辑,源表一改就出脏数据
  3. DWS 和 ADS 职责不清——DWS 是「公共汇总」,ADS 是「定制结果」,别把报表逻辑塞进 DWS
  4. ODS 做业务加工——ODS 应该「原样」,加工放 DWD,否则「现场」被破坏
  5. 每层都全量——应该分层增量,明细层按天增量、汇总层按天重算,避免无谓的全量扫描

十、小结​

层一句话
ODS原样落地,保留现场
DWD清洗 + 标准化,贴业务过程
DWS主题汇总,形成宽表
ADS面向应用,定制结果
DIM公共一致性维度,横向贯穿

分层的本质是**「每层只做一件事,且只做一次」**。分得对不对,判断标准就一个:改一个源字段,能不能只动 ODS 和 DWD,而不波及 ADS?


📌 本文是 dwsql.com 数仓建模方法论系列「数仓分层与指标体系」第 1 篇。下一篇讲分层的常见误区,见 数仓分层的常见误区。

📱关注公众号

「数据仓库技术」文章同步更新,不错过每一篇干货

微信公众号二维码
💬加群交流

备注「数据仓库技术」加入社群,每日一道大厂SQL真题

交流微信二维码

你可能还想看