這篇文章主要介紹“大數(shù)據(jù)開發(fā)中數(shù)倉拉鏈表怎么迭代或回滾”,在日常操作中,相信很多人在大數(shù)據(jù)開發(fā)中數(shù)倉拉鏈表怎么迭代或回滾問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”大數(shù)據(jù)開發(fā)中數(shù)倉拉鏈表怎么迭代或回滾”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
成都創(chuàng)新互聯(lián)專注于網(wǎng)站建設|網(wǎng)站建設維護|優(yōu)化|托管以及網(wǎng)絡推廣,積累了大量的網(wǎng)站設計與制作經(jīng)驗,為許多企業(yè)提供了網(wǎng)站定制設計服務,案例作品覆蓋PE包裝袋等行業(yè)。能根據(jù)企業(yè)所處的行業(yè)與銷售的產(chǎn)品,結合品牌形象的塑造,量身設計品質網(wǎng)站。
拉鏈表是什么,在數(shù)倉建立時候,一種重要的表數(shù)據(jù)處理方式,可以將數(shù)據(jù)結構于算法,類比于拉鏈表于數(shù)倉,旨在解決數(shù)倉建立里面的SCD需求,那么什么是SCD,就是緩慢變化維,隨著時間流逝,數(shù)據(jù)相對事實表發(fā)生緩慢變化。
SCD的常用處理方式有以下幾種:
保留原值
直接覆蓋
增加新屬性列
快照表
拉鏈表
本文主要講解拉鏈表來處理SCD的問題,其特點歸納以下,有以下幾種場景時候,可以使用拉鏈表。
1.表數(shù)據(jù)量較大,用全量表會占用很多存儲
2.表數(shù)據(jù)會有修改,用增量表,難以處理重復且修改數(shù)據(jù)
3.有回溯的需求,需要知道歷史某個時間點的全量數(shù)據(jù)
4.數(shù)據(jù)有修改,但是頻率和量不是很大比如只有百萬分之一有修改
首先拉鏈表是一個全量表且不是分區(qū)表,為了達到前面描述的各種效果,必然需要一個中間表來做中間跳板,這個中間跳板表是一個分區(qū)表,數(shù)據(jù)是增量數(shù)據(jù),增量內容包括修改和增加,即常常是create_time or update_time
落在當前天,對于拉鏈表需要增加兩個與原始數(shù)據(jù)沒有關系的兩個字段來標識數(shù)據(jù)開始時間和有效截至時間,在示例中,這兩個日期分別為start_date
和 end_date
,拉鏈表其處理方式主要有以下三種:初始化,每天更新數(shù)據(jù),回滾數(shù)據(jù)。
其每天的滾動方式如下圖:
初始化部分,是拉鏈全量表的開始時間,也奠定了回滾時候能夠回滾的最早時間,每天更新邏輯如上圖,新增數(shù)據(jù)會分為兩部分,一部分是每天新增的數(shù)據(jù),對于當天分區(qū)里面有相同變化或者未變化的數(shù)據(jù)時候,分別修改對應的start_date
和 end_date
即可達到更新數(shù)據(jù)。
對于上面的更新邏輯,我們來考慮如何回滾數(shù)據(jù),即回到歷史的某個時間點,對于拉鏈表來說是全量表,所以只有一個回滾即可。回滾策略可以根據(jù)回滾時間點和數(shù)據(jù)生成的start_date
和 end_date
,具體怎么回滾,我們來看下面的示意圖:
在end_date < rollback_date
的數(shù)據(jù)要保留,對于處理end_date ≥ rollback_date ≥ start_date
設置end_date
為9999-12-31
,對于回滾的結果,一般為了保持數(shù)據(jù)的完整性,可以將回滾的數(shù)據(jù)放在一個新的拉鏈臨時表中。
對于數(shù)倉的常用分層DIM即維度層是拉鏈表的常用場景,下面有個例子拉看看拉鏈表怎么做新增和回滾。
用拉鏈表實現(xiàn)核心交易分析中DIM層商家維表,并實現(xiàn)該拉鏈表的回滾。
其中商家維表結構如下:
--創(chuàng)建商家信息表(增量表 分區(qū)表) drop table if exists ods.ods_trade_shops; create table ods.ods_trade_shops( `shopid` int COMMENT '商鋪ID', `userid` int COMMENT '商鋪負責人', `areaid` int COMMENT '區(qū)域ID', `shopname` string COMMENT '商鋪名稱', `shoplevel` int COMMENT '商鋪等級', `status` int COMMENT '商鋪狀態(tài)', `createtime` string COMMENT '創(chuàng)建日期', `modifytime` string COMMENT '修改日期' ) COMMENT '商家信息表' PARTITIONED BY (`dt` string) row format delimited fields terminated by ','; -- 創(chuàng)建商家信息維表 drop table if exists dim.dim_trade_shops; create table dim.dim_trade_shops( `shopid` int COMMENT '商鋪ID', `userid` int COMMENT '商鋪負責人', `areaid` int COMMENT '區(qū)域ID', `shopname` string COMMENT '商鋪名稱', `shoplevel` int COMMENT '商鋪等級', `status` int COMMENT '商鋪狀態(tài)', `createtime` string COMMENT '創(chuàng)建日期', `modifytime` string COMMENT '修改日期', `startdate` string COMMENT '生效起始日期', `enddate` string COMMENT '失效結束日期' ) COMMENT '商家信息表';
導入以下測試數(shù)據(jù):
/root/data/shop-2020-11-20.dat 100050,1,100225,WSxxx營超市,1,1,2020-06-28,2020-11-20 13:22:22 100052,2,100236,新鮮xxx旗艦店,1,1,2020-06-28,2020-11-20 13:22:22 100053,3,100011,華為xxx旗艦店,1,1,2020-06-28,2020-11-20 13:22:22 100054,4,100159,小米xxx旗艦店,1,1,2020-06-28,2020-11-20 13:22:22 100055,5,100211,蘋果xxx旗艦店,1,1,2020-06-28,2020-11-20 13:22:22 /root/data/shop-2020-11-21.dat 100057,7,100311,三只xxx鼠零食,1,1,2020-06-28,2020-11-21 13:22:22 100058,8,100329,良子xxx鋪美食,1,1,2020-06-28,2020-11-21 13:22:22 100054,4,100159,小米xxx旗艦店,2,1,2020-06-28,2020-11-21 13:22:22 100055,5,100211,蘋果xxx旗艦店,2,1,2020-06-28,2020-11-21 13:22:22 /root/data/shop-2020-11-22.dat 100059,9,100225,樂居xxx日用品,1,1,2020-06-28,2020-11-22 13:22:22 100060,10,100211,同仁xxx大健康,1,1,2020-06-28,2020-11-22 13:22:22 100052,2,100236,新鮮xxx旗艦店,1,2,2020-06-28,2020-11-22 13:22:22 load data local inpath '/root/data/shop-2020-11-20.dat' overwrite into table ods.ods_trade_shops partition(dt='2020-11-20'); load data local inpath '/root/data/shop-2020-11-21.dat' overwrite into table ods.ods_trade_shops partition(dt='2020-11-21'); load data local inpath '/root/data/shop-2020-11-22.dat' overwrite into table ods.ods_trade_shops partition(dt='2020-11-22');
假設將第一天數(shù)據(jù)作為歷史的所有數(shù)據(jù)
INSERT OVERWRITE TABLE dim.dim_trade_shops SELECT shopid, userid, areaid, shopname, shoplevel, status, createtime, modifytime, CASE WHEN modifytime IS NOT NULL THEN substr(modifytime, 0, 10) ELSE substr(createtime, 0, 10) END AS startdate, '9999-12-31' AS enddate FROM ods.ods_trade_shops WHERE dt ='2020-11-20';
對于增量表,一般的邏輯是,create_time
或者modifytime
的截取作為當天分區(qū)dt
,modifytime
大于等于create_time
,這里取前兩個
INSERT OVERWRITE TABLE dim.dim_trade_shops SELECT shopid, userid, areaid, shopname, shoplevel, status, createtime, modifytime, CASE WHEN modifytime IS NOT NULL THEN substr(modifytime, 0, 10) ELSE substr(createtime, 0, 10) END AS startdate, '9999-12-31' AS enddate FROM ods.ods_trade_shops WHERE dt = '2020-11-21' UNION ALL SELECT b.shopid, b.userid, b.areaid, b.shopname, b.shoplevel, b.status, b.createtime, b.modifytime, b.startdate, CASE WHEN a.shopid IS NOT NULL AND b.enddate ='9999-12-31' THEN date_add('2020-11-21', -1) ELSE b.enddate END AS enddate FROM (SELECT * FROM ods.ods_trade_shops WHERE dt='2020-11-21') a RIGHT JOIN dim.dim_trade_shops b ON a.shopid = b.shopid;
加載拉鏈表的腳本如下:
dim_load_shops.sh
#!/bin/bash source /etc/profile if [ -n "$1" ] then do_date=$1 else do_date=`date -d "-1 day" +%F` fi sql=" INSERT OVERWRITE TABLE dim.dim_trade_shops SELECT shopid, userid, areaid, shopname, shoplevel, status, createtime, modifytime, CASE WHEN modifytime IS NOT NULL THEN substr(modifytime, 0, 10) ELSE substr(createtime, 0, 10) END AS startdate, '9999-12-31' AS enddate FROM ods.ods_trade_shops WHERE dt = '$do_date' UNION ALL SELECT b.shopid, b.userid, b.areaid, b.shopname, b.shoplevel, b.status, b.createtime, b.modifytime, b.startdate, CASE WHEN a.shopid IS NOT NULL AND b.enddate ='9999-12-31' THEN date_add('$do_date', -1) ELSE b.enddate END AS enddate FROM (SELECT * FROM ods.ods_trade_shops WHERE dt='$do_date') a RIGHT JOIN dim.dim_trade_shops b ON a.shopid = b.shopid; " hive -e "$sql"
可以執(zhí)行此腳本來加載2020-12-22
的數(shù)據(jù),sh dim_load_shops.sh 2020-12-22
先創(chuàng)建一個臨時表,tmp.shops_tmp
用來放回滾的數(shù)據(jù)
DROP TABLE IF EXISTS tmp.shops_tmp; CREATE TABLE IF NOT EXISTS tmp.tmp_shops AS SELECT shopid, userid, areaid, shopname, shoplevel, status, createtime, modifytime, startdate, enddate FROM dim.dim_trade_shops WHERE enddate < '2020-11-21' UNION ALL SELECT shopid, userid, areaid, shopname, shoplevel, status, createtime, modifytime, startdate, '9999-12-31' AS enddate FROM dim.dim_trade_shops WHERE startdate <= '2020-11-21' AND enddate >= '2020-11-21'; INSERT OVERWRITE TABLE dim.dim_trade_shops SELECT * FROM tmp.tmp_shops;
回滾腳本和更新腳本類似,只要更新其中的sql即可,這里不再重復。
到此,關于“大數(shù)據(jù)開發(fā)中數(shù)倉拉鏈表怎么迭代或回滾”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
網(wǎng)站題目:大數(shù)據(jù)開發(fā)中數(shù)倉拉鏈表怎么迭代或回滾
網(wǎng)址分享:http://weahome.cn/article/pchggi.html