赞
踩
作为一个刚入职场的新人,之前一直听说拉链表这个名词,一直以为是一个很高端的东西,今天闲来无事,自己学习理解了下,毕竟对自己不知道的东西应该抱有一点点好奇,哈哈~
首先拉链表就是在数据仓库中一种存储表数据的方式,就是记录某个事物从开始一直到最后状态的变化过程。最好理解的就是银行系统中核心系统,它肯定有一张表记录所有客户的交易流水,这个表中有客户编号,核心账号,账户余额,交易日期,交易对手等等字段。每天只要发生流水,都会有记录。但是现在存在两个问题,第一,在他所有客户中,只有一部分当天发生交易。第二,在发生交易的这 一批客户中,该表中只有一部分数据发生改变,大部分数据是不变的。对于这种表,我们有三种方法可以保留数据。第一,每天保留最新的一份全量数据,然后删掉之前的数据。这样实现起来简单,节省内存,但是我们看不到历史 数据。第二,每天保留当前最新的全量数据,这样我们可以看到所有历史数据,但其实这样其实把一些不变的数据保存了很多遍,对内存是 一种很大的浪费。第三就是使用拉链表,它虽然在内存上没有第一种方法那么优秀,但是相比于第二种方法也节省了很多,同时保留了历史数据。
拉链表原理:
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_dt | ent_dt |
A | 10000 | 20180101 | 99991231 |
B | 40000 | 20180101 | 99991231 |
C | 30000 | 20180101 | 99991231 |
ND(NewDay)表:
用户 | 账户余额 | stat_dt | end_dt |
A | 10000 | 20180102 | 99991231 |
B | 50000 | 20180102 | 99991231 |
C | 26000 | 20180102 | 99991231 |
D | 200 | 20180102 | 99991231 |
W_I=ND-OD(这些是新增数据,需要插入历史表 ,然后 把stat_dt改为当前日期,end_dt改为 最大值)
用户 | 账户余额 | stat_dt | end_dt |
B | 50000 | 20180102 | 99991231 |
C | 26000 | 20180102 | 99991231 |
D | 200 | 20180102 | 99991231 |
W_U=OD-ND(这些是从20180101到20180102需要封存的数据,在历史表修改,把end_dt改为 当前日期)
用户 | 账户余额 | stat_dt | end_dt |
B | 40000 | 20180101 | 99991231 |
C | 30000 | 20180101 | 99991231 |
提示:重要的两步
insert操作把W_I插入历史表
用户 | 账户余额 | stat_dt | end_dt |
A | 10000 | 20180101 | 99991231 |
B | 40000 | 20180101 | 99991231 |
C | 30000 | 20180101 | 99991231 |
B | 50000 | 20180102 | 99991231 --NEW |
C | 26000 | 20180102 | 99991231 --NEW |
D | 200 | 20180102 | 99991231 --NEW |
update操作在历史表修改W_U
用户 | 账户余额 | stat_dt | end_dt |
A | 10000 | 20180101 | 99991231 |
B | 40000 | 20180101 | 20180102 --UPDATE |
C | 30000 | 20180101 | 20180102 --UPDATE |
B | 50000 | 20180102 | 99991231 |
C | 26000 | 20180102 | 99991231 |
D | 200 | 20180102 | 99991231 |
最后就成了这样,其实总的来说,就是有一个全量的历史表,我们拿到今天 数据和昨天的 对比,拿到发生改变字段的增量数据,在历史表中逐条插入这一部分增量数据(上面的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这部分)。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。