前事不忘,后事之师,不忘国耻!

 用户注册  找回密码
 用户注册
搜索
查看: 17|回复: 0

数据仓库建模:星型与雪花模型

[复制链接]

数据仓库建模:星型与雪花模型

[复制链接]
dbaai

主题

0

回帖

151

积分

DBAAI

积分
151
10 小时前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?用户注册

×
数据仓库建模:星型与雪花模型


一、具体的问题

很多业务系统跑了一两年,老板突然要"看板""日报""同比环比",开发第一时间想到的是在几张业务表上直接写 JOIN 出报表。结果报表一复杂,SQL 就几百行,查询动辄十几秒,改一个维度字段就要动整段 SQL。真正的根因不是 SQL 写得差,而是底层没有按"分析"的视角建模——你用的是面向交易(OLTP)的第三范式表,却想干面向分析(OLAP)的活。数据仓库建模要解决的,就是把"业务数据"整理成"好算、好扩、好理解"的分析结构,而星型模型(Star Schema)和雪花模型(Snowflake Schema)就是这套方法里最基础、也最该先搞懂的两种布局。

二、核心原理

1. 维度建模的基本构件

维度建模只分两类表:


  • 事实表(Fact):存"发生了什么"——可度量的事件,如一笔订单的金额、数量、下单时间。特征是行数巨大、列少而稳定,包含两类列:度量(金额、数量,可加减)和外键(指向各维度)。
  • 维度表(Dimension):存"从什么角度看"——时间、门店、商品、客户等描述性属性。特征是行数相对小、列多、变化慢。


2. 星型模型:扁平的辐射结构

星型模型里,事实表居中,周围直接连着非规范化的维度表——每个维度是一张宽表,所有属性都摊平在同一张表里。比如"商品维度"把类目、品牌、供应商、规格全放一张表,不再拆子表。整个结构像一颗星星:事实在中心,维度在四周,查询时事实表 JOIN 各维度表即可,JOIN 层数通常为 1。

优点很直接:查询简单、JOIN 少、性能高、BI 工具(如 Tableau、FineBI、Power BI)开箱即认。绝大多数数据仓库、数据集市默认都用星型。

3. 雪花模型:把维度再拆规范化的分支

雪花模型是星型的"规范化"版本:维度表里的冗余属性被进一步拆成子维度。还是"商品维度"的例子——类目单独成表、品牌单独成表、供应商单独成表,商品维度表只留外键指向它们。结构从星星变成了雪花(多层分支)。

它省了存储空间、消除了维度内的数据冗余(类目名只存一处),但代价是查询要多层 JOIN(商品→类目→品牌),SQL 更复杂、性能略低、对业务人员不友好。只有在维度极宽、且同一维度被多张事实表高度复用时,才值得上雪花。

4. 一个常被踩的坑:把维度表当业务表用

新手常犯两类错:一是把事实表也做成了"宽表"——把维度属性直接冗余进事实表,导致一旦维度更新,要改海量事实行;二是维度表过度拆到雪花,结果一个简单的"按品牌汇总销售额"要 JOIN 四张表。经验法则:事实表瘦、维度表胖但扁平,星型优先,雪花只在"维度被多个事实复用且更新频繁"时局部采用。

三、实例参考(动手步骤)

下面用一个"门店销售"场景,给出星型模型的建表与查询 SQL,并对比雪花模型差异。假设我们要分析:各门店、各商品类目、按天的销售额。

