一、背景
很突然,本周被外bu的同学问到,数仓为什么要分层。很多时候一名同学加入团队自然就有了前人制定好的分层规范,自己只要照着做就好了,对于为什么这样做可能只是自己零星的感知,比如“公共逻辑下沉”,“增加复用性”,“隔离变化”等。但这些说法会稍显笼统,既不深入也不成体系。本次借着这个机会系统的梳理下,作为数仓开发的基本功记录下来,以供后来者参考。
二、为什么要分层
分层似乎是个很简单不用解释,又有些模糊说不太清的事情,我们不妨先看看怎么样叫不分层。数仓开发是一个由数据源生产加工到目标数据集的过程,下面这个图可以表示不分层的状态。
很显然,所有的目标数据集都是由最原始的数据源经过一次性的加工产生,没有中间过程,就是不分层的状态。虽然是一次性生产,但这里的ETL代码根据业务逻辑的复杂程度,可以是十几行也可以到上万行代码,一次性并不代表少。对于复杂的计算过程,所有的逻辑都杂糅在一块,很显然是不好维护的,真出了问题或者需要修改内容都不知道在哪里修改。因此很自然的就会想到,把一整段逻辑拆分成多个小逻辑,并把几个相近的逻辑组合成一个任务,这样就把大任务拆分成了多个小任务。
至此,其实还没有进行“分层”,只是使用了分治+封装的思想,但是很多好处已经显现出来了。
1.维护成本降低。试想一个上千行的代码从头一点点理解,有问题需要修改时的维护成本是相当高的,而且很容易出错。
2.隔离变化。试想一下,如果某天需要更换数据源A为C,只需要修改任务1的代码即可,对下游的可以做到屏蔽变化,无感知。
3.增加了复用性,进而带来一致性的提升和开发效率的提升。如下图,比如之后需要目标数据集N,需要保持与逻辑1234相同并增加逻辑89,此时可以直接在任务2的基础上增加任务5来实现逻辑89即可。这样不仅加速了开发,以后即使逻辑1234有变化,目标数据集N也会随之变化,始终保持一致。
4.持久化可以用空间换时间,节省计算资源。在此之前我们都是默认讨论进行逻辑的操作,如果对于任务2的结果进行持久化,以后基于任务2有多个下游逻辑都不用从逻辑1开始计算,一次计算多次使用,节省了计算资源。同样,如果每一个任务逻辑最终都是持久化为表的,那么结合复用性,整个数仓反而会更加节省存储。(数仓当中绝大部分任务都是进行了持久化的)
5.提升数据安全。不管是对表还是对视图,都可以按照不同规则把权限开放给不同的人,保证数据流通的前提下提升数据安全。
上面说了,到目前还没有进行严格意义上的分层,只是拆分成多个任务就有了以上的好处。那么分层是做了什么?分层是站在数仓全集的视角,对于一系列的计算过程抽象出通用的职责,规定每一层只做某些职责,每一层有自己独特的命名,并且不同层之间有明确的前后关系。对于一条生产链路,分层和任务(数据表)整体上是一对多的关系。有的链路短一层只有一个任务(数据表),有的链路复杂可能一层有好几个任务(数据表)。有了这样分层的概念,会增加一些好处。
6.统一建设思路。明确职责,明确开发的先后顺序,让不同的开发人员开发思路更加统一,以便不同的人员可以更好的协作,真正出现问题也更好的定位到哪一层。
7.血缘清晰。通过命名规范区分不同的层,可以使开发时都沿着同一个顺序进行生产,血缘关系更加清晰,避免开发和调度时的循环依赖。