多学点容易被忽略的数据建模知识
学点容易被忽略的建模知识
并不是说,时代进步了,技术升级了,历史的思考就不再被重视了,恰恰相反,越是顶尖的建模师,越应该去看最基础的理论。就像围棋一样,顶尖高手不是靠天马行空的创意赢得比赛,而是每一步最踏实的落子。
-- 读书笔记《数据仓库生命周期工具箱》。
|0x00 维度建模再重读
维度方法并不是一个人发明创造的,在数据库设计中,它具有不可抗拒的魅力,当设计人员将【可理解性】和【性能】作为最高目标时,维度方法总是首选。
维度建模将客观世界划分为度量和上下文,度量是由公司的业务过程和支持它们的业务源系统捕捉的,常常以数值的形式出现,我们将它们称作“事实”。事实由大量文本形式的上下文包围着,这些文本形式的上下文只有当事实被记录时才为真。这种上下文被直观地分割成了多个独立的逻辑块,我们将其称作“维”。维度描述了度量上下文的5W(who、what、when、where、why)信息,以及这些上下文是如何作用的。
关系数据库平台中存储的维度模型一般都被称作是星型模式,存储在OLAP结构中的维度模型被称为多维数据集,OLAP多维数据集都可以由维度星型模式生成。
业界有时将符合第三范式的模型称作ER模型,ER是实体-关系的首字母缩写,通过方框和连线来描述数据库表之间的联系,第三范式模型和维度模型都可以用ER图的形式来描述,二者之间的主要区别是规范化程度有所不同,正是因为第三范式模型和维度模型都能够用E-R图来描述,我们才尽量避免将符合第三范式的模型称作E-R模型,而是将其称作规范化模型来防止混淆。
可解释性是维度模型得以广泛应用的一个主要原因,建模过程中要“让所有的事项尽可能简单,但又不能简单得过了头”。业务分类可以帮助用户查询模型,因为如果某个分类和具体的分析操作并不相关,那么整个维度的内容都可以被跳过。但如果业务过程过度简化,那么模型就会丢失大量有价值的信息,而这些信息对于模型的性能好坏和人们理解业务过程往往都是非常重要的。
查询性能是维度建模的第二个主要驱动因素,反规范化维度层次结构和解码查询都对查询性能有十分重要的影响。
维度模型的第三个优点,每个维都是一个等效的事实表入口点,这种对称性使维度模型能够承受查询模式中的意外变化。在即席攻击中,来自各个角落的查询像暴风雪一般涌来,系统无法预知它们的查询模式,不过,维度模型的对称结构能够高效地处理所有查询任务。用技术术语来说,意味着星型联接数据库的查询优化是简单、可预测和可控制的。
维度模型进行扩展也是比较容易的,可以容纳那些事先未预料到的新数据,通过新增字段就可以进行相应的该表,而且一般不需要重载数据。
综上所述,按照一定的开发规范,写的又快、读起来简洁、扩展方便、性能还不差,是我们数仓的目标,维度建模就是数据界的“谷歌代码规范”。
|0x01 事实表
事实表存储了从机构业务活动或者事件中提炼出来的性能度量,“事实”其实就是指每种性能度量。一般来说,我们不会预先知道某个事实的价值,因为事实也是变化的,对事实价值的评估出现在度量时间发生的时候,如收到订单、运送订购货物或者记录服务问题等事件。可以想象自己正在装货点观察运输的过程,在产品被搬放到即将出发的货车上的过程中,每次都会产生一些事实(性能度量),例如运输量,几乎每一个事实都是数值型,大多数的事实是具备可加性的,这非常重要。
事实表在设计时,每个外键都必须和对应维度表的唯一主键相匹配,也就是说,事实表的外键不应当为空,因为如果为空,就违背了参照完整性。
事实表应当包含从业务过程中捕捉的最底层的、最细节的原子粒度,这样的数据会具有很强的灵活性和弹性,以尽可能地支持精确的查询请求。设计师Mies van der Rohe信奉这样的说法:“上帝是偏爱细节的。”事实表如果具有最细节的数据,那么就可能使模型具有最大的灵活性和可扩展性。
事实表通常是快速增长、不断变化的,因为它总是存储最细的细节,而事实表的复杂程度,可以决定我们下游数仓的实时程度。当你的业务逻辑不太复杂时,数仓的设计便可以脱离离线的思维,通过实时的方式进行计算,或者通过OLAP引擎,直接面向数据库统计。但如果你的业务很复杂,比如订单金额拆分子订单,遇到除不尽的情况时,或者是递归层次遇到图关系情况时,传统离线数仓还是很适合处理这一类的情况。
|0x02 维度表
事实表仅由键和数值型度量所组成,因此它们具有健壮性和完整性的特点,但与事实表不同,维度表不具有健壮性和完整性,它们当中充满了“大而笨重”的描述性字段。
因此,维度模型的优点在于所有的属性成为过滤条件或者标记的时候都是等价的,它具备了以下的特点:
是冗长的(名称由完整的词汇组成) 是描述性的 是完整的(没有遗漏值) 是离散取值的(维度表中的每一行仅取一个值) 质量是有保证的(没有错误拼写等)
这里有个小技巧,维度属性列中的空值常常会使业务用户感到困惑,并且会使SQL查询语句的性能受到影响,因此我们一般推荐使用描述性的字符串来代替空值,如“未知”。
维度表几乎必然会用于表示层次关系,在一个单独的维里面,解析几个多对一的层次关系很常见,这也是反规范化的必然结果。例如,如果产品可以上卷到品牌,而品牌可以上卷到类别,就可以用一个单独的产品维度来表示该层次的关系,该表中有和品牌及类别描述相对应的属性。部分人会认为应该将品牌和类别分别存储在单独的维中,但这样做会干扰可理解性和查询性能。
规范化的一致性维度是所有精心设计的数据仓库都在追求的目标,有时也将其称为主维度或者公共参照维度。如果两个一致性维度是完全相同的,那么它们有相同的键、属性名、属性定义和域值,不管它们联接什么样的事实表。例如销售订单事实表所参照的产品维和库存量事实表所联接的产品维度是相同的。这种维度表提供了相同的内容和解释,不管相关的业务过程如何。
上游加个维度,或者去掉一个维度,都是业务很常见的情况,但如果维度无法保证一致性,一次业务改动就足够让下游忙活半天了,例如将缓慢变化维放到了事实表里,这个维度没了,下游却依赖了上千张表,一种“积重难返”的感觉就会油然而生。你可以为了速度不仔细考虑维度的变化,但当问题发生时,我们就只能被迫的“以灾难推动规范治理”了。
|0xFF 结语
本文大部分是从原书中摘抄的段落。之所以要发出来,是因为最近对于维度模型的理解,有了一些更深层次的感受。
例如,维度模型的第一要义是可解释性,但事实上,大多数的非数据从业人员,都不太理解维度模型的理念,正常的认知是,我怎么好用,就怎么设计,为什么要冗余这么多信息,思考这么多过程。但对于数据从业人员而言,按照规范,就降低了很多未来挖坑的可能性,就像是Java编码规范一样,坏的代码总是一直被写出来,只是为了把业务跑起来,但苦了下一代接手的程序员。在工程界,各种规范、CR都应用的很广泛了,但数据领域,似乎还没有达成共识。
所以,读一些老书,很重要,因为老的一些场景,不会那么复杂,便于理解一件事情最原本的初心。