这是我的第28篇原创
《如何搭建一个数据仓库》这篇文章被几个大号转载了。有很多朋友留言,说能不能再细细的讲讲3NF、维度模型、宽表模型这几种模型。
最近工作有些忙,今天终于抽出空来好好写一下。
3NF模型
但凡是计算机科学、软件工程、信息技术等专业毕业的同学,大学的时候肯定有一门必修课《数据库原理》,在那本书里就非常详细的剖析了3NF(三范式)。但是那个解释非常晦涩难懂,甚至还有数学论证,摆明了就是不想让人看懂。
其实3NF很容易理解,换一个说法你就明白了。
三范式是数据库建表(类同于excel的sheet页)设计原则,分为第一范式、第二范式、第三范式(这也太简单了吧?),其实还有第四范式、第五范式,不过那都没人用。
- 第一范式:保证列的原子性(每一列都是不重复的,不可再拆分的原子列);人话翻译:每一列都只说一个事情。
- 第二范式:保证行的原子性(每一行都有唯一的主键,其他字段的值与主键一一对应);人话翻译:每一行都只说一个事情。
- 第三范式:保证表的原子性(每张表中的数据不会冗余,一旦有冗余字段,就需要拆一张表出来,用外键与主表关联)人话翻译:每张表都只说一个事情。是不是很简单?
详细的解释可以看我之前的文章《抽象真实世界的利器-三范式》,那篇文章讲的透透的。
三范式主要应用在业务数据库中,也就是传说中的OLTP(联机事务处理)。为啥叫联机事务处理这么生涩的名字,我当初也是纳闷了很久。后来我明白了,其实是相对于单机事务处理来的。
以前都是单机版程序,一台电脑完成所有业务流程和数据读写。后来架构分离了,变成C/S、B/S架构,那就必须得好几台机器连在一起,所以叫联机。事务处理好理解,就是业务流程(事务)处理的意思了。
维度模型
维度模型中,一般分为两种:星型模型和雪花模型,再往上就是CUBE。
星型模型
看下图你就知道为啥叫星型模型了,就是抽象出来的样子像一颗星星。
如果你足够仔细,其实就能发现星型模型,乃至于维度模型的秘密。
在维度模型的设计理念中,数据工程师把所有的业务操作抽象成两类:
- 一类是业务操作时,需要的一些基础信息,也就是事实发生的前提。比如商品列表、商家信息等;
- 一类是业务操作结果的记录,也就是当时事实的记录结果,所以叫事实,对应的表就叫事实表。比如上图中的订单事实表,就是记录了当时这个订单发生的所有事实,比如你买了几个东西,多少钱等。
这两类信息必须关联起来,才能形成完整的交易链条。这两类信息画成图,就是中间是事实表,四周是维表,中间用代码连接。整个形状像是一个星星一样,所以叫星型模型。
雪花模型
我朋友圈里全是聪明人,所以不看图你也应该能猜到,雪花模型为啥叫这个名字了。是的,没错!就是因为形状像雪花。
逻辑跟星型模型是一样的,事实表、维度表。
在关系型数据库中,那时候存储还比较贵,磁盘很小,所以每一份数据都要尽量少存一些,所以当时会严格按照三范式的要求,把每一个属性都单独抽成表。以全国的三级行政区划表为例,如果是一张表,三个列,就是省代码、省名称、市代码、市名称、县代码、县名称,省代码和省名称会重复非常多次。拆成三张表,就是一张省表、一张市表、一张县表,省表里有三十几条数据,市表里几百条数据;县表里就几千条数据。
另外一个好处就是表间关系就非常清晰,看到雪花模型图,一眼就能看明白整个架构有哪些内容,各自的关系是怎样的。
星系模型
雪花模型还有一个变种,叫做星系模型(星座模型),其实就是多个雪花模型连在一起。
如上表所示,上下是订单和营销两个雪花模型,两片雪花通过两个事实表连接在一起,形成一个星系。另外,在星系中还会对每个雪花中相同的维度进行抽象,比如地区维度,这时候星系就会很复杂,上图中为了保持简洁,并没有体现这种情况。
CUBE模型
之所以叫cube,就是因为抽象出来就像一个魔方-magic cube。
这个形象倒是很形象,但是很多人依然看不明白。你这个CUBE跟上面的维度模型貌似没啥区别啊,就是把每个维度中的值给罗列出来了而已。这类图最坑的地方就是只告诉你cube的维度了,没告诉大家事实在哪里,所以大家都糊里糊涂的。
这么写一下你就明白了。我们可以通过类目、订单状态和月份三个维度,去看订单量、订单金额的统计结果。减少一个维度,就是上卷,增加一个维度就是下钻。就这么简单。
所以理解cube,你可以取个巧:CUBE模型其实就是多维模型的存储结构。在kylin这类预计算的MOLAP产品中,资料稍微详细、易懂一些。kylin会把每个组合方式计算一遍,然后存储下来。在查询的时候,kylin直接读取预计算的结果就好了,所以速度非常快,但是非常占存储。为了减少存储,kylin提供了剪枝的功能,就是把不常要的某个分支给删掉。
以上图为例,一个类目+订单状态+月份的cube,其实会生成0维1张表,1维3*1=3张表,2维C32=(3*2)/(2*1)=3张表(3张表,两两组合),3维1张表,总共8张表。这才3个维啊!我们现在动辄几十个维度,这个存储你可想而知了。
宽表模型
前面讲过三范式。严格按照三范式的规则设计出来的表就是窄表,每张表只说一件事情,如果顺带说了其他事情,就要拆表。相对于窄表来说,一张表中说了好几个事情,好几个概念,就是宽表了。宽表其实就是三范式的退化。宽表在关系型数据库中是异类,但是在NoSQL数据库中大行其道。
上图就是用三个窄表解决了订单业务数据存储。优点是关系非常清晰,一眼能看明白实体以及之间的关系。
上表就是一张大宽表,冗余了卖家和买家的信息。对开发、数据分析师非常友好,不用join,直接拖数据就好了。
建模方法总结
从星型到雪花到星系到CUBE,最后到宽表,面对的业务越来越多,关系越来越复杂,数据量也越来越多。在关系型数据库为数仓载体的时候,我们尽可能的保证实体与关系之间的清晰逻辑。
但是在NoSQL环境中,分布式数据库JOIN的代价比较大,另外呢,现在的存储也非常便宜。所以星系模型是废了,雪花模型已经基本不用了;星型模型和CUBE在一些情况还在用;加上现在对效率的要求越来越高,所以数据仓库靠上的两层,基本都是直接建大宽表,导致现在很多人就知道宽表,而不知道其他模型了。
但是,这个世界始终还是底层规则决定上层逻辑。对于底层规则吃的越透,上层逻辑就越容易理解。
以上,与诸位共勉!