前言
上篇文章介绍了er模型,本次接着往下介绍维度数据模型,两者都是数据库建模的重要基础,分别适用于不同的场景。由于本人是边学习边发文,经验不足之处还请见谅,错误之处欢迎指教。
一、什么是维度建模
通俗来说,就是按照业务流程需求,将一个业务看作一个事实,事实所处的环境称为维度。如一个下单流程中的付款业务也看作为一个事实,其付款时间,付款人,付款商品则可以看作维度。因此,其包括事实和维度两个部分。因此在构建表时,先确定事实表,再确定维度表,一个维度表可以被多个事实表对应,以减少数据冗余。
二、维度建模和er建模
前文有过分析er建模的优缺点。其通过多级范式,在减少数据冗余和维持数据的一致性上具有较大优势,但是通常用于存储静态数据,如存储学校的学生数据,但是在业务场景,却不适用。
上图为一个较为典型的er建模结果,可以发现表格松散、零碎,每个表都有较多的分支,类似于一个雪花,因此也叫雪花模型。当需要进行一个select时,则需要多表join,性能较差。而维度建模将业务需要的数据放在一块,事实表与业务相关,也只跟维度表,因此,虽然增加了数据的冗余,但是却适用于数据的分析和处理。
三、事实表的构建
事务表根据对业务过程度量值的不同分为事务型事实表、周期快照事务表、累计快照事务表。
1、事务型事实表
事实事实表构建基于“选择业务->声明粒度->确定维度->确定事实”,粒度即为定义一行数据代表的含义,如一行表示一个商品的信息。事实指的是每个业务过程的度量值,如次数,个数等。
事务型事实表可以存储最细粒度操作事件,因此可以支持业务过程中统计粒度的需要。但存在如下缺点:
1)不适合处理存量指标
如虚拟货币的使用,其包含于虚拟货币的获取和虚拟货币的使用两个业务中,当我们想获取当天用户虚拟货币的余额,我们则需要对两张表的历史数据进行一次全量的聚合,如果表的数据量很大的话,则需要耗费较大的时间代价。
2)多表的join操作,如我们跟踪下单商品,需要知道下单时间,发货时间,送达时间,同样的,其都对应不同的事务事实表,需要进行join操作,同样,两张大表的join耗时不小。
因此针对上述两个问题,分别提出了另外两种事务表类型。
2、周期快照事务表
周期,表示该表是动态的操作,快照结合周期意味着全量同步,即每隔一段时间,将需要使用的业务表数据全量同步,构建周期快照事务表。则无需对以前的历史数据再做聚合,只需要对当天数据进行全量同步,显著减少了表的规模。
周期快照表的构建流程:确认粒度,确定事实。粒度包括维度加上采样周期。
3、累计快照事务表
和上面的思路一样,避免大表的join,因此根据需求,将多个事实放在同一张表里,需要使用时便可拿出直接计算。
其构建过程和事务性事实表基本一致。维度一般选择每个业务过程的日期维度。
四、维度表
4.1 维度表的构建
1、确定维度,构建维度表
一个事实表对应一张维度表,而一张维度表可能会被多个事实表所对应,因此在构建时要避免重复构建而且要保证维度的唯一性。
2、确定主维表和相关维表
主维表和相关维表都是在业务系统中与维度表相关的表,主维表通常而言是粒度分的更细的表,如商品的详情表则比商品类别表粒度更细。主维表外的其他表则都是相关维表,相关维表与主维表有关,用于帮助确定主维表的部分属性。而维度表的粒度通常和主维表保持一致。
3、确认维度表属性
维度表属性可以由主维表和相关维表的字段产生以及字段拼接产生,属性的确定应该注意以下几点:
1)尽可能使用多的属性,因为维度表的属性通常用于做分析统计,是用于做where,group的字段,字段越多,则支持的指标越丰富。
2)文字和编码共存,数据的存储以编码方式存更为合适,但是以纯编码形式我们又不懂其中的含义,因此需要文字和编码的共存。如商品id对应的商品是啥。
3)沉淀通用的维度属性,某些指标需要维度表通过复杂计算才能得到,我们可以考虑将其加入维度表中,避免后续的重复计算。与上文的累计型快照事实表有异曲同工之处。
4.2 维度表的变化
维度表的数据也是时刻发生变化的,如一个用户更改其手机号码等都会造成维度表的变化。对于数据仓库而言,需要保存历史信息以便于数据分析,因此对于变化的维度历史数据应该如何保存?目前的思路1:全量同步,即每天保存一份全量数据表,该方法快捷有效,就是占用空间较多。思路2:采取拉链表。
拉链表,zip,也可以称为压缩表,我们不进行全量数据 的同步。而是在一张表上,记录下前后两次的更改日期以及更改后的状态(即记录生命周期)。
4.3 多值维度
对于事实表而言的。在事实表中的一行数据,在维度表中对应多个。如订单业务,粒度为每个订单,一个订单会包含多个商品,因此会造成多值维度。
解决方案:降低粒度,将事实表粒度降低为记录每个商品。
4.3 多值属性
对于维度表而言,如一个商品,其可能对应多个标签,每种商品对应标签个数也不同。且一个商品就商品标签不同,其他信息都一致。此处降低粒度显然不是很好的方案,意味着会造成大量数据的重复。因此此处的解决方案:
在hive中,是能存储复杂数据结构的,因此可以采取key:v键值对在一个表格中存储。