拉链表(SlowlyChangingDimensions)

一、前言

这几天刷抖音,看到了个新的玩意儿。拉链表,所以打算学习一下。

二、什么是拉链表及其实现

  1. 一个带历史数据的信息表。
  2. 表里要有两个字段,startTime、endTime、status(可选)。
  3. startTime:记录数据的生成时间,这里完全可以在数据库设置上默认值,插值时间就是startTime。
  4. endTime:记录数据的失效时间,默认应该是一个无限大的时间,例如9999-12-31。当数据失效,作为历史记录时,应该改为当前时间。
  5. status:记录该行数据是否为历史数据,但是我觉得这个字段可有可无,用endTime的9999-12-31值作为判断也可以。

三、应用场景

  1. 用户信息变更:城市、等级、手机号
  2. 商品价格变更:不同时期价格
  3. 员工组织关系变更:部门、岗位
  4. 风控/审计:需要追踪某时点数据
  5. 数仓维度表(SCD2):最常见

大多数情况下,这个思想应用在数仓和数据分析的场景,一般业务的情况下使用较少。

1
2
3
4
5
6
7
8
9
10
11
-- 查询当前生效数据
select * from A where endTime = '9999-12-31'

-- 查询历史数据
select * from A where startTime >= '#{开始时间}' and endTime <= '#{结束时间}'

-- 修改操作
-- 先关闭数据
UPDATE A SET endTime = '2026-6-6' WHERE user_id = 1001 AND endTime = '9999-12-31';
-- 插入新数据
INSERT INTO A (……) VALUES ( ……, DATE '2024-03-01', DATE '9999-12-31');

四、扩展

Slowly Changing Dimensions即缓慢变化维(SCD)

维度表中的属性会随着时间慢慢变化,但这种变化不是高频实时的,需要考虑是否保留历史。

SCD解决了当维度属性变化时,如何管理旧值、新值和历史版本。

SCD的三种类型:

  • Type 1:直接覆盖,新值直接覆盖旧值,不保留历史。
  • Type 2:新增版本,不覆盖旧记录,而是保留旧版本,再插入一条新版本。【拉链表属于这个类型】
  • Type 3:保留有限历史,保留当前值和上一个值,但不保留完整历史。

缓慢变化维,就是“维度数据会变,而我们要设计一种方式处理这种变化”。

拉链表不用代理键,最大的问题不是“不能做”,而是“很难做对、很难长期稳定地做对”。