数据建模-缓慢变化的维度类型2:如何处理架构更改(添加列)



在构建慢速变化维度表时,处理模式更改的最佳实践是什么?

例如,添加了一列:

First state:
+----------+---------------------+-------------------+
|customerId|address              |updated_at         |
+----------+---------------------+-------------------+
|1         |current address for 1|2018-02-01 00:00:00|
+----------+---------------------+-------------------+

New state with new column, but every other followed column constant:
+----------+---------------------+-------------------+------+
|customerId|address              |updated_at         |newCol|
+----------+---------------------+-------------------+------+
|1         |current address for 1|2018-03-03 00:00:00|1000  |
+----------+---------------------+-------------------+------+

我的第一种方法是认为模式更改意味着行已经更改。所以我会在SCD表中添加一个新行:

+----------+---------------------+-------------------+------+-------------+-------------------+-------------------+
|customerId|address              |updated_at         |newCol|active_status|active_status_start|active_status_end  |
+----------+---------------------+-------------------+------+-------------+-------------------+-------------------+
|1         |current address for 1|2018-02-01 00:00:00|null  |false        |2018-02-01 00:00:00|2018-03-03 00:00:00|
|1         |current address for 1|2018-03-03 00:00:00|1000  |true         |2018-03-03 00:00:00|null               |
+----------+---------------------+-------------------+------+-------------+-------------------+-------------------+

但是,如果添加了列,但对于某个特定的行,值为null,该怎么办?例如,对于customerId为2的行,它为空:

+----------+---------------------+-------------------+------+
|customerId|address              |updated_at         |newCol|
+----------+---------------------+-------------------+------+
|2         |current address for 2|2018-03-03 00:00:00|null  |
+----------+---------------------+-------------------+------+

在这种情况下,我可以采取两种方法:

  1. 将每一次架构更改都视为行更改,即使是空行(更容易实现,但从存储角度来看成本更高(。这将导致:
+----------+---------------------+-------------------+-------------+-------------------+-------------------+------+
|customerId|address              |updated_at         |active_status|active_status_end  |active_status_start|newCol|
+----------+---------------------+-------------------+-------------+-------------------+-------------------+------+
|1         |current address for 1|2018-02-01 00:00:00|false        |2018-03-03 00:00:00|2018-02-01 00:00:00|null  |
|1         |current address for 1|2018-03-03 00:00:00|true         |null               |2018-03-03 00:00:00|1000  |
|2         |current address for 2|2018-02-01 00:00:00|false        |2018-03-03 00:00:00|2018-02-01 00:00:00|null  |
|2         |current address for 2|2018-03-03 00:00:00|true         |null               |2018-03-03 00:00:00|null  |
+----------+---------------------+-------------------+-------------+-------------------+-------------------+------+
  1. 检查每一行,如果它有这个新列的实际值,则添加它;否则,不要对此行执行任何操作(目前,我还没有想到它的实现,但它要复杂得多,而且很容易出错(。SCD表中第2行的结果将是"行未更改":
+----------+---------------------+-------------------+-------------+-------------------+-------------------+------+
|customerId|address              |updated_at         |active_status|active_status_end  |active_status_start|newCol|
+----------+---------------------+-------------------+-------------+-------------------+-------------------+------+
|1         |current address for 1|2018-02-01 00:00:00|false        |2018-03-03 00:00:00|2018-02-01 00:00:00|null  |
|1         |current address for 1|2018-03-03 00:00:00|true         |null               |2018-03-03 00:00:00|1000  |
|2         |current address for 2|2018-02-01 00:00:00|true         |null               |2018-02-01 00:00:00|null  |
+----------+---------------------+-------------------+-------------+-------------------+-------------------+------+

第二种方法似乎更";"正确";,但我说得对吗?此外,实施方法1要简单得多。大约2需要一些更复杂的东西,并有其他权衡,例如:a( 如果不是添加列,而是删除了columnd,该怎么办?b( 从查询的角度来看,它的成本要高得多。

我已经对这个问题进行了研究,但没有发现这种情况正在得到治疗。

标准方法是什么?权衡?这里还有我遗漏的另一种方法吗?

谢谢大家。

感谢@MarmiteBomber和@MatBailie的评论。根据你的评论,我最终实施了第二个选项,因为(你的想法摘要(:

  1. 第二种方法是唯一有意义的方法
  2. 实现是业务逻辑的结果,而不一定是标准做法。在我们的例子中,我们不需要区分null的类型,所以正确的方法是将已知的不存在的值封装为null,以及未知的值,等等
  3. 要明确

第二种方法还需要在写入时添加检查(行中是否存在新列?(,但它节省了查询时间和存储的复杂性。由于SCD是";"慢";这种情况很少见(模式更改会发生,但不是"每天都发生"(,添加签入写入时间比添加查询时间要好。

最新更新