缓慢变化维解决方案
Slowly Changing Dimensions (SCD) are dimensions that have data that slowly changes.
缓慢变化维:数据会发生缓慢变化的维度就叫”缓慢变化维”。
举个例子就清楚了:
在一个零售业数据仓库中,事实表保存着各销售人员的销售记录,某天一个销售人员从北京分公司调到上海分公司了,那么如何来保存这个变化呢?也就是说销售人员维度要怎么恰当的处理这一变化。先来回答一个问题,为什么要处理,或保存这一变化?如果我们要统计北京地区或上海地区的总销售情况的时候,这个销售人员的销售记录应该算在北京还是算在上海?当然是调离前的算在北京,调离后的算在上海,但是如标记这个销售人员所属区域?这里就需要处理一下这个维度的数据,即我们缓慢变化维需要做的事情。
处理缓慢变化维一般按不同情况有以下几种解决方案:
一. 新数据覆盖旧数据
此方法必须有前提条件,即你不关心这个数剧的变化。例如,某个销售人员的英文名改了,如果你不关心员工的英文名有什么变化则可直接覆盖数据仓库中的数据。
二. 保存多条记录,并添加字段加以区分
这种情况下直接新添一条记录,同时保留原有记录,并用单独的专用的字段保存区别。如:
(以下表格中Supplier_State表示上面例子中所属区域,为描述清晰,不用代理键表示)
添加是否可用来标识新旧数据:
Supplier_key |
Supplier_Code |
Supplier_Name |
Supplier_State |
Disable |
001 |
ABC |
Phlogistical Supply Company |
CA |
Y |
002 |
ABC |
Phlogistical Supply Company |
IL |
N |
添加数据版本信息标记新旧数据:
Supplier_key |
Supplier_Code |
Supplier_Name |
Supplier_State |
Version |
001 |
ABC |
Phlogistical Supply Company |
CA |
0 |
002 |
ABC |
Phlogistical Supply Company |
IL |
1 |
添加记录的生效日期和失效日期来标识新旧数据
Supplier_key |
Supplier_Code |
Supplier_Name |
Supplier_State |
Start_Date |
End_Date |
001 |
ABC |
Phlogistical Supply Company |
CA |
01-Jan-2000 |
21-Dec-2004 |
002 |
ABC |
Phlogistical Supply Company |
IL |
22-Dec-2004 |
|
空的End_Date表示当前版本数据,或者你也可以用一个默认的大时间 (如: 12/31/9999)来代替空值, 这样数据还能被索引识别到.
混合模式:
这种模式是以上几种模式的混合体,相对而言此种方法更全面,更能应对错综复杂且易变化的用户需求,也是较为常用的。
Row_Key |
Supplier_key |
Supplier_Code |
Supplier_Name |
Supplier_State |
Start_Date |
End_Date |
Current Indicator |
1 |
001 |
ABC001 |
Phlogistical Supply Company |
CA |
22-Dec-2004 |
15-Jan-2007 |
N |
2 |
001 |
ABC001 |
Phlogistical Supply Company |
IL |
15-Jan-2007 |
1-Jan-2099 |
Y |
此种方法有以下几条优点:
- 能用简单的过滤条件选出维度当前的值。
- 能较容易的关联出历史任意一时刻事实数据的值。
- 如果事实表中有一些时间字段(如:Order Date, Shipping Date, Confirmation Date),那么我们很容易选择哪一条维度数据进行关联分析。
其中Row_Key和 Current Indicator字段是可有可无的,加上去更方便,毕竟维度表的数据都不大,多点冗余字段不占太大空间但能提高查询效率。
这种设计模式下事实表应以Supplier_key为外键,虽然这个字段不能唯一标识一条维度数据,从而形成了事实表与维表多对多的关系,因此在做事实和维度做关联时应加上时间戳字段(或Indicator字段)。
三. 不同字段保存不同值
这种方法用不同的字段保存变化痕迹,但是不能象第二种方法一样保存所有变化记录,它只能保存两次变化记录.适用于变化不超过两次的维度。
Supplier_key |
Supplier_Name |
Original_Supplier_State |
Effective_Date |
Current_Supplier_State |
001 |
Phlogistical Supply Company |
CA |
22-Dec-2004 |
IL |
四. 另外建表保存历史记录
即另外建一个历史表来表存变化的历史记录,而维度只保存当前数据。
Supplier:
Supplier_key |
Supplier_Name |
Supplier_State |
001 |
Phlogistical Supply Company |
IL |
Supplier_History:
Supplier_key |
Supplier_Name |
Supplier_State |
Create_Date |
001 |
Phlogistical Supply Company |
CA |
22-Dec-2004 |
这种方法仅仅记录一下变化历史痕迹,其实做起统计运算来还是不方便的。
五.保证事实表和维表的参照完整性
维度表如果保存多条记录,事实表需要做相应处理,来保证参照完整性
方案一:复合主键参照维度表
Supplier Dimension:
Version_Number |
Supplier_key |
Supplier_Code |
Supplier_Name |
Supplier_State |
Start_Date |
End_Date |
1 |
001 |
ABC001 |
Phlogistical Supply Company |
CA |
22-Dec-2004 |
15-Jan-2007 |
0 |
001 |
ABC001 |
Phlogistical Supply Company |
IL |
15-Jan-2007 |
1-Jan-2099 |
Fact Delivery: (为描述清晰,同样不使用代理键标识维度)
Delivery_Key |
Supplier_key |
Supplier_version_number |
Quantity |
Product |
Delivery_Date |
Order_Date |
1 |
001 |
0 |
132 |
Bags |
22-Dec-2006 |
15-Oct-2006 |
2 |
001 |
0 |
324 |
Chairs |
15-Jan-2007 |
1-Jan-2007 |
Version_Number和Supplier_key可作为复合主键在两实体间建立链接,可解决事实表和维表多对多关系问题
方案二:在事实表参照维度表的代理键,解决参照完整性
Supplier Dimension:
Surrogate_key |
Version_Number |
Supplier_key |
Supplier_Code |
Supplier_Name |
Supplier_State |
Start_Date |
End_Date |
1 |
1 |
001 |
ABC001 |
Phlogistical Supply Company |
CA |
22-Dec-2004 |
15-Jan-2007 |
2 |
0 |
001 |
ABC001 |
Phlogistical Supply Company |
IL |
15-Jan-2007 |
1-Jan-2099 |
Fact Delivery:
Delivery_Key |
Supplier _Surrogate_key |
Quantity |
Product |
Delivery_Date |
Order_Date |
1 |
1 |
132 |
Bags |
22-Dec-2006 |
15-Oct-2006 |
2 |
1 |
324 |
Chairs |
15-Jan-2007 |
1-Jan-2007 |