3、粒度与维度关系:粒度决定维度、维度描述粒度、粒度与维度的映射
好,咱们接着聊。前面两章我们把粒度的概念和选择原则讲清楚了。这一章,我想重点聊聊粒度跟维度的关系。
说实话,我见过不少刚入行的数据工程师,把这两个概念搞混。他们觉得“维度就是描述事实的嘛,跟粒度有什么关系?”
关系大了去了。我甚至可以说,不理解粒度与维度的关系,你建出来的星型模型就是个空壳子。
3.1 粒度决定维度:先定“看多细”,再定“看哪些角度”
这句话怎么理解?
我举个例子。假设你在做电商订单分析。
- 如果粒度是“每个订单行”——那你的维度自然就是:商品、客户、日期、店铺。因为每个订单行只关联一个商品、一个客户、一个下单日期。
- 如果粒度是“每个包裹”——那维度就变了:物流商、发货仓、配送区域。商品维度反而可能退化成包裹内的商品列表,不再是直接关联。
你看,粒度先定下来,维度才能跟着确定。反过来,如果你先拍脑袋定了10个维度,再去看粒度,大概率会发现有些维度跟事实表对不上——要么多对多,要么一对多,要么根本没关系。
核心原则:粒度是维度的“锚点”。锚点没定,维度就是漂的。
我在项目中遇到过一件事。有个团队做销售分析,上来就建了一张“销售事实表”,维度表挂了产品、客户、门店、促销活动、销售人员……一共8个维度。结果一查数据,发现“销售人员”这个维度跟事实表是多对多——一个订单可能由多个销售员共同完成。但他们的粒度是“订单头”,根本承载不了这种关系。最后只能拆事实表,重做ETL,折腾了两周。
为什么会这样?
就是因为他们没先定粒度。如果一开始就明确“我的粒度是每个订单头”,那销售人员这个维度就应该用桥接表,而不是直接挂。
3.2 维度描述粒度:维度是粒度的“说明书”
好,粒度定了,维度也选好了。那维度到底在干什么?
说白了,维度就是在给粒度“贴标签”。
你想想看,事实表里存的都是数字:销售额、数量、成本……这些数字本身没有意义。是维度告诉了你:
“这个销售额是哪个商品的?”
“是哪个客户买的?”
“是在哪个门店发生的?”
“是什么时候发生的?”
所以我说,维度就是粒度的“说明书”。没有维度,粒度只是一个空洞的“行定义”;有了维度,粒度才变成有业务含义的数据单元。
| 粒度(事实表行含义) | 维度(描述角度) | 说明 |
|---|---|---|
| 每个订单行 | 商品、客户、日期、店铺 | 维度直接描述“谁买了什么、在哪买、何时买” |
| 每次网站点击 | 访客、页面、来源渠道、时间 | 维度描述“谁在哪个页面、从哪来、何时点” |
| 每笔银行交易 | 账户、交易类型、渠道、柜员 | 维度描述“哪个账户、做什么操作、通过什么方式” |
嗯,这里要注意:维度描述的是“这个粒度对应的业务上下文”,而不是“这个事实表里所有可能的分析角度”。有些分析角度可能来自多个维度的组合,但每个维度单独看,都必须能直接关联到一行事实数据。
3.3 粒度与维度的映射:一对一、一对多、多对多
这是最实操的部分。我直接说结论:
粒度与维度之间的映射关系,决定了你的模型是简单还是复杂。
常见的映射有三种:
- 一对一映射:一行事实数据,对应一个维度成员。比如“每个订单行”对应“一个商品”。这是最理想的情况,直接挂维度表就行。
- 一对多映射:一行事实数据,对应多个维度成员。比如“每个订单头”对应“多个商品”。这种情况,商品维度就不能直接挂,得用事实表里的商品列表字段,或者拆成更细粒度的事实表。
- 多对多映射:多行事实数据,对应多个维度成员。比如“每个销售员”对应“多个订单”,同时“每个订单”也对应“多个销售员”。这种情况,必须用桥接表或退化维度来处理。
避坑指南:我曾经接手过一个项目,事实表粒度是“每日门店汇总”,但维度表里挂了“单品”维度。结果每个门店每天卖几百个单品,事实表一行数据对应几百个商品——这就是典型的一对多映射没处理好。最后只能把事实表拆成“每日门店单品汇总”,粒度细化,才解决问题。
所以,我个人的习惯是:
在确定粒度之后,先画一张映射矩阵,把每个候选维度跟事实表粒度的映射关系标出来。一对一打勾,一对多打三角,多对多打叉。打叉的维度,要么换粒度,要么用桥接表,要么干脆不要。
下面这张图,就是我常用的映射关系判断流程:
我的小技巧:在建模初期,我会用Excel拉一张表,左边列候选维度,右边列粒度定义,然后逐行判断映射关系。这个过程虽然有点笨,但能避免后期80%的返工。
3.4 总结一下这三句话
- 粒度决定维度——先定“看多细”,再定“看哪些角度”。粒度是维度的锚点。
- 维度描述粒度——维度是粒度的“说明书”,给事实数据贴上业务标签。
- 粒度与维度的映射——一对一直接挂,一对多拆粒度,多对多用桥接表。
这三句话,我建议你记下来。每次建事实表之前,拿出来对照一遍。能帮你省下不少改模型的时间。