什么是SCD
SCD(Slowly Changing Dimensions),一般翻译成:缓慢变化维。
SCD的提出是因为,在现实世界中,维度的属性并不是静态的,它会随着时间的流逝发生缓慢的变化。
缓慢变化维度其实就是指,在维度表中那些会随着时间变化的字段,比如用户基本资料。
缓慢是一个相对的概念,与缓慢变化的维度相比,数据增长快速是事实表。
如何处理SCD问题
处理方法通常有3种,假设有如下的表数据:
id | name | city |
---|---|---|
1001 | tom | Shanghai |
现在tom被调到北京总部工作,所以需要对city进行更新。
直接覆盖原值
对其相应的需要重写的维度行中的旧值,以当前值替换。
id | name | city |
---|---|---|
1001 | tom | Beijing |
这样处理,易于实现,始终反映最近的情况,但是没有保留历史数据,无法分析历史变化信息。
增加维度行
当有维度属性发生变化时,生成一条新的维度记录,如下:
id | name | city |
---|---|---|
1001 | tom | Shanghai |
1001 | tom | Beijing |
但是这样,当与别的表通过id关联时,有两个1001的id数据,这样是有问题的,这时就需要代理键的支持(Surrogate Key,唯一标识数据仓库表记录的键)。
sk_id | id | name | city |
---|---|---|---|
0001 | 1001 | tom | Shanghai |
0002 | 1001 | tom | Beijing |
现在每条数据都唯一,但又有一个问题,现在不知道哪条是当前在用的数据,虽然可以通过代理键找最大的(主键往往是自增的,最大的通常是最新的数据),但某些情况下要查找历史数据就不好找了,所以在维度表中加入时间字段,用NULL来标识哪条是当前最新数据,有变化再进行更新。
sk_id | id | name | city | start_time | end_time |
---|---|---|---|---|---|
0001 | 1001 | tom | Shanghai | 2016/10/26 | 2018/01/21 |
0002 | 1001 | tom | Beijing | 2018/01/21 | NULL |
以上其实就是拉链表的典型实现,可以记录缓慢变化维度属性的变化,是一种非常有效的工具。
增加属性列
尽管第二种方式可以区分历史情况,但是无法保证能够将新属性值和过去的历史事实关联。
第三方式:增加属性列,比较适合需要根据先后顺序来得出某种结论的场景。
id | name | curr_city | old_city |
---|---|---|---|
1001 | tom | Beijing | Shanghai |
这种方式的优点是,可以同时分析当前及前一次变化的属性值;缺点是,只保留了最后一次变化信息。
这种方案,在一些场景中可以解决很多问题,但我们不能无限制地添加新的字段来记录历史的状态,因此在使用这种方案时,会有一些取舍。
总结:在实际建模中,我们可以结合使用三种方式,也可以对一个维度表中的不同属性使用不同的方式。这些都是需要根据实际情况来决定,但目的都是一样的,就是能够方便的支持分析历史变化情况。