维度模型- 缓慢变化维度

零案例:

             用户维度表(不使用代理主键):

用户id用户性别用户地址用户等级部门
张小花北京3财务部

            采购事实表:

订单id用户id产品id时间金额
1张小花乌龟2000-01-0115
2张小花王八2000-02-0125

             性别汇总表,每年一个分区:

年度性别金额
200040

     

一 . 第一种方式:直接修改维度值

变化属性:张小花性别从男变成女

修改后的维度属性:

用户id用户性别用户地址用户等级部门
张小花北京3财务部

优点: 简单

缺点: 丢历史, 所有数据都挂在最新维度值上。其实也算不得缺点,可能就是要这个效果。

适用场景:适合修正错误属性,或者确定目前和以后不需要历史的属性。比如用户性别,如果需要修改,肯定是以前弄错了。

隐含的成本: 汇总必须和明细保持一致。 如果有基于直接修改的维度属性的汇总,维度属性修改后,必须重新汇总数据。上面表格,性别汇总表的汇总数据和最新的明细数据已经不一致了, 得全量刷新一下(所有的历史分区都得刷新, 而且也很难判定是不是有属性更新了,干脆每次调度刷全部历史分区)。

再看优点:维度表本身处理简单了, 但是以直接修改的维度属性进行汇总的所有汇总表, 都得进行全量更新。 代价也不小。

经验: 非必要不汇总, 即使汇总也最好基于key汇总,比如基于用户id 进行汇总,虽然性能不如基于性别的好,但是维护成本低。性能达标即可,没有必要追求极致,成本非常高。

二. 第二种方式,加新行

变化属性:张小花在2000-01-10 ,从财务部调到后勤部。 订单用来计算成本或者效益,当时在哪个部门发生的,归属哪个部门。

拉链维度表(没用代理主键):

用户id开始时间结束时间用户性别用户地址用户等级部门
张小花0001-01-012000-01-10北京3财务部
张小花2000-01-109999-01-01北京3后勤部

缺点: 得比对需要记录历史的属性,如果发生变更,生成一个新行。

优点:能准确描述事实表的历史环境。历史汇总无需重新刷新。

可能导致的问题:多个不相关属性缓慢变化, 结果导致维度表整体快速变化。 或者一些属性变化频率明显快与其他属性。 极值:用户的最后下单时间。 这个说起来是用户属性,但是却是用户每次下单都不一样。放在用户维度,会导致用户维表变成快变维度。所以得当成退化维度或者单独建维度表。适可而止,别过分,太过分的话,用户表的可变属性都得拆出去,会生成太多的小维表。用户表的变化频率在可接受范围内就行了。

三.  第一种方式和第二种方式比较

第一种方式其实就是修正维度属性, 顺便修正相关的下游表(根据维度属性进行汇总的表)。

第二种方式是记录正确数据的历史变更。

拿到一个维度表,首先分一下, 哪些属性的变更是修正数据,哪些属性的变更是正常的变更。

有必要,再分一下属性的变化频率,重点关注一下变化特别快的属性。

不能盲目的对所有属性采用第一种或者第二种方法。

四. 其他方式

五. 每天一个最新快照

这个应该是大数据里用的最普遍的一种方式, 可能也是问题最多的方式。

1. 如果关联最新分区的维度表, 其实就是第一种方式,完全丢了历史。

2.如果根据业务时间关联对应分区的维度, 维度表其实就相当于对全表每天一条拉链, 而忽略有些属性是需要第一种方式的。如上面表格的性别属性, 事实表 和维度表通过 用户id 和etldt 进行关联,有一段时间关联出来的维度属性就不正确。 这个不是历史,是需要被修正的。还有,如果业务日期足够久远,维度表可能提供不了那么久远的快照。

优点: 简单

缺点: 浪费一点存储, 更关键的是他全行采用第一种或者第二种方法,没有进行拆分。 不一定满足需求

六. 第一种方式+ 第二种方式

这两种方式分别有适用对象,而一个维度表通常包含多个类型的属性,所以通常我们要两种方式结合使用。

用户id用户性别用户地址用户等级部门
张小花北京3财务部

拿这个举例, 

第一步,划分一下属性, 用户性别适合第一类; 用户地址, 用户等级, 部门适合第二类

假设,  2001-01-01 ,张小花从财务部调了 后勤部

            2001-02-01 ,发现张小花的性别搞错了,

生成的维度表应该是这样子:

1. 初始

用户id开始时间结束时间用户性别用户地址用户等级部门
张小花0001-01-19999-01-01北京3财务部

2.  2001-01-01 ,张小花从财务部调了 后勤部

用户id开始时间结束时间用户性别用户地址用户等级部门
张小花0001-01-12001-01-01北京3财务部
张小花2001-01-019999-01-01北京3后勤部

3. 2001-02-01 ,发现张小花的性别搞错了,

       

用户id开始时间结束时间用户性别用户地址用户等级部门
张小花0001-01-12001-01-01北京3财务部
张小花2001-01-019999-01-01北京3后勤部

      注意, 这里把已经关链的数据的性别也进行了修正。但是需要关注历史的字段没有改变,所以没有生成新的行。

      可以增加一个cdc字段, 把需要记录历史的字段生成一个cdc, 当cdc变化时,关闭旧链,生成新链。

   其他字段,每次都用最新值提花以前的旧值, 包括已经关链的行。 关链,只是对需要记录历史的属性关联,不再改变。 需要修正的数据,每次都是全表更新。

再啰嗦一句, 如果已经对维度表的属性进行了划分,哪些适用第一种方式,哪些适用第二种方式, 千万别根据第一种方式的属性进行汇总,千千万!! 除非你确认他绝对正确。 否则就需要每次对这个汇总表的所有历史分区重新计算。

七. 第一种方式+第二种方式变种

用户看数的需求是多样的,也不该由数仓去约束人家看数方式对不对,只能尽量去满足。

用户id用户性别用户地址用户等级部门
张小花北京3财务部

比如,明知道用户性别不存在历史只有对错, 但是数据已经对外输出了,不可更改。然后又想看看真实的数据。 

实现方式: 加列, 一列性别记录历史做拉链, 一列保留最新值。想用那列用哪列,想咋看咋看。

这块就没止境了, 维度就是想各种办法, 满足用户看数的需求。 

  • 10
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值