我们来详细讲解一下数据仓库中缓慢变化维(Slowly Changing Dimension, SCD) 的三种主要记录方式。这是数据仓库维度建模中一个非常核心的概念,用于处理维度属性随时间变化的情况。
为什么需要缓慢变化维?
在现实世界中,维度数据(如客户地址、产品名称、销售区域等)并不是一成不变的。例如:
- 一个客户换了居住地。
- 一个产品因升级而改变了名称。
- 一家分公司调整了所属的销售区域。
如果我们简单地用新值覆盖旧值(Type 1),就会丢失历史信息,导致无法准确地基于历史数据进行追溯和分析(例如,无法查询出“去年所有来自北京的客户”的销售情况,因为他们的地址可能现在都被更新成了上海)。
缓慢变化维的三种方式就是为了以不同的策略来应对这种变化,平衡“历史追溯”和“当前现实”的需求。
三种主要记录方式
Type 1:重写覆盖(Overwrite)
- 核心思想:不保留历史,直接用新数据覆盖旧数据。只反映最新的情况。
- 如何工作:当维度表的某条记录发生变化时,直接更新该记录中的字段。
- 示例:
- 客户
张三原本所在城市是北京。 - 他搬家到了
上海,系统更新了他的记录。 - 维度表中
张三的城市字段永远只显示上海,北京这个历史信息被永久丢失。
- 客户
- 优点:
- 实现最简单,易于理解和管理。
- 节省存储空间。
- 缺点:
- 无法追踪历史变化,破坏了历史数据的准确性。
- 适用场景:
- 修正错误的数据(如错别字)。
- 确实不需要历史信息的变化(例如,电话号码的变更,但业务上从不按电话区号分析)。
Type 2:增加新行(Add New Row)
-
核心思想:保留完整历史。为每一次变化创建一条新的维度记录,并通过额外的字段来标识其有效期。
-
如何工作:
- 当维度表的某条记录发生变化时,不更新原记录。
- 而是插入一条新的记录,其中包含新的属性值。
- 为了区分哪条记录在哪个时间段有效,通常会增加以下字段:
- 代理键(Surrogate Key):这是数据仓库中为维度表生成的一个无意义的、唯一的ID(通常是自增主键)。这是Type 2的核心。它与源系统的主键(自然键)分离。同一个客户(自然键相同)在不同时期会有多个不同的代理键。
生效日期(Start Date)/失效日期(End Date):标识该条记录有效的起止时间。当前有效的记录其失效日期可以是NULL或一个很大的日期(如9999-12-31)。是否当前标志(Is Current):一个标志位(如Y/N),快速标识哪条是当前最新记录。
-
示例:
代理键 (SK) 客户ID (NK) 客户姓名 城市 生效日期 失效日期 是否当前 101 1001 张三 北京 2020-01-01 2023-05-20 N 202 1001 张三 上海 2023-05-21 9999-12-31 Y - 当分析2023年第一季度的销售数据时,会关联到代理键
101的记录,显示张三在北京。 - 当分析2023年第四季度的销售数据时,会关联到代理键
202的记录,显示张三在上海。
- 当分析2023年第一季度的销售数据时,会关联到代理键
-
优点:
- 能够完整、精确地追踪所有历史变化。
- 是最常用和最经典的SCD处理方式。
-
缺点:
- 维度表会随着变化而不断增长,占用更多存储空间。
- ETL(抽取、转换、加载)逻辑比Type 1复杂得多。
-
适用场景:
- 绝大多数需要保留历史以便准确分析的情况(如客户地址、产品分类、员工部门调动等)。
Type 3:增加新列(Add New Column)
-
核心思想:有限度地保留历史。不增加新行,而是在原有记录上增加新的列来保存上一次或上几次的变化值。
-
如何工作:
- 在维度表中,为需要跟踪变化的属性预先创建多个列,例如
原始值列、previous值列、current值列。 - 当变化发生时,将旧值移动到
previous列,将新值放入current列。
- 在维度表中,为需要跟踪变化的属性预先创建多个列,例如
-
示例:
假设我们只关心客户的“当前城市”和“上一个城市”。客户ID 客户姓名 当前城市 上一个城市 1001 张三 上海 北京 - 张三从北京搬到上海后,
上一个城市被更新为北京,当前城市被更新为上海。 - 如果张三再次搬家到广州,那么
上一个城市会变成上海,当前城市会变成广州。北京这个历史信息就会被覆盖丢失。
- 张三从北京搬到上海后,
-
优点:
- 不需要增加新行,易于查询当前和上一次的状态(性能较好)。
-
缺点:
- 只能保留有限的历史(通常只能保留上一次变化)。无法应对多次变化。
- 需要预先设计好要保留哪些历史字段,缺乏灵活性。
-
适用场景:
- 变化次数很少,且业务上只关心最近一次或两次变化的情况。在实际应用中比较少见。
总结与对比
| 类型 | 别名 | 策略 | 历史保留 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|---|---|
| Type 1 | 重写 | 覆盖旧值 | 不保留 | 简单、节省空间 | 丢失历史 | 错误修正、无关历史的变化 |
| Type 2 | 新增行 | 增加新记录+代理键 | 完整保留 | 历史追溯精准 | 表体积大、ETL复杂 | 最常用,如地址、分类变化 |
| Type 3 | 新增列 | 增加新列存旧值 | 部分保留(通常只保留上一次) | 查询性能好 | 灵活性差、无法应对多次变化 | 较少用,如记录上级、前一个状态 |
在实际的数据仓库项目中,Type 2 是应用最广泛的方式,因为它提供了最强大的历史分析能力。一个成熟的维度表设计往往是混合模式,即对不同的字段采用不同的SCD类型处理。例如,客户的“生日”字段发生变更(可能是之前录错了)可以用Type 1覆盖,而“地址”字段变更则用Type 2记录全历史。
541

被折叠的 条评论
为什么被折叠?



