Hudi实现拉链表实战

共 3230字,需浏览 7分钟

 ·

2023-08-24 14:25

1 基于Hudi表实现拉链表的方案

  • 由于Hudi表存储为了保证数据唯一性要求有主键,拉链表会对某一个对象的历史状态都存储所以主键设计为联合主键,将对象ID和生效时间作为联合主键。
  • Hudi新增了数据的更新能力,因此相对于传统的大数据平台,可以基于update的能力优化传统hive的拉链表的实现方案。
  • 增量数据一般不携带历史数据的生效时间

2 拉链表实现算法

  1. 当前最新的拉链表为Now_table(UserID:用户ID,BundleID为套餐ID;Start_date为生效时间;End_date为失效效时间)
  2. 新增数据Tmp_table,(由于大数据平台的数据基于上游采集而来,基于时间戳的增量数据相对容易获取到)
  3. 新增数据Tmp_table与Now_table关联,将以存在数据更新写入Now_table,end_date为当前时间
  4. 将新增数据全部写入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());
800bc8dc595b88b8eb9b86ac77dc750a.webp
  • 新增数据临时表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数据内容如下:

bf181019d4e7a6c3098a3a7196d52bba.webp
  • 将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数据变更如下:

069f5107b9345baa72f091486bd52ca6.webp
  • 将增量数据开链写入Now_table
      
      insert into Now_table 
select 
 userid,
 bundleid,
 start_date,
 '9999-12-31',
 now() 
from Tmp_table

Now_table数据更新如下:

921535791ce864f7fbb681ea303352b5.webp
  • 通过userid可以查询到历史的状态变化。
      
      select userid,bundleid,start_date,end_date from Now_table where userid='U0001';
77b16652026139d0f818d393ec42af88.webp

4 算法总结

  • Hudi表具有数据更新能力,不需要对全表数据进行insert overwrite操作,算法更简单
  • Hudi表提供Upsert的能力,当相同主键的数据存在,新数据会自动更新老数据,因此不用对老数据进行update操作,直接Insert即可(Sparksql的Insert操作默认为upsert操作。)
  • 对于缓慢变化维的操作会更加简化,设置合理的主键,基于Merge语法直接操作,会更加简单。

欢迎关注微信公众号:大数据AI


浏览 108
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报