在最近的面试中,好多公司的面试官都会问在数据处理的过程中是怎么处理缓慢变化维的?也特意去查看了下相关的资料,今天整理出来跟大家一起分享
一.缓慢变化维的概念
缓慢变化维(Slowly Changing Dimensions)指的是:维度表里面的数据并非是始终不变的,总会随着时间发生变化。
数据仓库的重要特点之一是反应历史变化,所以如何处理维度的变化是维度设计的重要工作之一。缓慢变化维的提出是因为在现实世界中维度的属性并不是静态的,它会随着时间的流逝发生缓慢的变化。与数据增长较为快速的事实表相比,维度变化相对缓慢。
在一些情况下,保留历史数据没有什么分析价值,而在另一些情况下,保留历史数据将会起到至关重要的作用。在Kimball的理论中,有三种处理缓慢变化维的方式,下面通过简单实例进行说明。
二.处理缓慢变化维的三种方式
假设我们有一张公司的销售员维度表如下,记录了每个销售员的一些基本信息,那么随着时间的变化销售员可能会在各省公司间调岗,如将张三调入北京分公司,针对这种变化,业务系统会直接将业务数据库中张三的地址直接update为北京,而不会考虑历史变化,不过在数据仓库中由于有时我们需要进行历史变化分析,或者防止销售数据记录错误,所以需要对这种变化进行相应的处理,主要有以下三种办法:
销售员维度表
TYPE 1 SCD :重写维度值
与业务数据保持一致,同样为直接update。采用此种方法,不保留历史数据,始终取最新数据,这样就难以记录历史变化,如果张三于2019-07-01 调入北京,那么我们想要知道北京销售员在19年的销售数据时,就会将张三的业绩算入北京分公司下,实际上张三7月份以前的销售数据均应算在天津,所以为了避免这样的问题就有了TYPE2的处理方式。
缓慢渐变类型一
TYPE 2 SCD :插入新的维度行
采用此种方法,保留历史数据
不过带来一个问题,当事实表中的销售数据与此维度表进行关联时,由于存在customer_id的数据有两条1的,所以会关联出两个数据,这样是有问题的,那么就引入了一个代理键的概念,相当于数据仓库为维度表分配一个主键,而不用当初业务数据库中的主键,如下:
接着上面的表结构讲,光这样设置了新的 dw_customer_id 是不够的,因为还需要告诉数据仓库哪一条信息是现在正在使用的。当然可以根据 dw_customer_id 的顺序来查出最新的记录(因为主键往往是自增的,最大的肯定是最新的),或者根据最新的update_time来查出最新的记录,但是每次都要比较customer_id然后找出最大的 dw_customer_id 这样的查询比较麻烦。
因此可以额外一个标志表示这条数据是最新更改的。
另外的一种方式就是通过起始时间来标识,end_time为'9999-12-31' 标识当前数据,这个就涉及到拉链表了,后期会具体讲解下拉链表的具体实现方法。此种方法在互联网行业用的较少,实现比较困难,而且业务人员理解和使用起来也不是特别容易。
TYPE 3 SCD :添加维度列
采用第二种处理方式不能将变化前后记录的事实归一为变化前的维度或者归一为变化后的维度。有时需求中并非所有字段的变化都进行记录并且不需要每次变化都记录,比如我们可能只关心address(所在地)的最近两次变化,那么可以这样记录:
这样做只可以记录少量的变化次数,需要的话也可以相应加上时间列,这种方式一般用到的比较少,多数均为TYPE1,TYPE2,根据是否有必要记录历史变化进行选择。
三.其他方式
对于选择哪种方式处理缓慢变化维,并没有一个完全正确的答案,可以根据业务需求来进行选择。在互联网行业中,大多数企业都是采用的分布式的大数据平台,对于存储已经不是问题,而且大多数的维度表数据量也不是特别的大,所以很多企业处理缓慢变化维的方式是采用快照方式,数据仓库的计算周期一般是每天一次,基于此周期,处理维度变化的方式就是每天保留一份全量快照数据。这样任意一天的事实均可以获取到当天的维度信息,通过限定日期,采用自然键进行关联即可。此方法既有优点也有弊端。
优点:
1.简单而有效,开发和维护成本低。
2.使用方便,理解性好。数据使用方只需要限定日期,即可获取到当天的快照数据。任意一天的事实快照和维度快照通过维度的自然键进行关联即可。
弊端:
主要体现在存储的极大浪费上。比如某维度,每天的变化量占总体数据量的比例很低,在极端情况下,每天无变化,使得存储浪费很严重。此方法主要就是实现了牺牲存储获取ETL效率的优化和逻辑上的简化。但是一定要杜绝过度使用这种方法,而且必须要有对应的数据生命周期制度,清除无用的历史数据。
还没有评论,来说两句吧...