greenplum--历史拉链表

历史拉链表

历史拉链表是一种数据模型,主要是针对数据仓库设计中表存储数据的方式而定义的。历史拉链表是记录一个事物从开始一直到当前状态的所有变化的信息。
拉链表可以避免按每一天存储所有记录造成的海量存储问题,同时也是处理缓慢变化数据的一种常见方式。

原理

在拉链表中,每一条数据都有一个生效日期(dw_beg_date)和失效日期(dw_end_date)。
以用户表为例,在2020年2月1日有新增的用户,此时需要将生效日期设置为2020年2月1日,失效日期设置为日期的最大值3000年12月31日。

用户手机号生效日期失效日期
10011321111111112020-02-013000-12-31
10021321111111122020-02-013000-12-31

若在第二天需要删除用户1001时,将该用户的失效日期修改为2020年2月2日。

用户手机号生效日期失效日期
10011321111111112020-02-012020-02-02
10021321111111122020-02-013000-12-31

若在第三天,修改用户1002的手机号,需要新增一条1002的记录,将原先的1002用户的失效日期修改为2020年2月3日,新增的1002记录,生效日期为2020年2月3日,失效日期为最大值3000年12月31日。

用户手机号生效日期失效日期
10011321111111112020-02-012020-02-02
10021321111111122020-02-012020-02-03
10021321111111132020-02-033000-12-31

若要查询用户的最新数据,只需要筛选出日期为3000年12月31日的数据;若要查看2020年2月2日的历史数据,则筛选生效时间<=2020-02-02并且失效时间>2020-02-02。

实现

相关表结构:

--事实表
create table public.member_fatdt0
(
	member_id varchar(64) --会员id
	,phoneno varchar(20) --电话号码
	,dw_beg_date date   --生效日期
	,dw_end_date date   --失效日期
	,dtype char(1)     --类型(历史数据、当前数据)
	,dw_status char(1)  --数据操作类型(I,D,U)
	,dw_ins_date date  --数据仓库插入日期
) with(appendonly=true,compresslevel=5)
distributed by (member_id)
partition by range(dw_end_date)
(
	partition p20200201 start(date'2020-02-01') inclusive,
	partition p20200202 start(date'2020-02-02') inclusive,
	partition p20200203 start(date'2020-02-03') inclusive,
	partition p30001231 start(date'3000-12-31') inclusive
	end (date'3001-01-01') exclusive
);
 --当天的数据库变更数据存储表
create table public.member_delta
(
	member_id varchar(64)  --会员号
	,phoneno varchar(20)  --电话号码
	,action char(1)  --类型(新增、删除、更新)
	,dw_ins_date date  --数据仓库插入日期
)with(appendonly=true,compresslevel=5)
distributed by(member_id)
;
--临时表,主要用于记录历史数据和当前数据的变更
create table public.member_tmp0
(
	member_id varchar(64)  --会员ID
	,phoneno varchar(20)   --电话号码
	,dw_beg_date date   --生效日期
	,dw_end_date date   --失效日期
	,dtype char(1)       --类型(历史数据H、当前数据C)
	,dw_status char(1)   --数据操作类型(I,D,U)
	,dw_ins_date date    --数据仓库插入日期
)with(appendonly=true,compresslevel=5)
distributed by(member_id)
partition by List(dtype)
(partition phis values('H'),
partition pcur values('C'),
default partition other
)
;

--临时表,用户交换分区
create table public.member_tmp1
(
	member_id varchar(64)
	,phoneno varchar(20)
	,dw_beg_date date 
	,dw_end_date date 
	,dtype char(1)
	,dw_status char(1)
	,dw_ins_date date
)with(appendonly=true,compresslevel=5)
distributed by(member_id);


2020年2月1日的数据(member_fatdt0):
在这里插入图片描述
2020年2月2日新增的数据(member_delta):
在这里插入图片描述

  1. 关联member_fatdt0和member_delta表中更新,删除的数据进行左连接,关联上说明数据发生过变化,需要将该数据的生效时间更新为当天,并插入到临时表中的历史数据分区中,关联不上就插入到临时表的当前数据分区
--全量数据为2月1日,在2月3日刷新2月2日增量数据
truncate table public.member_tmp0;
insert into  public.member_tmp0
(
member_id
,phoneno
,dw_beg_date
,dw_end_date
,dtype
,dw_status
,dw_ins_date
)
select 
  a.member_id
  ,a.phoneno
  ,a.dw_beg_date
  ,case when b.member_id is null then a.dw_end_date
  else date'20200202' end as dw_end_date
  ,case when b.member_id is null then 'C'
  else 'H' end as dtype
  ,case when b.member_id is null then a.dw_status
  else b.action end as dw_status
  ,date'20200203'
from public.member_fatdt0 a
left join public.member_delta b
on a.member_id=b.member_id
and b.action in ('D','U')
where a.dw_beg_date<=date'20200202'-1
and a.dw_end_date>date'20200202'-1

在这里插入图片描述
2. 将member_delta的新增,更新数据插入到临时表(member_tmp0)表的当前数据分区中


insert into  public.member_tmp0
(
member_id
,phoneno
,dw_beg_date
,dw_end_date
,dtype
,dw_status
,dw_ins_date
)
select 
  member_id
  ,phoneno
  ,date'20200202'
  ,date'30001231'
  ,'C'
  ,action
  ,date'20200203'
from public.member_delta
where action in ('I','U');

在这里插入图片描述
3. 将member_fatdt0表中的对应分区与member_tmp0表的历史数据分区交换

truncate table public.member_tmp1;
alter table public.member_tmp0 exchange partition for('H') with table public.member_tmp1;
alter table public.member_fatdt0 exchange partition for('2020-02-02') with table public.member_tmp1;

  1. 将member_fatdt0表中的对应分区与member_tmp0表的当前数据分区交换
alter table public.member_tmp0 exchange partition for('C') with table public.member_tmp1;
alter table public.member_fatdt0 exchange partition for('3000-12-31') with table public.member_tmp1;
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值