一:企业级数仓多事务事实表的重要性
整个企业级的数据仓库,从表的性质来分,有维度表和事实表,事务表又分为多事务事实表,累积快照事实表,周期型快照表,这些不同种类的事实表,其实在数仓里面都扮演者不同的角色。
三种事实表区分里面已经介绍过了三种事实表的大概概念。
其实有很多了解过数据仓库建模的同学,都会对多事务事实表和累积型快照表,产生疑惑,感觉像似冗余存在,其实这两种类型的事实表,是相辅相成,结合来使用已经可以满足数仓全部的指标需求了,周期型快照表只是在一定周期,按照一定粒度,完成聚合操作,是基于上诉两种事实表加工得来的。
多事务事实表,有几个优点,首先其是增量的,每天分区只存新增或者变更的数据,这对于大数据量的表来说是非常重要的,因为像累积型快照表,每天都存全量数据,空间开销是非常大的。另外一个多事务事实表更加擅长计算不跨业务过程的统计分析,如最近N天的下单/支付/发货等的订单数、金额等等。
二:多事务事实表开发的准备工作
下面内容就以电商的交易域来做例子,因为交易的各个业务过程在很多领域通用性较好,并且多个业务比较典型,且好理解。一般交易系统都包含这几个过程:下单,支付,交易,发货,签收,结算,下单后取消,支付后取消等。
涉及步骤如下:
1:选择业务过程及确定事实表类型
事实表的类型已经确定是多事务事实表了,这点毋庸置疑,业务过程的选择,往往需要结合业务需求来,但是但凡将多个业务过程组合在一起,要注意粒度一致性。这里就假设将业务过程分为:下单,支付,交易,发货,签收,结算,下单后取消,支付后取消,这是一个订单正常和非正常生命周期都会走过的过程。
2:声明粒度
事实表的粒度必须是明确的,因为粒度决定了多个业务是否能够结合使用,也决定了这个事实表的应用范围。假设这里的粒度是子订单粒度,或者可以称之为订单商品粒度。(在电商领域因为各种原因会涉及到拆单,一个订单会包含多个商品,订单粒度一般泛指一个订单,订单商品粒度一般泛指订单和商品,后者粒度很小,当然也存在交易粒度的,一个交易包含多个订单,这里就不考虑了)
3:确定维度
这点很好理解,事实表除了事实(度量值),剩余就是维度了,维度是描述事实的环境,那么自然也是为后面能够产出更多丰富的指标做准备的,尽可能丰富就对了。
4:确定事实
这里有点讲究,因为多事务事实表,存在的业务过程不止一个,每个业务过程都伴随着零到多个事实(度量值),事实也是跟维度一样,尽可能丰富,但是要注意只能选取跟业务过程有关系的度量值。就跟上诉业务过程一样,支付过程的度量可以有支付金额,优惠金额等。
5:冗余维度
降维操作,牺牲存储空间换算力,不多解释了。
三:多事务事实表开发步骤
1、准备一张包含了多个业务过程的原始增量表作为主表
一般交易那边会维护一张包含了多个业务过程并且是实时的交易表,这个表的操作一般只有insert和update,离线数据仓库需要每天取拉取一份数据,这份数据必须是增量的,可以通过监听binlog拉取增量数据,也可以全量拉取,然后筛选更新时间(一般记录都存在更新时间)来取得T-1的新增或者更新数据。
2、在业务系统那边并没有维护一张这样包含多个业务过程的原始表
2.1. 如果是这样的话,需要通过一点技巧来加工得到一张包含多个业务过程的增量表。假设现在下单,支付,交易等业务过程都是分开存储。使用同样的方法,将这几个业务表都取得增量的数据。
因为这几个业务过程同属于交易系统,那么应该是有子订单号可以用来做为关联用的,接着可以将这几个增量表的oiid(子订单号)合并去重,这一步其实是为了得到T-1的这个时间分区,有哪些子订单发生了更新,或者新增了哪些子订单。
2.2. 整个交易系统,开始第一个业务过程就是下单(创建订单),从下单表取一份全量数据,然后跟之前筛选出来的子订单号做一个join,这样就可以拿到T-1天发生变更或者新增的子订单的下单数据了。注意了这里表示的并不是T-1下单的数据。
2.3. 下单下一个业务过程是支付或者下单取消,这里需要估算一下,两个业务过程中间最大会隔多长时间,一般来讲,从业务角度来说,下单以后,必须要在30分钟内完成支付,不然该订单就会被取消,那么这两个业务过程是不是就一定间隔在30分钟内,通过筛选数据得出,其实并不是这样的,由于各种原因,可能就存在及其少数的订单就是这么另类,所以这里需要根据数据探查得出两个业务过程的最大时间间隔。得出时间间隔以后,将2.2产出的表和支付的增量表做join,支付的表可能需要跨多个天分区这是很正常的,比如交易到发货,发货到签收,都是可能隔很多天的。具体右表筛选的时间分区范围为多少,要根据数据探查的结果来定。
2.4. 重复2.3的过程,将其余几个业务过程都关联起来。当然如果有各个业务过程的全量表的话,那就更加方便了,也不用做数据探查了。但是如果都使用全量表,就体会不到多事务事实表的精髓了。这样就可以得到一张包含多个业务过程的增量表了。
3、降维操作以及其他ETL
2步骤其实已经完成了多事务事实表的大部分工作,剩余的可以根据业务需求,做一些锦上添花的操作。
3.1. 增加业务过程标识,比如是否是当天下单,当天支付,当天交易,当天发货,当天签收等,这样下游使用起来会更加方便。
3.2. 降维操作,将常用的维度就添加到这个多事务事实表当中来,方便使用,避免在下游使用过程当中,过多跟维度表关联。
3.3. 剔除测试数据等
四:多事务事实表的难点分析
1:多个业务过程中的业务时间间隔如何测量?
这个问题其实上诉已经有提到,如果使用的是全量表,那么并不会存在这个问题,这个问题只针对对增量表的使用。比如现在要测量下单到签收这个业务过程能跨的时间跨度最大是多少天。其实这个问题应该是有多种办法可以解决的。我分享一下我的思路,拿下单全量表和签收的全量表用oiid做join,然后将签收时间-下单时间,这样可以得到一个时间间隔,然后用于统计分析,比如10内完成从下单到签收的订单数有多少,占比多少,30天内完成从下单到签收的订单数有多少,占比多少,这样就可以得出最大的时间间隔以及大部分的订单都会在哪个时间段完成签收。其实就准确性而言,当然时间跨度越大,精度越高,但是这样就伴随着算力的增大。比如百分之99.99的订单,在10天都可以完成下单到签收这个过程,只有一两单时间间隔有100多天,那么这种就需要做一下取舍。
2:业务过程存在非线性变化怎么办?
假设将业务过程分为:下单,支付,交易,发货,签收,结算,下单后取消,支付后取消,这是一个订单正常和非正常生命周期都会走过的过程。
这是一个理想的状态,比如现在存在这种情况,发货后,退款,要求退货,签收以后要求退货,或者要求售后,售后完又需要重新发货或者退款,后面又有可能有售后,退货等,那么这其实就是一个非线性的业务生命周期,像这种情况的话,对于多事务事实表的业务过程抽象带来了很大的挑战,这时候需要根据业务方需求,定下来一个标准,比如刚才的售后,我们就定下来不管售后几次,都取第一次,除了业务需求,也要考量每个业务过程加入进来的意义,要尽量保证多事务事实表,简洁但又不失核心。