AI摘要

本文详细介绍了数据仓库的分层架构,包括ODS(贴源层)、DWD(明细层)、DWS(汇总层)和ADS(应用层),并解释了各层的职责、命名规范和数据流转的全链路示例。分层架构有助于提高数据的可追溯性、可复用性、解耦合性和易维护性。

为什么你的报表总是对不上?从数据分层说起

什么是数据仓库分层

数据仓库(Data Warehouse)不是把数据堆在一起,而是按层次组织,让每一层只干一件事。

这样做的好处很实际:数据出问题时,能快速定位是哪一层的锅;中间层算好的结果可以被多个下游复用;源系统改了字段,只需要改最底层,上层不用动;每层职责清晰,改动的影响范围可控。

标准分层架构

主流的数据仓库分层方案如下:

业务系统 (OLTP)
    ↓
ODS(贴源层)
    ↓
DWD(明细层)
    ↓
DWS(汇总层)
    ↓
ADS(应用层)
    ↓
报表 / BI / 接口

ODS:贴源层(Operational Data Store)

ODS 是数据进入仓库的第一站。从业务系统(MySQL、PostgreSQL、日志等)同步过来,原样保存,不加任何业务逻辑。按天分区,保留历史快照,顺带做数据质量检查(空值、格式异常这类)。

命名通常以 ods_ 开头,带上源系统名和表名:

ods_mysql_user_info_di       # di = daily increment,日增量
ods_mysql_order_di
ods_log_app_click_di

有几点容易踩坑:ODS 这层只管存,别在这里做业务逻辑;源系统如果有物理删除,ODS 要用软删除记下来;字段名保持原样,改名的事留到 DWD 做。


DWD:明细层(Data Warehouse Detail)

DWD 是数据清洗和整合的核心。ODS 的原始数据经过清洗、标准化、关联维度表之后,在这里变成干净的、面向业务过程的明细数据。具体做的事包括:去脏数据、空值处理、类型转换、统一时区编码和状态含义、把 ID 关联成有意义的字段(比如 user_id 关联出 city_name),以及按业务过程拆分或合并表。

命名以 dwd_ 开头,描述业务过程:

dwd_order_detail_di          # 订单明细
dwd_user_behavior_click_di   # 用户点击行为明细
dwd_pay_success_di           # 支付成功明细

示例

ODS 原始订单数据:

-- ods_mysql_order_di
order_id | user_id | status | create_time         | amount
1001     | 888     | 2      | 2026-02-27 10:00:00 | 99.00

DWD 清洗后:

-- dwd_order_detail_di
order_id | user_id | status_name | create_date | amount | city_name
1001     | 888     | 已付款       | 2026-02-27  | 99.00  | 上海

关键点:

  • status=2 转成了可读的 已付款
  • create_time 拆出了 create_date 用于分区
  • 通过 user_id 关联用户维度表,补充了 city_name

维度表 vs 事实表

DWD 里有两类表:

类型说明示例
事实表(Fact)记录业务过程,有度量值订单、支付、点击
维度表(Dimension)描述业务实体,相对稳定用户、商品、地区

维度表通常以 dim_ 命名:

dim_user_info_full           # full = 全量快照
dim_product_info_full
dim_region_full

DWS:汇总层(Data Warehouse Summary)

DWS 在 DWD 明细基础上做聚合汇总,按主题域和时间粒度生成宽表。这层是报表计算的主要数据来源。按天/周/月聚合统计指标,按业务主题构建宽表(用户域、商品域、地区域),提高下游查询效率,避免重复计算。

命名以 dws_ 开头,体现主题域 + 时间粒度:

dws_user_order_1d            # 用户粒度,订单,最近1天
dws_product_sale_1d          # 商品粒度,销售,最近1天
dws_region_gmv_1d            # 地区粒度,GMV,最近1天

举个例子,用户日汇总宽表长这样:

-- dws_user_order_1d
user_id | dt         | order_count | pay_amount | avg_amount | city_name
888     | 2026-02-27 | 3           | 299.00     | 99.67      | 上海

ADS:应用层(Application Data Store)

ADS 是最终结果表,直接给报表、BI 工具、接口查询用。按具体业务场景定制,结构贴近前端使用,通常是聚合度最高的一层。

命名以 ads_ 开头,体现具体业务报表:

ads_daily_gmv_report         # 日GMV报表
ads_user_retention_report    # 用户留存报表
ads_new_user_funnel          # 新用户转化漏斗

比如日 GMV 报表:

-- ads_daily_gmv_report
dt         | gmv      | order_count | pay_user_count | avg_order_amount
2026-02-27 | 10000.00 | 320         | 280            | 31.25

数据流转全链路示例

以"统计昨日各城市 GMV"为例,完整链路如下:

1. ODS 入仓

-- 从 MySQL 同步原始订单
INSERT INTO ods_mysql_order_di
SELECT * FROM mysql_source.t_order WHERE date(create_time) = '2026-02-27';

2. DWD 清洗

-- 清洗、标准化、关联维度
INSERT INTO dwd_order_detail_di
SELECT
    o.order_id,
    o.user_id,
    CASE o.status WHEN 2 THEN '已付款' WHEN 3 THEN '已退款' END AS status_name,
    o.amount,
    u.city_name,
    DATE(o.create_time) AS dt
FROM ods_mysql_order_di o
LEFT JOIN dim_user_info_full u ON o.user_id = u.user_id
WHERE o.dt = '2026-02-27' AND o.status = 2;

3. DWS 汇总

-- 按城市聚合
INSERT INTO dws_region_gmv_1d
SELECT
    city_name,
    dt,
    SUM(amount) AS gmv,
    COUNT(1) AS order_count
FROM dwd_order_detail_di
WHERE dt = '2026-02-27'
GROUP BY city_name, dt;

4. ADS 输出

-- 生成报表数据
INSERT INTO ads_city_gmv_report
SELECT city_name, dt, gmv, order_count
FROM dws_region_gmv_1d
WHERE dt = '2026-02-27'
ORDER BY gmv DESC;

常见问题

分层一定要这么多吗?

小团队数据量不大时,可以简化为三层:ODS → DWD → ADS,跳过 DWS。但随着业务复杂度增加,DWS 能显著减少重复计算。

DWD 和 DWS 的边界在哪?

DWD 有明细行,一行代表一个业务事件(一笔订单、一次点击);DWS 已经聚合过了,一行代表一个统计周期的汇总结果。

维度表放哪层?

维度表通常单独放在 DIM 层或归入 DWD 层管理,不参与 ODS→DWS 的加工链路,供各层 JOIN 使用。

数据怎么跑?

分层数据通常用调度工具按依赖顺序跑任务,常见工具:

工具特点
Apache DolphinScheduler开源,国内用得多
Apache Airflow功能全,社区大
DataWorks阿里云托管,配合 MaxCompute
xxl-job轻量,Java 技术栈常用

总结

层次英文名核心职责数据粒度
ODSOperational Data Store原样同步源数据原始行
DIMDimension维度数据管理实体快照
DWDData Warehouse Detail清洗标准化业务事件行
DWSData Warehouse Summary主题聚合宽表统计周期行
ADSApplication Data Store业务报表输出指标结果行

搭数据仓库不难,难的是把每层的职责想清楚。先定好分层,再落技术选型,比一上来就堆 SQL 要稳得多。

标签: none

添加新评论