基础概念
缓慢变化维度(slowly changing dimension, SCD)就是数据仓库维度表中,那些随时间变化比较不明显,但仍然会发生变化的维度。
在从 OLTP 业务数据库向 DW 数据仓库抽取数据的过程中,在增量抽取的过程中,往往会遇到问题。维度表的数据发生了变化,那么这些变化是否要保留变化的记录。
SCD Type 分为五种
- SCD Type 0: Retain Original(维持原状)
- SCD Type 1: Overwrite(覆盖)
- SCD Type 2: Add New Row(添加新行)
- SCD Type 3: Add New Attribute(添加新属性列)
- SCD Type 4: Add Mini-Dimension(添加微维度)
SCD Type 0: Retain Original(维持原状)
一种特殊的SCD类型,即不管维度属性的实际值如何变化,数仓中维度的值都会维持第一次的值。它主要适用于那些本身含义就是“原始值”(original)的维度,比如在用户维度表中,用户注册时使用的原始用户名(original_user_name)。如果它发生变化,那么变化后的值是无效的,会被抛弃。
SCD Type 1: Overwrite(覆盖)
最简单的SCD类型,即一旦维度属性的实际值发生变化,就会直接覆写到数仓中。数仓中的维度属性总是且仅仅保存着最近一次变更的值(most recent assignment)。
只保留最新的状态,就无法看到变更的历史。
SCD Type 2: Add New Row(添加新行)
当然在数据仓库中更多是对相对静态的历史数据进行数据的汇总和分析,因此会尽可能的维护来自业务系统中的历史数据,能够真正捕获到这种历史数据的变化。
这种是最主要、最常用的SCD类型,在我们日常以Hive为基础的数仓建设过程中,体现为拉链表技术。
这种类型在维度表中添加两个辅助列:该行的有效日期(effective date)和过期日期(expiration date),分别指示该行从哪个时间点开始生效,以及在哪个时间点过后会变为无效。每当一个或多个维度发生更改时,就创建一个新的行,新行包含有修改后的维度值,而旧行包含有修改前的维度值,且旧行的过期日期也会同步修改。如下图:

这种类型的SCD处理方式能够非常有效且精确地保留历史与反映变更,但缺点是会造成数据的膨胀,因为即使只有一个维度变化,也要创建新行。
SCD Type 3: Add New Attribute(添加新属性列)
Type 2虽然非常好,但是当要在同一个时间维度内把新值和旧值关联起来时,就没有那么方便了。
当使用某个时间过滤数据的时候,很有可能会将数据过滤掉。为了解决这种问题,就有了type 3。修改的时候不添加新行,新增一列来记录变化的值。
这样其实也有新的问题出现,如果一个字段频繁变更,新增的字段就会越来越多。所以这种类型经常用来处理那种变化可预测的(predictable)、“牵一发而动全身”的少数SCD。
SCD Type 4: Add Mini-Dimension(添加微维度)
当维度的变化没有那么“缓慢”时,前面三种类型的处理就都显得力不从心了(特别是对于规模非常大的维度表,比如有百万甚至千万行)。这种维度一般就不再称为SCD,而称为“快速变化维度”(rapidly changing dimensions, RCD)。当RCD的规模比较小时,还能够采用Type 2或者Type 3来撑着,但规模很大时,就只能采用Type 4了。Type 4的方式是将那些快速变化的维度从原来的大维度表中拆分出来单独处理,是为微维度(mini-dimension)。

其中,微维度表的维度最好是少量、分段的(banded)离散值,例如:
