一、数仓建模的意义
数据模型就是数据组织和存储的方法,它强调从业务、数据存取和使用角度合理存储数据。
二、数据仓库建模的作用
- 高性能:良好的数据模型能够帮助我们快速查询所需要的数据。
- 低成本:良好的数据模型能减少重复计算,实现计算结果的复用,降低计算成本。
- 高效率:良好的数据模型能极大的改善用户使用数据的体验,提高使用数据的效率。
- 高质量:良好的数据模型能改善数据统计口径的混乱,减少计算错误的可能性。
三、数据仓库建模方法论
3.1 Inmon 范式建模
- 核心思想:自上而下。首先从企业全局视角设计一个高度集成、稳定、符合数据库范式的企业级数据模型(3NF),即企业数据仓库。然后再从其中派生出各种面向主题的数据集市。
- 特点:强调整体性、一致性和可扩展性,但设计周期长、成本高。
3.2 Kimball 维度建模
- 核心思想:自上而下。从最重要的、最具体的业务过程(如销售、下单、支付等)开始,构建一个个独立的、面向主题的数据集市。所有数据集市组合起来,构成企业数据仓库。
- 特点:快速交付、以用户需求为导向、强调易用性和查询性能。
3.2.1 维度建模核心步骤
- 选择业务过程:确定要分析的具体业务活动,例如(销售、下单、用户注册、支付、物流更新、客服工单等)。
- 声明粒度:精确定义事实表中每一行数据代表什么。粒度决定了模型的清晰度和可扩展性。应该选择最原子级的粒度。
- 确定维度:围绕业务过程,确定分析的视角。例如(时间维度、商品维度、门店维度、用户维度)。
- 确定事实:确定业务过程的度量值。事实通常时可累加、可计算的数值,例如(销售数量、销售金额等)。
四、维度建模理论之事实表
事实表是数据仓库维度建模的核心,紧紧围绕着业务过程来设计。
4.1 事实表的特点
事实表通常比较"细长",既列较少,但行较多,且行的增速快。
4.2 事实表的分类
4.2.1 事务型事实表
事务事实表用来记录各业务过程,它保存的是个业务过程的原子操作事件,及最细粒度操作事件。事务事实表可用于分析与各业务过程相关的各项统计指标。
4.2.2 周期型快照事实表
周期型快照事实表以具有规律性的、可预见的时间间隔来记录事实,主要用于分析一些存量型(例如商品库存,账户余额)或者状态型(空气温度,行驶速度)指标。
4.2.3 累积型快照事实表
- 累积型快照事实表是基于一个业务流程中的多个关键业务过程联合处理而构建的事实表,如交易流程中的下单、支付、发货、确认收货业务过程。
- 累积型快照事实表通常具有多个日期字段,每个日期对应业务流程中的一个关键业务过程(里程碑)。

