Hudi实现拉链表实战
1 基于Hudi表实现拉链表的方案
- 由于Hudi表存储为了保证数据唯一性要求有主键,拉链表会对某一个对象的历史状态都存储所以主键设计为联合主键,将对象ID和生效时间作为联合主键。
- Hudi新增了数据的更新能力,因此相对于传统的大数据平台,可以基于update的能力优化传统hive的拉链表的实现方案。
- 增量数据一般不携带历史数据的生效时间
2 拉链表实现算法
- 当前最新的拉链表为Now_table(UserID:用户ID,BundleID为套餐ID;Start_date为生效时间;End_date为失效效时间)
- 新增数据Tmp_table,(由于大数据平台的数据基于上游采集而来,基于时间戳的增量数据相对容易获取到)
- 新增数据Tmp_table与Now_table关联,将以存在数据更新写入Now_table,end_date为当前时间
- 将新增数据全部写入Now_table,end_date为'9999-12-31'
3 实现举例
- 创建Now_table,并初始化数据
Create table Now_table(
userid string,
bundleid string,
start_date string,
end_date string,
ts timestamp
)using hudi
OPTIONS(
type = 'mor',
`payloadClass` 'org.apache.hudi.common.model.DefaultHoodieRecordPayload',
primaryKey = 'userid,start_date',
preCombineField = 'ts'
);
insert into Now_table(userid,bundleid,start_date,end_date) values('U0001','A01','2020-05-31','2021-05-31',now());
insert into Now_table(userid,bundleid,start_date,end_date) values('U0001','A01','2021-05-31','9999-12-31',now());
insert into Now_table(userid,bundleid,start_date,end_date) values('U0002','A01','2020-05-31','2021-05-31',now());
insert into Now_table(userid,bundleid,start_date,end_date) values('U0002','A02','2021-05-31','9999-12-31',now());
- 新增数据临时表Tmp_table,新增数据到Tmp_table
Create table Tmp_table(
userid string,
bundleid string,
start_date string
)using hudi
OPTIONS(
type = 'mor',
primaryKey = 'userid',
preCombineField = 'start_date'
);
insert into Tmp_table(userid,bundleid,start_date) values('U0001','A03','2022-05-31');
insert into Tmp_table(userid,bundleid,start_date) values('U0002','A03','2022-05-31');
insert into Tmp_table(userid,bundleid,start_date) values('U0003','A03','2022-05-31');
Tmp_table数据内容如下:
- 将Now_table数据闭链
insert into Now_table
select
t1.userid,
t1.bundleid,
t1.start_date,
t2.start_date,
now()
from Now_table t1,Tmp_table t2
where t1.userid= t2.userid and t1.end_date='9999-12-31';
Now_table数据变更如下:
- 将增量数据开链写入Now_table
insert into Now_table
select
userid,
bundleid,
start_date,
'9999-12-31',
now()
from Tmp_table
Now_table数据更新如下:
- 通过userid可以查询到历史的状态变化。
select userid,bundleid,start_date,end_date from Now_table where userid='U0001';
4 算法总结
- Hudi表具有数据更新能力,不需要对全表数据进行insert overwrite操作,算法更简单
- Hudi表提供Upsert的能力,当相同主键的数据存在,新数据会自动更新老数据,因此不用对老数据进行update操作,直接Insert即可(Sparksql的Insert操作默认为upsert操作。)
- 对于缓慢变化维的操作会更加简化,设置合理的主键,基于Merge语法直接操作,会更加简单。
欢迎关注微信公众号:大数据AI
评论