维度建模
问题
什么是维度建模?星型模型和雪花模型有什么区别?
答案
什么是维度建模
维度建模(Dimensional Modeling)是 Ralph Kimball 提出的数仓建模方法,核心思想是把数据分为两类:
| 类型 | 定义 | 示例 |
|---|---|---|
| 事实表(Fact Table) | 记录业务事件,包含度量值 | 订单事实表(金额、数量) |
| 维度表(Dimension Table) | 描述事件的上下文 | 时间维、商品维、用户维 |
星型模型
事实表居中,维度表直接连接,形状像星星:
雪花模型
维度表进一步规范化(拆分),形状像雪花:
星型 vs 雪花对比
| 对比 | 星型模型 | 雪花模型 |
|---|---|---|
| 维度表 | 扁平化、宽表 | 规范化、拆分 |
| 查询性能 | ✅ 更快(JOIN 少) | ⚠️ JOIN 多 |
| 存储空间 | 稍多(冗余) | 稍少 |
| 维护成本 | 低 | 高 |
| 推荐 | 大多数场景首选 | 维度需要单独维护时 |
实际工作中
- 绝大多数数仓用星型模型,因为性能好、易理解
- 雪花模型在需要严格维护维度层级时使用(如商品品类多级分类)
事实表类型
| 类型 | 特点 | 示例 |
|---|---|---|
| 事务事实表 | 每行一个事件 | 订单表、点击表 |
| 周期快照事实表 | 按固定周期汇总 | 每日库存、月活统计 |
| 累积快照事实表 | 跟踪业务流程里程碑 | 订单流程(下单→支付→发货→签收) |
维度表设计
商品维度表示例
CREATE TABLE dim_product (
product_sk BIGINT PRIMARY KEY, -- 代理键
product_id VARCHAR(32), -- 业务键
product_name VARCHAR(200),
category_l1 VARCHAR(50), -- 一级品类
category_l2 VARCHAR(50), -- 二级品类
brand VARCHAR(100),
price DECIMAL(10,2),
effective_date DATE, -- SCD 生效日期
expire_date DATE, -- SCD 失效日期
is_current TINYINT DEFAULT 1 -- 是否当前有效
);
代理键 vs 业务键
- 业务键(Natural Key):业务系统的 ID,如
product_id = 'SKU001' - 代理键(Surrogate Key):数仓自动生成的自增 ID,用于处理 SCD
- 事实表外键指向代理键,维度表主键用代理键
常见面试问题
Q1: 你们的事实表设计了哪些度量?粒度是什么?
答案(以电商订单事实表为例):
- 粒度:一行 = 一个订单 + 一个商品(订单明细粒度)
- 度量:
order_amount(订单金额)、qty(数量)、discount_amount(优惠金额) - 外键:
date_key、product_key、user_key、channel_key - 粒度决定了事实表能回答的最细问题
Q2: 宽表和维度建模有什么关系?
答案:
- 维度建模产出的是星型/雪花模型(事实表 + 维度表,需要 JOIN)
- 宽表是把事实表和维度表 JOIN 好的"结果表",一张表包含所有字段
- 宽表适合 BI 直接查询(无 JOIN,快),但灵活性差
- 实际工作中常在 DWS/ADS 层做宽表
Q3: 事实表和维度表的粒度不一致怎么办?
答案:
- 事实表粒度必须一致(同一张表所有行粒度相同)
- 如果需要不同粒度,建不同的事实表(如"订单级"和"日汇总级")
- 维度表的粒度通常比事实表粗,通过外键关联