拉链表学习

    作为一个刚入职场的新人,之前一直听说拉链表这个名词,一直以为是一个很高端的东西,今天闲来无事,自己学习理解了下,毕竟对自己不知道的东西应该抱有一点点好奇,哈哈~

    首先拉链表就是在数据仓库中一种存储表数据的方式,就是记录某个事物从开始一直到最后状态的变化过程。最好理解的就是银行系统中核心系统,它肯定有一张表记录所有客户的交易流水,这个表中有客户编号,核心账号,账户余额,交易日期,交易对手等等字段。每天只要发生流水,都会有记录。但是现在存在两个问题,第一,在他所有客户中,只有一部分当天发生交易。第二,在发生交易的这 一批客户中,该表中只有一部分数据发生改变,大部分数据是不变的。对于这种表,我们有三种方法可以保留数据。第一,每天保留最新的一份全量数据,然后删掉之前的数据。这样实现起来简单,节省内存,但是我们看不到历史 数据。第二,每天保留当前最新的全量数据,这样我们可以看到所有历史数据,但其实这样其实把一些不变的数据保存了很多遍,对内存是 一种很大的浪费。第三就是使用拉链表,它虽然在内存上没有第一种方法那么优秀,但是相比于第二种方法也节省了很多,同时保留了历史数据。

    拉链表原理:

   1.采集当日全量数据到ND(NewDay)表;
   2.可从历史表中取出昨日全量数据存储到OD(OldDay)表;
   3.(ND-OD)就是当日新增和变化的数据,也就是当天的增量,用W_I表示;
   4.(OD-ND)为状态到此结束需要封链的数据,用W_U表示;
   5.将W_I表的内容全部插入到历史表中,这些是新增记录,start_date为当天,而end_date为max值;

   6.对历史表进行W_U部份的更新操作,start_date保持不变,而end_date改为当天

   其中,5,6步不太好理解,当时我自己绕了很久。其实想一下,它就是在历史表中,能看到每个时间段发生变化的过程。比如一张用户表,第一天20180101有A,B,C三个 用户,账户余额分别是10000,40000,30000。第二天20180102,这个表有四个用户A,B,C,D,金额分别是10000,50000,26000,200。其实和第一天相比,D用户是新增的,B和C的值发生了改变,A没有任何变化。那么,对应到上面如下:

OD(OldDay)表:

用户账户余额stat_dtent_dt
A100002018010199991231
B400002018010199991231
C300002018010199991231

ND(NewDay)表:

用户 账户余额stat_dtend_dt
A100002018010299991231
B500002018010299991231
C260002018010299991231
D2002018010299991231

W_I=ND-OD(这些是新增数据,需要插入历史表 ,然后 把stat_dt改为当前日期,end_dt改为 最大值)

用户账户余额stat_dtend_dt
B500002018010299991231
C260002018010299991231
D2002018010299991231

W_U=OD-ND(这些是从20180101到20180102需要封存的数据,在历史表修改,把end_dt改为 当前日期)

用户账户余额stat_dtend_dt
B400002018010199991231
C300002018010199991231

提示:重要的两步

insert操作把W_I插入历史表

用户账户余额stat_dtend_dt
A100002018010199991231
B400002018010199991231
C300002018010199991231
B500002018010299991231   --NEW
C260002018010299991231   --NEW
D2002018010299991231   --NEW

update操作在历史表修改W_U

用户账户余额stat_dtend_dt
A100002018010199991231
B400002018010120180102   --UPDATE
C300002018010120180102   --UPDATE
B500002018010299991231
C260002018010299991231
D2002018010299991231

    最后就成了这样,其实总的来说,就是有一个全量的历史表,我们拿到今天 数据和昨天的 对比,拿到发生改变字段的增量数据,在历史表中逐条插入这一部分增量数据(上面的B,C,D),stat_dt为当前,end_dt为最大值。然后再在历史表中,修改这部分增量数据对应的昨天的记录(上面的B,C),保持stat_dt不变,把end_dt改为当前。这样,我们就能清楚的看到每个对象从产生到最后的 变化状态。

    end_dt为有效的数据,如果查当前所有有效的数据:select * from user  where end_dt=‘99991231’。(作为初学者,我当时不知道为啥end_dt为‘99991231’为有效的状态。其实想一下,end_dt为‘99991231’就是说它从产生到现在一直没有改变过,或者说某次改变后再 没有变化过,所以是当前有效 的状态)。如果需要查看20180102这一天的数据,则select * from user where  stat_dt<='20180102' and end_dt>='20180102’(作为初学者,我当时一直在想,要查20180102的数据,让stat_dt为啥有stat_dt<20180102和ent_dt>20180102这部分,后来想一下,因为比如20180101这天产生的一天记录,到20180102这天状态没有改变,那么这条数据在20180102是存在的,但是stat_dt是20180101,所以会有stat_dt<20180102。同时,如果一个数据在20180102这天后者这天之前改变的,那么这些数据在20180102这天存在,但是end_dt是99991231,所以会有end_dt>20181231这部分)。





### 拉链的特点 拉链是一种特殊的数据结构设计,主要用于解决历史数据查询和高效存储的问题。其核心特点是通过时间维度记录每一笔数据的有效期,从而能够在任意时刻快速计算出符合条件的结果[^3]。 #### 数据结构特点 1. **有效期标记** 每一条记录都包含两个时间字段:`生效时间` 和 `失效时间`。这两者共同定义了一条记录的时间范围,在此范围内该记录有效。 2. **增量更新** 当数据发生变化时,不会直接修改原记录,而是新增一条记录,并调整原有记录的失效时间。这种方式保留了完整的变更历史。 3. **紧凑存储** 相较于每天全量备份的方式拉链仅需存储变化的部分,因此能显著减少存储空间占用[^3]。 --- ### 拉链的优势 1. **高效的查询能力** 对于特定时间点或时间段内的数据分析需求,可以通过简单的条件过滤实现精准定位,无需复杂的计算逻辑[^3]。 2. **完整的历史记录** 拉链设计天然支持对历史版本的追踪,适合需要长期保存变更日志的应用场景。 3. **节省存储资源** 由于只存储实际发生过变化的数据,相比每日全量快照的方法,拉链大幅降低了存储成本。 4. **易于维护** 新增、修改和删除操作均遵循统一的模式——即创建新记录并调整旧记录的结束时间,简化了开发复杂度。 --- ### 应用场景 1. **金融行业** 银行交易流水、账户余额变动等业务中经常需要用到精确到秒级甚至毫秒级的历史回溯功能,这正是拉链擅长之处[^3]。 2. **人力资源管理** 员工入职离职情况统计是一个典型例子。例如要统计某个日期的在职员工数量,只需筛选满足条件的区间即可完成计算。 3. **电商领域** 商品价格波动跟踪、库存状态变迁分析都可以借助拉链来实现高性能检索与展示效果优化。 4. **实时数仓建设** 结合工具如 Canal ,可以将数据库中的动态更新转化为静态化的拉链形式入库,便于后续离线报生成或者机器学习模型训练使用[^2]。 ```sql -- 创建一张典型的拉链示例 CREATE TABLE employee_history ( emp_id INT, name VARCHAR(50), department VARCHAR(50), start_date DATE, -- 生效时间 end_date DATE -- 失效时间,默认为9999-12-31示当前最新记录 ); ``` ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值