update 两个表关联_拉链表(二)
拉鏈表(二)
一、前言
在上一節簡單介紹了拉鏈表,本節主要講解如何通過binlog采集MySQL的數據并且按月分區的方式實現拉鏈表。
這里以上節介紹的用戶表(user) 舉例
二、涉及到的表
1. 原始表(user)
原始表指的是MySQL中的表,表結構如下:
其中name為主鍵,如果沒有主鍵則無法做拉鏈表。
2. binlog流水表(user_binlog)
操作類型字段枚舉值為:insert、update、delete。
設置binlog時間 的目的是防止業務方沒有設置modify_time導致獲取不到最新的更新時間,所以增加binlog時間。
日期分區字段是從binlog_time計算得來,作為分區字段
3. 拉鏈表(user_link)
這里包含的字段除去原始表的字段增加了生效日期及失效日期具體作用已經在上一節介紹過,這里就不再贅述。
4. 臨時表(user_link_tmp)
這張表的用途是: 在數據從user_binlog寫入user_link時,臨時表起到中轉的作用。并且臨時表沒有分區。
三、計算流程
1. 整體數據流向
2. user到user_binlog
數據從user表到user_binlog表可以采用開源的采集binlog工具實時寫入。具體的實施方案和選擇的開源工具有關,這里不詳細介紹。
3. user_binlog到user_link
(1) 常規流程
把數據從binlog表同步到拉鏈表中主要分兩步:
- 刪除拉鏈表中失效的數據: 這里包括update和delete類型的數據,都涉及到刪除原始拉鏈表的數據。在這一步驟中有兩個子步驟
- 將拉鏈表中失效的失效日期字段改為批次日期
- 從拉鏈表原有分區中刪除失效的數據
- 插入新的數據:這一步驟涉及到的操作類型包含insert和update
接下來會以7月11日執行的SQL舉例,詳細介紹如何把binlog表的數據同步到拉鏈表中。其中的SQL涉及到先把binlog表中的數據同步到臨時表,并把臨時表寫入到拉鏈表。
-- 先清空臨時表的數據。 -- 理論上這張表已經是清空的。 -- 這里清空主要是防止異常清空,導致上一批次沒有清空臨時表 truncate table user_link_tmp;-- 將拉鏈表中需要改為失效的數據的失效時間改為'2019-07-10',并把數據寫入到臨時表中 -- 其中start_date>='2019-07-01'是因為7月1日之前未失效的數據會寫入到開始時間為7月1日的分區中, -- 所以查開始分區只要查當月的即可 -- 結束分區用end_date>'2019-07-09'而不用end_date='9999-12-31'是防止歷史數據重跑時前一中寫法不會有問題,而第二種寫法只有在正常邏輯中沒有問題。 insert into table user_link_tmp select name,phone,sing_up_date,modify_time,start_date,'2019-07-10' as end_date from user_link where start_date<='2019-07-09' and start_date>='2019-07-01' and end_date>'2019-07-09' and name in (select name from user_binlog where day_num='2019-07-10' and type in ('update','delete') group by name );-- 將原始拉鏈表中未失效的數據原樣寫入到臨時表中 -- 此步驟的目的是從原有分區中刪除失效的數據 -- 即在把臨時表的數據覆蓋到拉鏈表中時會把失效的數據從原有未失效分區中刪除。 insert into table user_link_tmp select name,phone,sing_up_date,modify_time,start_date,end_date from user_link where start_date<='2019-07-09' and start_date>='2019-07-01' and end_date>'2019-07-09' and name not in (select name from user_binlog where day_num='2019-07-10' and type in ('update','delete') group by name );-- 將新增的數據寫入到臨時表中。 -- 并且開始時間為當前批次日期,結束日期為最大日期 insert into table user_link_tmp select a.name,a.phone,a.sing_up_date,a.modify_time,'2019-07-10' as start_date,'9999-12-31' as end_date from (select name,phone,sing_up_date,modify_time,binlog_timefrom user_binlogwhere day_num='2019-07-10' ) a right join (select name,max(binlog_time)from user_binlogwhere day_num='2019-07-10'and type in ('insert','update') group by name ) b on a.name=b.name and a.binlog_time=b.binlog_time ;-- 將臨時表中的數據覆蓋到拉鏈表中。 insert overwrite table user_link partition(start_date) select name,phone,sing_up_date,modify_time,start_date,end_date from user_link_tmp;-- 刪除臨時表中的數據 truncate table user_link_tmp;(2) 月初流程
在每個月月初會涉及到把上月還未失效的數據寫入到開始時間為當月1日失效日期為9999-12-31的分區中,并把原始數據的失效日期改為上月末的邏輯。
接下來會以7月2日執行的SQL為例,來展示7月1日的數據是如何同步的。
truncate table user_link_tmp;-- 把拉鏈表所有6月30日未失效的數據失效日期改為7月1日 insert into table user_link_tmp; select name,phone,sing_up_date,modify_time,start_date,'2019-07-01' as end_dat from user_link where start_date<='2019-06-30' and start_date>='2019-06-01' and end_date>'2019-06-30'-- 把7月1日依然為失效的數據的開始日期改為7月1日失效日期改為9999-12-31 insert into table user_link_tmp select name,phone,sing_up_date,modify_time,'2019-07-01' as start_date,'9999-12-31' as end_date from user_link where start_date<='2019-06-30' and start_date>='2019-06-01' and end_date>'2019-06-30' and name not in (select name from user_binlog where day_num='2019-07-01' and type in ('update','delete') group by name );-- 把7月1日新的數據寫入到臨時表中 insert into table user_link_tmp select a.name,a.phone,a.sing_up_date,a.modify_time,'2019-07-01' as start_date,'9999-12-31' as end_date from (select name,phone,sing_up_date,modify_time,binlog_timefrom user_binlogwhere day_num='2019-07-01' ) a right join (select name,max(binlog_time)from user_binlogwhere day_num='2019-07-10'and type in ('insert','update') group by name ) b on a.name=b.name and a.binlog_time=b.binlog_time-- 將臨時表中的數據覆蓋到拉鏈表中。 insert overwrite table user_link partition(start_date) select name,phone,sing_up_date,modify_time,start_date,end_date from user_link_tmp;-- 刪除臨時表中的數據 truncate table user_link_tmp;-- 刪除6月份所有結束時間為9999-12-31分區的數據 alter table user_link_tmp drop if exists partition(stat_date>='2019-06-01' , start_date<'2019-07-01', end_date='9999-12-31' );(3) 數據重跑
如果某個日期同步的數據出現問題需要重跑數據,則需要重跑從當日的同步SQL到當前日期所有的SQL才能保證數據準確。
三、總結
至此,拉鏈表的同步過程就結束了。總體將拉鏈表的同步對資源消耗還是蠻多的。
注意:本文的實現還有需要考慮不周的地方,在應用的時候需要根據自己的需求進行優化。 《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的update 两个表关联_拉链表(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: httpclient异步发送请求_关于T
- 下一篇: python模块使用_PYthon模块使