考察点
这是数仓面试的开场题,几乎所有大数据岗位的初面都会问。面试官不只想听你背出四层名字,更想看你能不能讲清「不分层会出什么问题」以及「每层之间数据怎么流动」。追问通常往两个方向走:你们公司的实际分层是怎样的、某张具体表应该放在哪一层。
参考答案
不分层会怎样
先想反面。如果直接从业务库抽数给报表用,每个需求都是一套独立的抽数、清洗、计算链路,这就是典型的烟囱式开发。三个报表算同一个 GMV,口径可能对不齐;业务库表结构一改,下游几十个任务同时挂掉;出了问题想排查,连数据从哪来的都说不清。分层的本质就是用架构手段解决三件事:解耦(源系统变化不直接冲击应用)、复用(清洗和公共计算只做一次)、可追溯(问题能沿着层间血缘定位)。
ODS:操作数据层,贴源留现场
ODS 的原则是基本不动数据,把业务库、日志的数据原样接进来。业务库一般走 DataX、Sqoop 或 CDC(Flink CDC、Canal)同步,日志走 Flume、Kafka。工程上有两个细节:一是 ODS 也要解决增量问题,全量表直接按天快照,增量表常见的做法是「每日增量 + 昨日全量 merge 成新全量」,或者维护拉链;二是保留源系统的原貌意味着命名、字段类型尽量贴源,这一层是给排查问题用的「现场」,出问题随时能回这里对数。ODS 通常只做最轻的处理,比如补 dt 分区字段、过滤测试数据。
DWD:明细数据层,数仓的地基
DWD 以业务过程为单位建模,一张表对应一个业务过程(下单、支付、退款、曝光),用维度建模组织事实表和维度表。这一层干的核心活:
- 清洗:去重(订单重复推送)、空值处理、异常值剔除(金额为负、时间穿越);
- 规范化:编码统一(性别有的系统存 0/1 有的存 M/F)、单位统一(金额统一成分或元,全公司只能选一个)、字典翻译;
- 维度退化与关联:把常用维度属性退化进事实表,比如把用户表里的地区、年龄带进来,减少下游 join。
DWD 的粒度必须到最明细级别——能到订单行就不停在订单级,因为粒度一旦汇总就不可逆,下游想要更细的口径就没办法了。
DWS:汇总层,沉淀公共计算逻辑
DWS 按主题和维度做轻度汇总,比如「用户-天-品类」粒度的交易汇总宽表,一行包含下单金额、支付金额、下单件数等十几个度量。它存在的意义是复用:如果没有这一层,每个 ADS 需求都要从 DWD 明细重新算一遍,同样的 join 和聚合逻辑在几十个任务里重复,口径漂移、资源浪费。宽表设计是这一层的常见手法,把高频使用的维度和度量预 join、预聚合好。注意是轻度汇总,一般保持天级粒度,不做需求级的定制。
ADS:应用层,面向消费场景
ADS 直接对接报表、BI、接口、推荐特征,按需求定制,什么粒度、什么口径都可以。这一层的表生命周期往往最短,需求没了表就可以下线。成熟团队会给 ADS 立规矩:ADS 不许直接读 ODS,指标必须来自 DWS 或 DWD,防止绕过中间层又长出烟囱。
一个补充
分层是逻辑约定不是物理隔离,实际落地都是 Hive/Spark 里的库和表命名规范(ods_、dwd_、dws_、ads_ 前缀),靠平台权限和 code review 守住边界。层数也不是教条,中小公司三层甚至两层也能跑,关键是每层职责清晰、跨层引用受控。
可能的追问
- 你们实时数仓怎么分层? 思路一样但层级会压缩:ODS 是 Kafka 原始 topic,DWD 是 Flink 清洗后的明细 topic,DWS 用 Flink 窗口或 StarRocks/Doris 物化视图做实时汇总,通常 3 层为主,ADS 和 DWS 经常合并。
- DWD 和 DWS 的边界怎么把握? 看是否发生聚合:保持业务过程原始粒度的是 DWD,跨粒度或跨业务过程汇总的是 DWS。拿不准时宁放 DWD,粒度损失不可逆。
- 层间数据回溯怎么处理? 出错时用 ODS 重跑是最稳的,所以 ODS 的生命周期(比如保留 90 天)决定了回溯能力上限,这是存储成本和可恢复性的权衡。