第一次搭数据仓库的人常在建模这步犯晕:业务库几十张表,怎么归拢成报表友好的结构?答案绕不开两个概念,事实表和维度表。

维度表管「描述」

维度表回答的是谁、什么、在哪、什么时候这类描述性问题。用户维度存编号、性别、城市、会员等级;商品维度存商品名、类目、品牌;日期维度存年、月、星期几、是否节假日。特征是行数相对少、列多、内容以文字属性为主,更新不频繁。

事实表管「发生了什么」

事实表记录业务事件,每一行对应一次订单、一次点击或一笔支付。它存两类东西:指向各维度的外键,以及金额、数量、时长这类度量值。度量值用来求和、求平均,维度用来切分筛选,分工很清楚。订单事实表的一行可能是用户 1001 在 2026 年 10 月 31 日买了 2 件商品 2003,实付 99 元,用户和商品的详细信息都不在这张表里,只留编号。

查询时把两表 join 起来:按城市、按会员等级统计销售额,就是订单明细关联用户维度再分组汇总。一张事实表居中、周围一圈描述表的形状,就是常说的星型模型。维度表的价值这时候就显出来了:分析口径要加要改,动描述表就行,事实表本身保持稳定。

实际建模要注意的点

描述属性会变。用户搬家换了城市,直接覆盖旧值,历史报表的口径就乱了;需要保留历史的用二类慢变化维度处理,加生效时间和失效时间字段,旧记录归档、新记录另起一行。会员等级升级、组织架构调整,同理。要不要保留历史,就看老板会不会问「去年这时候这个人在哪个组」。

还有一点容易忽视:维度的主键必须唯一,事实表里关联不上的记录,一般设计一条「未知」默认记录兜底,避免统计时悄悄丢数。

实际判断:分析口径经常变、报表维度多的场景,老老实实拆出维度表建星型模型;只是临时取数,直接在业务库写 join 也行,别为了建模而建模。