Hudi實(shí)現(xiàn)拉鏈表實(shí)戰(zhàn)
1 基于Hudi表實(shí)現(xiàn)拉鏈表的方案
- 由于Hudi表存儲(chǔ)為了保證數(shù)據(jù)唯一性要求有主鍵,拉鏈表會(huì)對(duì)某一個(gè)對(duì)象的歷史狀態(tài)都存儲(chǔ)所以主鍵設(shè)計(jì)為聯(lián)合主鍵,將對(duì)象ID和生效時(shí)間作為聯(lián)合主鍵。
- Hudi新增了數(shù)據(jù)的更新能力,因此相對(duì)于傳統(tǒng)的大數(shù)據(jù)平臺(tái),可以基于update的能力優(yōu)化傳統(tǒng)hive的拉鏈表的實(shí)現(xiàn)方案。
- 增量數(shù)據(jù)一般不攜帶歷史數(shù)據(jù)的生效時(shí)間
2 拉鏈表實(shí)現(xiàn)算法
- 當(dāng)前最新的拉鏈表為Now_table(UserID:用戶ID,BundleID為套餐ID;Start_date為生效時(shí)間;End_date為失效效時(shí)間)
- 新增數(shù)據(jù)Tmp_table,(由于大數(shù)據(jù)平臺(tái)的數(shù)據(jù)基于上游采集而來(lái),基于時(shí)間戳的增量數(shù)據(jù)相對(duì)容易獲取到)
- 新增數(shù)據(jù)Tmp_table與Now_table關(guān)聯(lián),將以存在數(shù)據(jù)更新寫(xiě)入Now_table,end_date為當(dāng)前時(shí)間
- 將新增數(shù)據(jù)全部寫(xiě)入Now_table,end_date為'9999-12-31'
3 實(shí)現(xiàn)舉例
- 創(chuàng)建Now_table,并初始化數(shù)據(jù)
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());
- 新增數(shù)據(jù)臨時(shí)表Tmp_table,新增數(shù)據(jù)到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數(shù)據(jù)內(nèi)容如下:
- 將Now_table數(shù)據(jù)閉鏈
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數(shù)據(jù)變更如下:
- 將增量數(shù)據(jù)開(kāi)鏈寫(xiě)入Now_table
insert into Now_table
select
userid,
bundleid,
start_date,
'9999-12-31',
now()
from Tmp_table
Now_table數(shù)據(jù)更新如下:
- 通過(guò)userid可以查詢到歷史的狀態(tài)變化。
select userid,bundleid,start_date,end_date from Now_table where userid='U0001';
4 算法總結(jié)
- Hudi表具有數(shù)據(jù)更新能力,不需要對(duì)全表數(shù)據(jù)進(jìn)行insert overwrite操作,算法更簡(jiǎn)單
- Hudi表提供Upsert的能力,當(dāng)相同主鍵的數(shù)據(jù)存在,新數(shù)據(jù)會(huì)自動(dòng)更新老數(shù)據(jù),因此不用對(duì)老數(shù)據(jù)進(jìn)行update操作,直接Insert即可(Sparksql的Insert操作默認(rèn)為upsert操作。)
- 對(duì)于緩慢變化維的操作會(huì)更加簡(jiǎn)化,設(shè)置合理的主鍵,基于Merge語(yǔ)法直接操作,會(huì)更加簡(jiǎn)單。
歡迎關(guān)注微信公眾號(hào):大數(shù)據(jù)AI
評(píng)論
圖片
表情
