精选·数仓与建模

维度表设计与缓慢变化维:拉链表到底是怎么实现的

91学AI·2026/7/13·8 阅读

考察点

维度表看似简单,真正拉开差距的是缓慢变化维(SCD)的处理。面试官通常会先问 SCD 几种类型,然后深挖拉链表:表结构怎么设计、每天怎么跑、下游怎么查。能讲清拉链表每日 merge 的完整流程,基本就过了这关。

参考答案

维度表的基础设计

维表一行代表一个维度成员(一个用户、一个商品),字段分两类:主键描述属性。主键推荐用代理键(自增或 hash 生成的无意义整数)而不是业务键,原因是业务键会复用、会变,代理键配合 SCD2 能让同一业务实体的不同历史版本各占一行。属性就是分析时用作过滤和分组的字段:用户的年龄段、商品的类目层级、地区的省市。高频属性可以做规范化整理,比如把「注册渠道」从几十个杂乱取值收敛成标准枚举。另外维度属性里常做维度退化的反向判断:基数极高、几乎不用于分组的属性(如订单号)不要塞进维表,直接留在事实表里。

缓慢变化维:维度属性变了怎么办

用户改了城市、商品换了类目,历史数据按旧口径算还是新口径算?这就是 SCD 问题,经典处理有四类:

  • SCD0:属性从不变化(出生日期),或变化了也不理,最简单;
  • SCD1:直接覆盖旧值。历史全按新口径看,实现最简单(update 或每天全量重刷),适合「改错」类场景——比如用户性别之前录错了,历史就应该按修正后的算。Hive 里就是每天全量拉业务库当前状态,insert overwrite;
  • SCD2:加一行保存历史版本。旧行封链(记录失效时间),新行生效,历史查询能精确还原「当时」的维度值。这是保留历史的标准做法,拉链表就是它在 Hive 系的实现;
  • SCD3:加「上一值」列,只保留前一次历史,实际用得少,了解即可。

选型的判断依据是业务语义:这个属性变化后,历史报表应不应该变?该变用 SCD1,不该变用 SCD2。

拉链表的结构与每日构建

拉链表用两个字段标记每行生效区间:

user_id  city     start_date   end_date
1001     北京     2023-01-01   2023-06-14
1001     上海     2023-06-15   9999-12-31

end_date = 9999-12-31 表示当前生效。查询「6 月 10 日那天的用户城市」就是 where user_id = 1001 and start_date <= '2023-06-10' and end_date >= '2023-06-10'

每天 T+1 的构建流程是拉链表的核心,分三步:

  1. 取当日变化:从 ODS 拿到当日新增和变更的用户记录(业务库的 binlog 增量或 updated_at 落在昨天的记录);
  2. 封旧链:对发生变化的旧生效记录,把 end_date 更新为昨天;
  3. 开新链:变化记录以今天为 start_date9999-12-31end_date 插入;两部分 union 后写回新分区。

Hive 上的经典写法是 insert overwrite 拉链全表:「旧生效记录 left join 当日变化」改 end_date,再 union 当日变化记录。数据量大时全表重刷成本高,可以只对变化用户重算、其余用户直接透传,或者迁到 Hudi 用 upsert 天然支持。

拉链表的空间账和简化变体

拉链表的优势是相对每日全量快照省存储——一亿用户如果每天只有 1% 变化,拉链表一年增长约 3.65 亿行,而每日快照是一年 365 亿行。代价是查询逻辑复杂,下游写错 between 条件是常见事故。所以有个常用的简化变体:每日分区快照 + 生命周期裁剪,即每天保留全量维度快照(用当天的维度状态),历史只保留近期 30-90 天分区和每月月末分区。查询简单(where dt = 某天),存储可控,多数团队实际选这个。拉链表留给「精确回溯历史任意一天」是硬需求的场景,比如财务结算、风控取证。

可能的追问

  • 拉链表 end_date 用 9999-12-31 还是 NULL? 工程上推荐固定大日期而不是 NULL,因为 NULL 参与 between 比较结果是 NULL,下游查询必须额外 or end_date is null,漏写就是数据丢失。
  • 维度高频变化(比如用户积分)也进拉链吗? 不进。变化频率太高的属性进拉链会让链碎片化、表膨胀失控,这类属性要么放快照事实表(积分本质是度量不是维度),要么只保留当前值(SCD1)。
  • 拉链断链了怎么发现和修复? 常规 DQC:每天校验每个业务键有且仅有一条 end_date 为最大值的记录、各链段区间不重叠不空缺。修复通常是从 ODS 按业务库变更日志重放,重建该实体的整条链。

评论 (0)

暂无评论,快来抢沙发吧!

91学AI

© 2026 91学AI · 按岗位学 AI 与大数据. All rights reserved.