赞
踩
简单点说:记录一个事物,从开始一直到当前状态的所有变化信息。
复杂点说:记录数据在某一时间内的状态,以及数据在某一时间点的变化的数据存储方式。
针对一些数据量大的表,像是保存了几年的数据,但是新增或者需要操作查看的数据只有一部分,或者只需要某个时间节点的数据,这个时候就可以使用拉链表进行操作。
drop table emp1;--如果以前有 alter table emp1 add up_date date; --添加了一个新增数据的时间节点字段 insert into emp1 e1( e1.empno, e1.ename, e1.job, e1.mgr, e1.hiredate, e1.sal, e1.comm, e1.deptno, e1.up_date ) select et.empno, et.ename, et.job, et.mgr, et.hiredate, et.sal, et.comm, et.deptno, sysdate-5 from emp et; select * from emp1
---目标表 drop table linkTable; create table linkTable as select * from emp where 1=2; select * from linkTable; alter table linkTable add up_date date; alter table linkTable add start_date date;--开始时间 alter table linkTable add end_date date;--结束时间 insert into linkTable lt( lt.empno, lt.ename, lt.job, lt.mgr, lt.hiredate, lt.sal, lt.comm, lt.deptno, lt.up_date, lt.start_date, lt.end_date ) select et.empno, et.ename, et.job, et.mgr, et.hiredate, et.sal, et.comm, et.deptno, et.up_date, to_date('2024-4-26','YYYY-MM-DD'), to_date('9999-9-9','YYYY-DD-MM') from emp1 et;
update emp1 set sal=sal+1000,up_date=sysdate where ename='SMITH';
insert into emp1 values(9999,'张三','xingjiapo',7369,
date'1998-06-01',3600,1000,10,sysdate-1);
select * from emp1;
---创建存储过程 create or replace procedure updateLinkTable(startTime varchar2,endTime varchar2) is v_start date := to_date(startTime,'YYYY-MM-DD HH24:MI:SS'); v_end date := to_date(endTime,'YYYY-MM-DD HH24:MI:SS'); cursor update_cursor is --创建游标保存指定时间内需要比对的数据 select * from emp1 where up_date>=v_start and up_date<=v_end; ---指定时间内的数据 v_count number; begin for i in update_cursor loop --目标表与源表比对, select count(1) into v_count from linkTable lk --找到当前的数据并且当前数据未过期 where i.empno = lk.empno and lk.end_date=to_date('9999-9-9','YYYY-MM-DD'); if v_count=1 then update linkTable lk set lk.end_date=trunc(sysdate-1) --把原先的数据更新为过期数据(历史数据) 也就是闭链 where i.empno = lk.empno and lk.end_date=to_date('9999-9-9','YYYY-MM-DD'); --添加当前已更新的业务变动数据,并更新end_date无穷大 insert into linkTable lk( lk.empno, lk.ename, lk.job, lk.mgr, lk.hiredate, lk.sal, lk.comm, lk.deptno, lk.up_date, lk.start_date, lk.end_date ) values( i.empno, i.ename, i.job, i.mgr, i.hiredate, i.sal, i.comm, i.deptno, i.up_date, trunc(sysdate), to_date('9999-9-9','YYYY-MM-DD') ); elsif v_count=0 then --没有匹配上说明当前数据是新增数据,直接插入进去即可 (更新end_date无穷大 开链) insert into linkTable lk( lk.empno, lk.ename, lk.job, lk.mgr, lk.hiredate, lk.sal, lk.comm, lk.deptno, lk.up_date, lk.start_date, lk.end_date ) values( i.empno, i.ename, i.job, i.mgr, i.hiredate, i.sal, i.comm, i.deptno, i.up_date, trunc(sysdate), to_date('9999-9-9','YYYY-MM-DD') ); end if; end loop; exception when others then dbms_output.put_line(sqlcode); dbms_output.put_line(sqlerrm); end; select * from linkTable; select * from emp1;
---方法一 pl/sql调用
begin
updateLinkTable('2024-5-28 00:00:00','2024-5-29 23:59:59');
end;
--方法二 SQL语句调用
call updateLinkTable(p_star => '2024-05-28 00:00:00',p_end => '2024-05-29 23:59:59');
-- 或者
call updateLinkTable('2024-05-28 00:00:00','2024-05-29 23:59:59');
优点
缺点
查询性能低怎么优化?
1、在一些查询引擎中,我们对生效开始时间和失效结束时间做索引,这样可以提高性能
2、保留部分历史数据,比如说我们一张表里面存放全量的拉链表数据,然后再对外保留一张只提供近三个月数据的拉链表。
拉链表和流水表有什么区别?
流水表存放的是一个用户的变更记录,比如一张流水表中,一天的数据中,会存放一个用户的多条修改记录,变更几次就存几条记录,通过cancel监听mysql获取变更变化数据。但是在拉链表中只有一条记录,取当天最后一个状态。
1、它的适用范围是缓慢变化维,就是数据会变化但是变化频率不高
2、它存在与DIM层,也就是公共维度层
3、而ods层的更新方法是增量更新
4、它的分区是是以结束生效时间进行划分
5、它必须存在一个开始时间和一个结束时间
术语:
生效开始时间(表示这条记录的生命周期的开始时间——周期快照时的状态)
失效开始时间(这条记录的生命周期结束时间)
end_dt=’9999-12-31’ 表示这条记录处于有效状态
流程
公共维度层的数据是以拉链表的形式进行存储的,拉链表是以生效结束时间作为分区键进行划分的。
在处理前一天的数据时,它从ods层获取到增量更新的那部分数据后,会和拉链表正在生效分区的数据,也就是9999-12-31的分区数据进行比对,如果新增的数据它是已经存在于生效分区的数据里面,那么会把正在生效分区里面的数据的生效结束生效时间置为前一天,然后新增一条一样的数据,但是生效开始时间置为前一天,生效结束时间置为9999-12-31。
如果是新增的数据,不存在与正在生效的分区里面,这条数据则会放置到生效的分区中,然后会把生效开始时间置为前一天,生效结束时间置为9999-12-31。
最后做好的分区集会以动态分区的方式,重新覆盖这个维度层拉链表。
置为前一天的那部分数据会重新生成一前一天生效结束时间的分区,然后所有生效结束时间为999-12-31的那部分数据会覆盖9999-12-31分区数据。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。