1) 星型模型建表(PostgreSQL 语法,其它库相似):
  1. -- 维度:时间(扁平,所有属性摊在一张表)
  2. CREATE TABLE dim_date (
  3.   date_key   INT PRIMARY KEY,
  4.   full_date  DATE,
  5.   year       INT,
  6.   quarter    INT,
  7.   month      INT,
  8.   weekday    INT
  9. );
  10. -- 维度:门店(扁平)
  11. CREATE TABLE dim_store (
  12.   store_key  INT PRIMARY KEY,
  13.   store_name VARCHAR(50),
  14.   city       VARCHAR(30),
  15.   region     VARCHAR(20)
  16. );
  17. -- 维度:商品(星型:类目/品牌直接冗余在商品表里,不拆分)
  18. CREATE TABLE dim_product (
  19.   product_key INT PRIMARY KEY,
  20.   product_name VARCHAR(80),
  21.   category    VARCHAR(30),
  22.   brand       VARCHAR(30),
  23.   supplier    VARCHAR(40)
  24. );
  25. -- 事实:销售(只存度量与外键)
  26. CREATE TABLE fact_sales (
  27.   sales_key   BIGINT PRIMARY KEY,
  28.   date_key    INT REFERENCES dim_date(date_key),
  29.   store_key   INT REFERENCES dim_store(store_key),
  30.   product_key INT REFERENCES dim_product(product_key),
  31.   quantity    INT,
  32.   amount      NUMERIC(12,2)
  33. );
复制代码

2) 星型查询:按"城市 + 类目"汇总 2026 年销售额——只需事实表 JOIN 三个维度,全部 1 层 JOIN:
  1. SELECT  s.city,
  2.         p.category,
  3.         SUM(f.amount) AS total_amount,
  4.         SUM(f.quantity) AS total_qty
  5. FROM    fact_sales f
  6. JOIN    dim_date    d ON f.date_key    = d.date_key
  7. JOIN    dim_store   s ON f.store_key   = s.store_key
  8. JOIN    dim_product p ON f.product_key = p.product_key
  9. WHERE   d.year = 2026
  10. GROUP BY s.city, p.category
  11. ORDER BY total_amount DESC;
复制代码

3) 雪花对比:若把 dim_product 拆成 dim_product(category_key, brand_key, ...) + dim_category + dim_brand,上面那条查询就要再多 JOIN 两张表,SQL 变长、执行计划多两层,BI 自助分析时业务人员也更难理解。存储上雪花省了类目/品牌的重复字符串,但现代列存 + 压缩下这点收益通常抵不过查询复杂度。

4) 前后对比结论:星型在"查询性能 + 可理解性"上全面占优;雪花仅在"维度被多事实表复用(如销售事实和库存事实都引用同一商品类目)且类目结构经常整体调整"时,靠规范化减少同步成本。落地建议:先用星型把集市搭起来跑通,遇到具体复用痛点再局部雪花化,不要一上来就拆。

四、实操检查清单


  • 事实表是否只含"度量列 + 各维度外键",没有任何描述性冗余属性?
  • 维度表是否尽量扁平(星型优先),而非一上来就拆成多层雪花?
  • 是否每个维度都有稳定的代理键(surrogate key,如 date_key/store_key),与业务自然键解耦?
  • 粒度(grain)是否已明确定义——一行事实代表"一次销售明细"还是"一天一店汇总"?粒度乱了报表必错。
  • 是否区分了"可加度量"(金额,可跨任意维度加)与"半加/不可加度量"(比率、余额,仅部分维度可加)?
  • 是否给常用查询路径建了合适的索引/列存投影,并验证过查询耗时在可接受范围?
  • 维度属性变更(如商品换类目)是否定义了 SCD 策略(覆盖/历史快照),避免历史报表失真?
  • 雪花化之前,是否确认该维度确实被多张事实表复用、且更新频繁到值得付出查询复杂度代价?
免责申明1、欢迎访问本站,本文内容及相关资源来源于网络,版权归版权方所有!本站原创内容版权归本站所有,请勿转载!
2、本文内容仅代表作者观点,不代表本站立场,作者自负,本站资源仅供学习研究,请勿非法使用,否则后果自负!请下载后24小时内删除!
3、本文内容,包括但不限于源码、文字、图片等,仅供参考。本站不对其安全性,正确性等作出保证。但本站会尽量审核会员发表的内容。
4、如本帖侵犯到任何版权问题,请立即告知本站 ,本站将及时删除并致以最深的歉意!客服邮箱:admin@dbabbs.com
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

QQ|Archiver|小黑屋|DBA论坛中国 ( 鲁ICP备20017503号-2 )

GMT+8, 2026-9-10 18:17 , Processed in 0.016502 second(s), 9 queries , MemCached On.

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表