1. 维度建模概述
- 维度建模理论为Ralph-Kimball 倡导的建模方法;
- 维度模型面向业务,将复杂业务通过
事实
和维度
呈现出来。 - 事实
对应业务过程,
维度`对应业务过程发生时所处的环境; - 维度模型以数据分析作为出发点,不遵循三范式,故数据存在一定的冗余。
- 表结构简单,故查询简单,查询效率较高。
维度建模的特点就是以事实表为核心,一个事实表代表一个业务过程;
2. 事实表
- 事实表中的每行数据代表一个业务事件(下单、支付、退款、评价等)
- “事实”这个术语表示的是业务事件的度量值(可统计次数、个数、金额等)
- 事实表的字段有3部分组成,一个是主键,唯一代表一次业务操作;然后是维度外键,其关联维度表;最后是度量值,用来度量这次业务操作;
例如,2020年5月21日,宋宋老师在京东花了250块钱买了一瓶海狗人参丸。维度 : 时间、用户、商品、商家。事实:250块钱、一瓶
事实表的特征:
- 数据量非常的大;因为一条数据表示一个业务事件,受用户行为影响
- 内容相对的窄:列数较少(主要是外键id和度量值)
- 经常发生变化,每天会新增加很多 ,一个业务事件对应一行记录
2.1 事务型事实表
事务事实表用来记录各业务过程,它保存的是各业务过程的原子操作事件,即最细粒度的操作事件。粒度是指事实表中一行数据所表达的业务细节程度。
事务型事实表可用于分析与各业务过程相关的各项统计指标,由于其保存了最细粒度的记录,可以提供最大限度的灵活性,可以支持无法预期的各种细节层次的统计需求。
- 最细粒度的操作事件
- 以每个事务或事件为单位,例如一个销售订单记录,一笔支付记录等,作为事实表里的一行数据。
- 一旦事务被提交,事实表数据被插入,数据就不再进行更改,其更新方式为增量更新。(保留所有操作事件 )
- 事务性事实表在做同步的时候都是用增量同步
设计流程
选择业务过程→声明粒度→确认维度→确认事实
1)选择业务过程
- 在业务系统中,挑选我们感兴趣(由指标需求决定,当然不完全,可以有前瞻性,未来会有哪些需求)的业务过程;(根据要统计的指标确定需要哪个业务过程的数据,比如要统计每日下单量,那就需要下单这个业务)
- 业务过程可以概括为一个个不可拆分的行为事件,例如电商交易中的下单,取消订单,付款,退单等,都是业务过程。
- 通常情况下,一个业务过程对应一张事务型事实表
2)声明粒度
业务过程确定后,需要为每个业务过程声明粒度。即精确定义每张事务型事实表的每行数据表示什么,应该尽可能选择最细粒度,以此来应各种细节程度的需求。
典型的事实表粒度声明如下:
订单事实表中一行数据表示的是一个订单中的一个商品项。因为商品项比订单还细,一个订单中有多个商品
最细粒度:说白了就是维度尽可能多!!!
3)确定维度
确定维度具体是指,确定与每张事务型事实表相关的维度有哪些。
确定维度时应尽量多的选择与业务过程相关的环境信息。因为维度的丰富程度就决定了维度模型能够支持的指标丰富程度。
4)确定事实
此处的“事实”一词,指的是每个业务过程的度量值(通常是可累加的数字类型的值,例如:次数、个数、件数、金额等)。
经过上述四个步骤,事务型事实表就基本设计完成了。第一步选择业务过程可以确定有哪些事务型事实表,第二步可以确定每张事务型事实表的每行数据是什么,第三步可以确定每张事务型事实表的维度外键,第四步可以确定每张事务型事实表的度量值字段。
不足
事务型事实表可以保存所有业务过程的最细粒度的操作事件,故理论上其可以支撑与各业务过程相关的各种统计粒度的需求。但对于某些特定类型的需求,其逻辑可能会比较复杂,或者效率会比较低下。例如:
1)存量型指标 例如商品库存,账户余额等。此处以电商中的业务包含的业务过程主要包括获取货币和使用货币,两个业务过程各自对应一张事务型事实表,一张存储所有的获取货币的原子操作事件,另一张存储所有使用货币的原子操作事件。
假定现有一个需求,要求统计截至当日的各用户余额。由于获取货币和使用货币均会影响到余额,故需要对两张事务型事实表进行聚合,且需要区分两者对余额的影响(加或减),另外需要对两张表的全表数据聚合才能得到统计结果。
可以看到,不论是从逻辑上还是效率上考虑,这都不是一个好的方案。
简而言之: 一个下单事实表,一个退单事实表,我们要统计一天净下单数(存量),就需要两张表数据进行聚合
2)多事务关联统计
例如,现需要统计最近30天,用户下单到支付的时间间隔的平均值。统计思路应该是找到下单事务事实表和支付事务事实表,过滤出最近30天的记录,然后按照订单id对两张事实表进行关联,之后用支付时间减去下单时间,然后再求平均值。
逻辑上虽然并不复杂,但是其效率较低,因为下单事务事实表和支付事务事实表均为大表,大表join大表的操作应尽量避免。
可以看到,在上述两种场景下事务型事实表的表现并不理想。下面要介绍的另外两种类型的事实表就是为了弥补事务型事实表的不足的。
总结
- 事务型事实表 是业务驱动的,一个业务线对应一张事务型事实表;
- 粒度要求最细,即维度尽可能多;
- 缺点:当一些指标需求需要多个业务过程的时候,用事务型事实表做join效率就很低;
- 增量同步
2.2 周期型快照事实表
周期快照事实表以具有规律性的、可预见的时间间隔来记录事实,主要用于分析一些存量型(例如商品库存,账户余额)或者状态型(空气温度,行驶速度)指标。
对于商品库存、账户余额这些存量型指标,业务系统中通常就会计算并保存最新结果,所以定期同步一份全量数据到数据仓库,构建周期型快照事实表,就能轻松应对此类统计需求,而无需再对事务型事实表中大量的历史记录进行聚合了。
对于空气温度、行驶速度这些状态型指标,由于它们的值往往是连续的,我们无法捕获其变动的原子事务操作,所以无法使用事务型事实表统计此类需求。而只能定期对其进行采样,构建周期型快照事实表。
- 周期型快照事实表中不会保留所有数据,只保留固定时间间隔的数据,例如每天或者每月的销售额,或每月的账户余额等。
例如购物车,有加减商品,随时都有可能变化,但是我们更关心每天结束时这里面有多少商品,方便我们后期统计分析。 - 一般用全量同步策略
设计流程
1)确定粒度
周期型快照事实表的粒度可由采样周期和维度描述,故确定采样周期和维度后即可确定粒度。
- 采样周期通常选择每日。
- 维度可根据统计指标决定,例如指标为统计每个仓库中每种商品的库存,则可确定维度为仓库和商品。
确定完采样周期和维度后,即可确定该表粒度为每日-仓库-商品。
2)确认事实
事实也可根据统计指标决定,例如指标为统计每个仓库中每种商品的库存,则事实为商品库存。
事实类型
此处的事实类型是指度量值的类型,而非事实表的类型。事实(度量值)共分为三类,分别是可加事实,半可加事实和不可加事实。
1)可加事实
可加事实是指 事实 可以按照事实表种任意维度进行累加,例如事务型事实表中的事实。
2)半可加事实
半可加事实是指只能按照与事实表相关的一部分维度进行累加,周期型快照事实表中的事实都是半可加事实。以上述各仓库中各商品的库存每天快照事实表为例,这张表中的库存事实可以按照仓库或者商品维度进行累加,但是不能按照时间维度进行累加,因为将每天的库存累加起来是没有任何意义的。
每天所有仓库的某个商品的库存 √
当月北京仓库的某个商品的总库存 ×
3)不可加事实
不可加事实是指完全不具备可加性,例如比率型事实。不可加事实通常需要转化为可加事实,例如比率可转化为分子和分母。
比如:各个商品的退货率;
退货率 = 商品退单次数 / 商品下单次数 ;
所有商品的退货率 是不能叠加的;可以拆成:所有商品的退单次数 和 所有商品的下单次数,这样就可以求解了;
总结
- 周期性快照事实表是由需求驱动的,需要什么指标,就设计什么样的周期性快照事实表!比如需要一些存量型指标、状态型指标
- 不要求粒度最细,粒度由采样周期和需求维度 构成
- 全量同步
2.3 累积型快照事实表
- 累计快照事实表用于跟踪业务事实的变化。
累计快照事实表是基于一个业务流程中的多个关键业务过程联合处理而构建的事实表,如交易流程中的下单、支付、发货、确认收货业务过程。
一个累积性快照事实表种有多个关键业务过程;
设计流程
累积型快照事实表的设计流程同事务型事实表类似,也可采用以下四个步骤,下面重点描述与事务型事实表的不同之处。
选择业务过程→声明粒度→确认维度→确认事实
1)选择业务过程
选择一个业务流程中需要关联分析的多个关键业务过程,多个业务过程对应一张累积型快照事实表。
2)声明粒度
精确定义每行数据表示的是什么,尽量选择最小粒度。(这里不要求必须是最小粒度,事务型事实表必须是最小粒度)
3)确认维度
选择与各业务过程相关的维度,需要注意的是,每各业务过程均需要一个日期维度。
4)确认事实
选择各业务过程的度量值。
总结
- 累积型快照事实表是需求驱动的,当一个指标跨多个业务时,可以考虑设计累积型快照事实表。
- 一行有多个业务过程及业务发生时间
- 粒度不做最小要求
3 维度表
维度表是维度建模的基础和灵魂。前文提到,事实表紧紧围绕业务过程进行设计,而维度表则围绕业务过程所处的环境进行设计。维度表主要包含一个主键和各种维度字段,维度字段称为维度属性。
维度表:一般是对事实的描述信息。每一张维表对应现实世界中的一个对象或者概念。 例如:用户、商品、日期、地区等。
维表的特征:
- 维表的范围很宽(具有多个属性、列比较多)
- 跟事实表相比,行数相对较小:通常< 10万条
- 内容相对固定:编码表
比如时间维度表:
3.1 维度表设计步骤
1)确定维度(确定表)
在设计事实表时,已经确定了与每个事实表相关的维度,理论上每个相关维度均需对应一张维度表。
- 唯一性: 需要注意到,可能存在多个事实表与同一个维度都相关的情况,这种情况需保证维度的唯一性,即只创建一张维度表。
- 维度退化: 另外,如果某些维度表的维度属性很少,例如只有一个名称,则可不创建该维度表,而把该表的维度属性直接增加到与之相关的事实表中,这个操作称为维度退化。(如果全都维度退化就不需要维度表了)
2)确定主维表和相关维表
此处的主维表和相关维表均指业务系统中与某维度相关的表。例如业务系统中与商品相关的表有sku_info,spu_info,base_trademark,base_category3,base_category2,base_category1等,其中sku_info就称为商品维度的主维表,其余表称为商品维度的相关维表。维度表的粒度通常与主维表相同。
3)确定维度属性
确定维度属性即确定维度表字段。
维度属性主要来自于业务系统中与该维度对应的主维表和相关维表。维度属性可直接从主维表或相关维表中选择,也可通过进一步加工得到。
确定维度属性时,需要遵循以下要求:
- 尽可能生成丰富的维度属性
维度属性是后续做分析统计时的查询约束条件、分组字段的基本来源,是数据易用性的关键。维度属性的丰富程度直接影响到数据模型能够支持的指标的丰富程度。 - 尽量沉淀出通用的维度属性
有些维度属性的获取需要进行比较复杂的逻辑处理,例如需要通过多个字段拼接得到。为避免后续每次使用时的重复处理,可将这些维度属性沉淀到维度表中。
3.2 维度设计要点
1.规范化与反规范化
- 规范化是指使用一系列范式设计数据库的过程,其目的是减少数据冗余,增强数据的一致性。通常情况下,规范化之后,一张表的字段会拆分到多张表。
- 反规范化是指将多张表的数据冗余到一张表,其目的是减少join操作,提高查询性能。
在设计维度表时,如果对其进行规范化,得到的维度模型称为雪花模型,如果对其进行反规范化,得到的模型称为星型模型。
在维度建模的基础上又分为三种模型:星型模型、雪花模型、星座模型
1)星型和雪花
- 星行模型的维度只有一层;
- 雪花模型靠近三范式,维度有多层;
2)星座模型
2. 维度变化
维度属性通常不是静态的,而是会随时间变化的,数据仓库的一个重要特点就是反映历史的变化,所以如何保存维度的历史状态是维度设计的重要工作之一。保存维度数据的历史状态,通常有以下两种做法,分别是全量快照表和拉链表。
1)全量快照表
- 离线数据仓库的计算周期通常为每天一次,所以可以每天保存一份全量的维度数据。这种方式的优点和缺点都很明显。
- 优点是简单而有效,开发和维护成本低,且方便理解和使用。
- 缺点是浪费存储空间,尤其是当数据的变化比例比较低时。
2)拉链表
- 拉链表的意义就在于能够更加高效的保存维度信息的历史状态。
3. 多值维度
如果事实表中一条记录在某个维度表中有多条记录与之对应,称为多值维度。
比如,下单事实表中的一条记录的粒度一个订单,一个订单可能包含多个商品,商品维度表中就可能有多条数据与之对应。
针对这种情况,通常采用以下两种方案解决:
- 第一种: 这种现象往往是由事实表的粒度不是最小粒度导致的;因此可以降低事实表的粒度,例如将订单事实表的粒度由一个订单降低为一个订单中的一个商品项。
- 第二种: 在事实表中采用多字段保存多个维度值,每个字段保存一个维度id。这种方案只适用于多值维度个数固定的情况。
- 第三种: 用集合类型的字段来保存;比如Array类型,可以保存多个skuid
建议尽量采用第一种方案解决多值维度问题。
4. 多值属性
维表中的某个属性同时有多个值,称之为“多值属性”,例如商品维度的平台属性和销售属性,每个商品均有多个属性值。
针对这种情况,通常有可以采用以下两种方案。