多值维度及交叉维度最佳解决方案
1、前言
正常情况下,维表和事实表之间是一对多的关系,维表中的一行记录会连接事实表中的多行记录,事实表中的一行记录在维度表中只能关联上一条记录,不会发生数据发散的现象。
想法是美好的,但是事实总是不尽人意。因为现实中不但事实表和维度表之间存在多对多的关系,维度表和维度表之间也存在多对多的关系。
这两种情况本质是相同的,但事实表和维度表之间的多对多关系少了唯一描述事实和维度组的中间维度。
对于这两种情况,一种称为桥接表
的中间表就需要派上用场了,并且还可以支持更为复杂的多对多的关系。
2、事实表与维度表多对多(多值维度)
比如下单了一套学习课程,但是这套课程并不是某一个用户买的,而是好几个用户合买的,所以为了处理这种情况,需要创建一个桥接表
,将这些合买的用户组成一个组。
ETL过程需要对每条事实表中的用户组,在桥接表
中查找相应的用户主键, 上图所示的桥接表有重复计数的风险。如果按用户累加购买金额,对某些分析而言结果是正确的,但对于其他情况仍会有重复计数的问题。要解决这个问题,可以向桥接表中添加权重。
权重是一个分数值,所有的用户组的权重累加起来为1。将权重和累加事实相乘 (这里就是weight * price获取用户购买需要的金额),以按照每个用户在分组中的比重分配事实。
优点:
- 灵活简化了生成报表的难度
- 借权重避免了多重计算
缺点:
- 桥接表的维护比较复杂,当出现一个新组合时,得先判断桥接表中是否已存在
3、维表与维表多对多(交叉维度)
从分析的角度来看,维度之间的多对多关系是一个很重要的概念,大多数维度都不是完全相互独立的。
在银行系统中,账户和顾客之间有直接关系,但不是一对一的关系。一个账户可以有一个或多个签名确认的用户,一个用户也可有多个账户。
有2种方案解决:
- 和多值维度一样,创建账户-用户组桥接表来连接事实表
- 还有一种方法是利用账户和用户之间的关系,如下图
桥接表可以捕获多对多关系,并且由于源系统中的关系是已知的,因此创建桥接表比多值维度手动构建维度表(桥接表)更容易。
4、总结
处理多值维度最好的办法是降低事实表的粒度。这种处理方式也是维度建模的一个原则,即事实表应该建立在最细粒度上。这样的处理,需要对事实表的事实进行分摊。
但是有些时候,事实表的粒度是不能降低的,多值维度的出现是无法避免的。如上述交叉维度,事实表与用户维度没有直接的关系,不能将数据粒度进行细分,即使细分的话帐户余额也很难分摊。这时,可以采用桥接表技术进行处理。在帐户维度表和用户维度表之间建立个帐户-用户桥接表。这个桥接表可以解决掉帐户维度和用户维度之间的多对多关系,也解决掉的帐户维度表的多值维度问题。
总之,多值维度是应该尽量避免的,它给数据处理带来了很大的麻烦。如果多值维度不能避免的话,应该建立桥接表来进行处理。
维度: 班级(拉链表,涉及退班转班情况)/课程/城市/商品/时间/讲次/学生/机构