五、维度建模理论之维度表
维度表是维度建模的基础和灵魂。前文提到,事实表紧紧围绕业务过程进行设计,而维度表则围绕业务过程所处的环境进行设计。维度表主要包含一个主键和各种维度字段,维度字段成为维度属性。
5.1 维度表设计步骤
- 确定维度
在设计事实表时,已经确定了与每个事实表相关的维度,理论上每个相关维度均需对应一张维度表。需要注意到,可能存在多个事实表与同一个维度都相关的情况,这种情况需保证维度的唯一性,即只创建一张维度表。另外,如果某些维度表的维度属性很少,例如只有一个名称,则可不创建维度表,而把该表的维度属性直接增加到与之相关的事实表中,这个操作称为维度退化
- 确定主维表和相关维表
此处的主维表和相关维表均指业务系统中与某维度相关的表。例如业务系统中与商品相关的表有sku_info,spu_info,base_trademark,base_category3,base_category2,base_category1等,其中sku_info 就称为商品维度的主维表,其余表称为商品维度的相关维表。
- 确定维度属性
确定维度属性即确定维度表字段。维度属性主要来自于业务系统中与该维度对应的主维表和相关维表。维度属性可直接从主维表或相关维表中选择,也可通过进一步加工得到。
确定维度属性时,需要遵循以下要求:
(1)尽可能生成丰富的维度属性。
(2)尽量不使用编码,而使用明确的文字说明,一般可以编码和文字共存。
(3)尽量沉淀出通用的维度属性。
5.2 维度设计要点
5.2.1 规范化与反规范化
5.2.1.1 规范化
规范化是指使用一系列范式设计数据库的过程,其目的是减少数据冗余,增强数据的一致性。通常情况下,规范化之后,一张表的字段会拆分到多张表。
5.2.1.2 反规范化
反规范化是指将多张表的数据冗余到一张表,其目的是减少 join 操作,提高查询性能。在设计维度表,如果对其进行规范化,得到的维度模型称为雪花模型 ,如果对其进行反规范化,得到的模型称为星型模型。
5.2.1.3 常用维度模型
- 星型模型
一个中心的事实表,周围连接多个维度表。所有维度表都是扁平、非规范化的,每个维度只对应一张表。维度表包含了该维度所有的层次和属性。存在大量数据冗余,牺牲存储换取查询速度。查询时只需进行少量的表连接,性能高。
- 雪花模型
是星型模型的规范化版本,在星型模型的基础上,将维度表进一步规范化,拆分成多层,一个维度可能被分解为多个关联的表,形如雪花。减少了数据冗余,节省存储空间。更符合数据库设计范式。查询时需要连接更多的表,性能通常低于星型模型。
- 星座模型
也称星系模型,是多个事实表共享维度表的模型。可以看作是多个星型模型(或雪花模型)组合在一起,这姓星型模型共享某些公共的维度表。这是数据仓库中最常见、最现实的情况,因为一个企业不会只有一个业务过程。它支持从不同业务角度(事实表)进行交叉分析(例如,用同一套产品、时间维度,同时分析销售和库存)。
如何选择使用哪种模型?
-
优先选择星型模型 :在绝大多数BI和分析场景下,星型模型是首选。因为它用适量的存储空间(现在存储很便宜)换来了极佳的查询性能和简洁性。
-
谨慎使用雪花模型:除非有明确的、强烈的需求(如某些金融行业对数据规范化有严格要求,或某些维度层次极其复杂且更新频繁),否则应避免使用雪花模型,因为它会损害查询性能。
-
星座模型是必然归宿 :当需要构建覆盖多个业务领域的数据仓库时,星座模型是必然的选择。其设计核心是建立一致的、共享的维度(一致性维度),这是实现企业数据集成和跨主题分析的关键。
5.2.2 维度变化
维度属性通常不是静态的,而是会随时间变化的,数据仓库的一个重要特点就是反映历史的变化,所以如何保存维度的历史状态是维度设计的重要工作之一。保存维度数据的历史状态通常有两种做法,分别是全量快照表和拉链表。
5.2.2.1 全量快照表
离线数据仓库的计算周期通常为每天一次,所以可以每天保存一份全量的维度数据。
优点 :简单而有效,开发和维护成本低,且方便理解和使用。
缺点:缺点是浪费存储空间,尤其是当数据的变化比例比较低时。
5.2.2.2 拉链表
拉链表的意义就在于能够高效的保存维度信息的历史状态。
1. 什么是拉链表?
拉链表,记录每条信息的生命周期,一旦一条记录的生命周期结束,就重新开始一条新的记录,并把当前日期放入生效开始日期。
如果房前信息至今有效,在生效日期中填入一个极大值(如 9999-12-31)。

2.为什么要做拉链表?
拉链表适合于:数据会发生变化,但是变化频率并不高的维度(即缓慢变化维)。
比如:用户信息会发生变化,但是每天变化的比例不高。如果数据量有一定规模,按照每日全量的方式保存效率很低。

3.如何使用拉链表
通过,生效开始日期 <= 某个日期 且 生效结束日期 >= 某个日期,能够得到某个时间点的数据全量切片。
(1)拉链表数据

(2)例如获取 2022-01-01 的历史切片:
sql
select * from user_info where start_date <='2022-01-01' and end_date >= '2022-01-01'

(3)例如获取 2022-01-02 的历史切片:
sql
select * from user_info where start_date <='2022-01-02' and end_date >= '2022-01-02'

5.2.3 多值维度
如果事实表中一条记录在某个维度表中有多条记录与之对应,则称为"多值维度"。例如,下单事实表中的一条记录为一个订单,一个订单可能包含多个商品,所以商品维度表中就可能有多条数据与之对应。
在标准的星型模型中,事实表通过外键只关联到维度表的一条记录。多值维度违反了这个一对一的假设。这会造成数据不准确与错误合计、信息丢失、分析粒度错乱、查询复杂与性能低下。
针对这种情况,通常采用以下两种方案解决:
- 降低事实表的粒度,例如将订单事实表的粒度由一个订单降为一个订单中的一个商品项。(主要用这个)
- 在事实表中采用多个字段保存多个纬度值,每个字段保存一个维度id。(这个方案只适用于多值维度个数固定的情况)
5.2.4 多值属性
维表中的某个属性同时有多个值,称之为"多值属性",例如商品维度的平台属性和销售属性,每个商品均有多个属性值。
多值属性违反了数据库第一范式的"原子性"要求。这会造成查询与筛选功能失效、分组与聚合困难、数据更新和删除困难、空间浪费和性能差。
针对这种情况,通常可以采用以下两种解决方案:
- 将多值属性放到一个字段,该字段内容为 key1:value1,key2:value2 的形式,例如一个手机商品的平台属性值为"品牌:华为,系统:鸿蒙,CPU:麒麟990"。
- 将多值属性放到多个字段,每个字段对应一个属性。(只适用于多值属性个数固定的情况)