维度建模四步法:选业务过程、声明粒度、确认维度、确认事实

做数据仓库建模,我见过太多人一上来就画 ER 图,结果画到一半发现根本对不齐业务。其实有个更靠谱的套路——Kimball 老爷子总结的维度建模四步法。这四步我用了十几年,每次都能把混乱的需求理清楚。

说白了,就是四个问题:做什么?多细?从哪看?看什么?咱们一个一个拆。

核心口诀:先定过程,再定粒度,维度围绕业务转,事实跟着粒度走。

维度建模四步法核心流程 ① 选业务过程 做什么? ② 声明粒度 多细? ③ 确认维度 从哪看? ④ 确认事实 看什么? 关键原则: • 业务过程是核心,选错了后面全白搭 • 粒度决定数据行含义,必须精确到原子级别 • 维度提供「谁、什么、何时、何地」的上下文 • 事实是度量值,必须与粒度严格对齐

第一步:选业务过程

业务过程,就是业务里发生的一件事。比如电商的「下单」「支付」「发货」,银行的「开户」「转账」「放贷」。每个业务过程对应一个事实表。

我个人的习惯是,先跟业务方聊清楚:你们最关心的核心活动是什么?别一上来就想着把所有表都建了,那又回到烟囱式开发的老路上了。

我的经验:选业务过程时,优先选那些「有明确事件发生、有可度量数值、业务方天天盯着看」的过程。比如销售订单、客服工单、物流签收——这些是数据仓库的「现金牛」。

举个例子,一个电商平台的核心业务过程可能有:

业务过程 事件描述 典型事实
下单 用户提交订单 订单金额、商品数量
支付 用户完成付款 支付金额、支付手续费
发货 仓库发出商品 发货数量、物流费用
退货 用户申请退款 退款金额、退货数量

你看,每个过程都是独立的「事件快照」。把它们分开建模,后面做分析时才能灵活组合。

第二步:声明粒度

粒度,说白了就是一行数据代表什么。这是四步法里最容易翻车的一步。

我曾经在一个项目中,业务方说「我要看每天的销售汇总」,我就直接建了日汇总表。结果两周后他们又说「我要看每个订单的明细」——完蛋,粒度太粗,回不去了。只能重做。

血的教训:粒度一定要选最细的原子粒度。比如「每笔订单的每个商品行」,而不是「每天每个商品的汇总」。原子粒度可以向上聚合,但反过来不行。你想想看,是不是这个理?

常见的粒度声明方式:

  • 事务粒度:每发生一次事件就一条记录。比如每笔支付、每次点击。
  • 周期快照粒度:每个周期(如每天)每个实体一条记录。比如每日账户余额。
  • 累积快照粒度:每个流程实例一条记录,记录其全生命周期。比如每个订单从下单到完成的全过程。

我个人建议,能用事务粒度就别用快照。事务粒度最灵活,能回答的问题最多。快照粒度虽然查询快,但一旦业务需求变了,你只能干瞪眼。

第三步:确认维度

维度就是看问题的角度。比如「哪个用户买的?」「什么时间买的?」「在哪个渠道买的?」——这些「谁、什么、何时、何地」就是维度。

确认维度时,有个简单的方法:对着粒度描述,把每个「修饰词」拎出来。比如粒度是「每笔订单的每个商品行」,那修饰词就有:订单号、商品ID、用户ID、下单时间、支付方式……这些就是维度。

维度建模的核心思想:事实表记录「发生了什么」,维度表描述「这件事的背景」。两者通过外键关联,形成星型模型。

常见的维度类型:

  • 日期维度:几乎每个事实表都有。年、季、月、周、日、节假日……
  • 产品维度:商品名称、品类、品牌、规格。
  • 客户维度:姓名、等级、地区、注册时间。
  • 门店/渠道维度:门店编号、区域、类型。

嗯,这里要注意:维度不是越多越好。我见过有人一张事实表挂了 30 多个维度,查询慢得要命,业务方还看不懂。一般 5-10 个维度就够用了,核心维度控制在 8 个以内。

第四步:确认事实

事实就是你要衡量的数值。比如金额、数量、时长、次数。事实必须跟粒度严格对齐——粒度是「每笔订单」,那事实就不能是「每天的总金额」。

事实分三种:

事实类型 说明 例子
可加事实 可以跨所有维度相加 销售金额、商品数量
半可加事实 只能跨部分维度相加 账户余额(不能跨时间相加)
不可加事实 不能相加,只能做比率 单价、折扣率、利润率

我刚开始做建模时,总想把所有字段都塞进事实表。后来发现,事实表里只放度量值,描述性的东西全扔给维度表。这样事实表才「瘦」得下来,查询才快得起来。

避坑指南:我曾经在一个项目中,把「商品名称」也放进了事实表。结果商品改名后,历史数据全乱了。后来才明白——名称是维度属性,不是事实。事实只放数字,不放文本。

四步法实战:一个完整的例子

咱们拿「电商订单」来走一遍四步法:

  1. 选业务过程:「下单」——用户提交订单这个事件。
  2. 声明粒度:「每笔订单的每个商品行」——一条记录代表一个商品在一个订单里的购买行为。
  3. 确认维度:订单维度、商品维度、用户维度、时间维度、门店维度。
  4. 确认事实:商品数量、销售单价、折扣金额、实际支付金额。

你看,四步走完,模型结构就清晰了:

-- 事实表:订单明细事实
CREATE TABLE fact_order_detail (
    order_sk      INT,      -- 订单维度外键
    product_sk    INT,      -- 商品维度外键
    customer_sk   INT,      -- 客户维度外键
    date_sk       INT,      -- 日期维度外键
    store_sk      INT,      -- 门店维度外键
    quantity      INT,      -- 商品数量(可加事实)
    unit_price    DECIMAL,  -- 单价(不可加事实)
    discount_amt  DECIMAL,  -- 折扣金额(可加事实)
    pay_amt       DECIMAL   -- 实付金额(可加事实)
);

这个模型,既能回答「昨天卖了多少钱」,也能回答「哪个商品卖得最好」,还能回答「哪个门店的折扣最大」。你想想看,如果一开始就做烟囱式的汇总表,能做到这么灵活吗?

总结一下:四步法不是理论空谈,是实打实的工程方法论。选对业务过程,定准粒度,配好维度,填对事实——数据仓库建模就成功了一大半。