X-Blog

缓慢变化维相关概念

Peijun 于 2022-03-22 发布

在数据同步任务开发过程中,有一个问题经常会被问到:全量OR增量?处了部分业务场景特殊要求外,一般还是按照上游数据更新方式来进行同步。在数据更新过程中,有一个比较重要的概念:缓慢变化维(Slowly Changing Dimension)

SCD问题简单介绍

在数据仓库的数据模型设计过程中,经常会遇到下面这种表的设计:

有一些表的数据量很大,比如一张合同表,大约5000万条记录,289个字段。表中的部分字段会被update更新操作,如客户基本信息,产品的描述信息,合同的状态等等。需要查看某一个时间点或者时间段的历史快照信息,比如,查看某一个合同在历史某一个时间点的状态。表中的记录变化的比例和频率不是很大,比如,总共有10亿的用户,每天新增和发生变化的有200万左右,变化的比例占的很小。

维度缓慢变化维SCD(Slowly Changing Dimensions)一些维度表的数据不是静态的,而是会随着时间而缓慢地变化(这里的缓慢是相对事实表而言,事实表数据变化的速度比维度表快)把处理维度表数据历史变化的问题,称为缓慢变化维问题,简称SCD问题。

例如:根据合同类型的维度,统计不同的合同类型在某一时间段的发货占比。而期间,用户可能去修改某一个合同的合同类型,例如:将测试合同改为客户需求合同。此时,合同维度表就发生了变化。当然这个变化相对事实表的变换要慢。但这个维度表的变化,就是缓慢变化维。

那么对于这种表该如何设计呢?下面有几种方案可选:

SCD问题的几种解决方案:

重写维度值

修改维度属性为最新值,直接覆盖,不保留历史信息。

比如合同属于哪个类别:当合同类别发生变化时,直接重写为新类别,如果业务只关心最新的类别。

插入新的维度行

在维度表中增加新的一行,新行中采用新的属性值。此种方式需要借助代理键,需要为新行分配新的代理键,将其作为事实表的外键。

采用此方式,一般会在维度行中额外增加3列:行生效时间,行失效时间以及当前行标识(或者不使用当前行标识,由行失效时间来判断是否是当前行)

此方式及其变种是处理缓慢变化维的主要技术。

维度属性值变化前:

合同号 合同类型 行生效时间 行失效时间 SCD_ACTIVE_IND
001A 测试合同 2020-01-01 9999-12-31 1

维度属性值变化后:

合同号 合同类型 行生效时间 行失效时间 SCD_ACTIVE_IND
001A 测试合同 2020-01-01 2020-01-31 0
001A 技术服务合同 2020-02-01 9999-12-31 1

添加维度列

在维度表中增加新的一列,原先属性列存放上一版本的属性值,当前属性列存放当前版本的属性值。

维度属性值变化前:

合同号 合同类型 其他属性
001A 测试合同 XXX

维度属性值变化后:

合同号 当前合同类型 原合同类型 其他属性
001A 技术服务合同 测试合同 XXX

快照维度

此种方式比较暴力,每天保留全量维度属性的快照数据。

此方式依托的是当前存储成本远低于计算成本,以空间换时间的理念。

跑数日期 合同号 合同类型 其他属性
20200101 001A 测试合同 XXX
20200101 002A 客户需求 XXX
20200102 001A 技术服务合同 XXX
20200102 002A 客户需求 XXX
20200103 001A 技术服务合同 XXX
20200103 002A 客户需求 XXX