數據倉庫中的全量表,增量表,拉鍊表,流水錶及快照表

一.全量表

每天的所有的最新狀態的數據。

  1. 全量表,有無變化,都要報
  2. 每次上報的數據都是所有的數據(變化的 + 沒有變化的)

2020-04-06 mysql對應的user_info表

用戶id

姓名

年齡

手機號

創建時間

修改時間

0001

張三

20

111111

2020-04-06

2020-04-06

0002

小紅

21

222222

2020-04-06

2020-04-06

date_id = 2020-04-06 數倉表wedw_dwd.test_user_info_df(抽取user_info表所有數據)

用戶id

姓名

年齡

手機號

創建時間

修改時間

date_id(分區)

0001

張三

20

111111

2020-04-06

2020-04-06

2020-04-06

0002

小紅

21

222222

2020-04-06

2020-04-06

2020-04-06

2020-04-07 mysql對應的user_info

用戶id

姓名

年齡

手機號

創建時間

修改時間

0001

張三

20

111111

2020-04-06

2020-04-06

0002

小紅

21

222222

2020-04-06

2020-04-06

0003

李四

18

333333

2020-04-07

2020-04-07

date_id = 2020-04-07 數倉表wedw_dwd.test_user_info_df(抽取user_info表所有數據)

用戶id

姓名

年齡

手機號

創建時間

修改時間

date_id(分區)

0001

張三

20

111111

2020-04-06

2020-04-06

2020-04-07

0002

小紅

21

222222

2020-04-06

2020-04-06

2020-04-07

0003

李四

18

333333

2020-04-07

2020-04-07

2020-04-07

二.增量

增量表:新增數據,增量數據是上次導出之後的新數據。
(1)記錄每次增加的量,而不是總量;
(2)增量表,只報變化量,無變化不用報
(3)每天一個分區

2020-04-06 mysql對應的user_info表

用戶id

姓名

年齡

手機號

創建時間

修改時間

0001

張三

20

111111

2020-04-06

2020-04-06

0002

小紅

21

222222

2020-04-06

2020-04-06

date_id = 2020-04-06 數倉表wedw_dwd.test_user_info_di(第一次初始化的時候抽取user_info表所有數據)

用戶id

姓名

年齡

手機號

創建時間

修改時間

date_id(分區)

0001

張三

20

111111

2020-04-06

2020-04-06

2020-04-06

0002

小紅

21

222222

2020-04-06

2020-04-06

2020-04-06

2020-04-07 mysql對應的user_info表

用戶id

姓名

年齡

手機號

創建時間

修改時間

0001

張三

20

111111

2020-04-06

2020-04-06

0002

小紅

21

222444

2020-04-06

2020-04-07

0003

李四

18

333333

2020-04-07

2020-04-07

數倉表wedw_ods.test_user_info_20200407表的數據

用戶id

姓名

年齡

手機號

創建時間

修改時間

0002

小紅

21

222444

2020-04-06

2020-04-07

0003

李四

18

333333

2020-04-07

2020-04-07

date_id = 2020-04-07 數倉表wedw_dwd.test_user_info_di的數據

用戶id

姓名

年齡

手機號

創建時間

修改時間

date_id(分區)

0001

張三

20

111111

2020-04-06

2020-04-06

2020-04-07

0002

小紅

21

222444

2020-04-06

2020-04-07

2020-04-07

0003

李四

18

333333

2020-04-07

2020-04-07

2020-04-07

注:因爲數倉都是T+1的,所以7號的數據是8號加工出來的

加工邏輯:

  1. 根據修改時間,把修改時間等於昨天(即7號)的數據抽取到ods層wedw_ods.test_user_info_20200407
  2. 和數倉表wedw_dwd.test_user_info_di 分區date_id = 2020-04-06通過主鍵用戶id進行關聯,先把wedw_dwd.test_user_info_d存在並且wedw_ods.test_user_info_20200407不存在的數據插入到wedw_dwd.test_user_info_di分區date_id=2020-04-07中
  3. 最後把wedw_ods.test_user_info_20200407表的所有數據插入到wedw_dwd.test_user_info_di分區date_id=2020-04-07
insert overwrite table wedw_dwd.test_user_info_di PARTITION(date_id='2020-04-07') 
select
     a.user_id
    ,a.user_name
    ,a.user_age
    ,a.user_cellphone
    ,a.create_time
    ,a.update_time
from wedw_dwd.test_user_info_di a 
left join wedw_ods.test_user_info_20200407 b
    on  b.user_id=a.user_id
where a.date_id = '2020-04-06'
    and  b.user_id is null;

insert into table wedw_dwd.test_user_info_di PARTITION(date_id='2020-04-07')
select 
     coalesce(user_id'-99')                                          as user_id
    ,coalesce(user_name,'-99')                                       as user_name
    ,coalesce(user_age,0)                                            as user_age
    ,coalesce(user_cellphone,'-99')                                  as user_cellphone
    ,coalesce(create_time,cast('1700-01-01 00:00:00' as timestamp )) as create_time
    ,coalesce(update_time,cast('1700-01-01 00:00:00' as timestamp )) as update_time
from wedw_ods.test_user_info_20200407 b ;

--僅保留近7天的分區
alter table wedw_dwd.test_user_info_di drop if EXISTS partition(date_id='2020-03-31');

特殊增量表:da表,每天的分區就是當天的數據,其數據特點就是數據產生後就不會發生變化,如日誌表

三.拉鍊表

維護歷史狀態,以及最新狀態數據

適用情況:

1.數據量比較大

2.表中的部分字段會被更新

3.需要查看某一個時間點或者時間段的歷史快照信息

            查看某一個訂單在歷史某一個時間點的狀態

            某一個用戶在過去某一段時間,下單次數

4.更新的比例和頻率不是很大
         如果表中信息變化不是很大,每天都保留一份全量,那麼每次全量中會保存很多不變的信息,對存儲是極大的浪費

優點

  1. 滿足反應數據的歷史狀態
  2. 最大程度節省存儲

2020-04-06 mysql對應的user_info表

用戶id

姓名

年齡

手機號

創建時間

修改時間

0001

張三

20

111111

2020-04-06

2020-04-06

0002

小紅

21

222222

2020-04-06

2020-04-06

2020-04-07 mysql對應的user_info表

用戶id

姓名

年齡

手機號

創建時間

修改時間

0001

張三

20

111222

2020-04-06

2020-04-07

0002

小紅

21

222222

2020-04-06

2020-04-06

0003

李四

22

333333

2020-04-07

2020-04-07

0004

王五

44

444444

2020-04-07

2020-04-07

2020-04-08 mysql對應的user_info表

用戶id

姓名

年齡

手機號

創建時間

修改時間

0001

張三

20

111233

2020-04-06

2020-04-08

0002

小紅

21

222221

2020-04-06

2020-04-08

0003

李四

22

333333

2020-04-07

2020-04-07

0004

王五

44

444445

2020-04-07

2020-04-08

005

德瑪

55

555555

2020-04-08

2020-04-08

歷史拉鍊表:分區date_id=2020-04-08的數倉表wedw_dwd.test_user_info_dz

用戶id

姓名

年齡

手機號

創建時間

修改時間

start_time

end_time

date_id

0001

張三

20

111111

2020-04-06

2020-04-06

2020-04-06

2020-04-06

2020-04-08

0001

張三

20

111222

2020-04-06

2020-04-07

2020-04-07

2020-04-07

2020-04-08

0001

張三

20

111233

2020-04-06

2020-04-08

2020-04-08

9999-12-31

2020-04-08

0002

小紅

21

222222

2020-04-06

2020-04-06

2020-04-06

2020-04-07

2020-04-08

0002

小紅

21

222221

2020-04-06

2020-04-08

2020-04-08

9999-12-31

2020-04-08

0003

李四

22

333333

2020-04-07

2020-04-07

2020-04-07

9999-12-31

2020-04-08

0004

王五

44

444444

2020-04-07

2020-04-07

2020-04-07

2020-04-07

2020-04-08

0004

王五

44

444445

2020-04-07

2020-04-08

2020-04-08

9999-12-31

2020-04-08

005

德瑪

55

555555

2020-04-08

2020-04-08

2020-04-08

9999-12-31

2020-04-08

增加兩個字段:
start_time(表示該條記錄的生命週期開始時間——週期快照時的狀態)
end_time(該條記錄的生命週期結束時間)

end_time= ‘9999-12-31’ 表示該條記錄目前處於有效狀態

查詢當前所有有效的記錄:

select * from wedw_dwd.test_user_info_dz where date_id = ‘2020-04-08’ and end_time = ‘9999-12-31’;

用戶id

姓名

年齡

手機號

創建時間

修改時間

start_time

end_time

date_id

0001

張三

20

111233

2020-04-06

2020-04-08

2020-04-08

9999-12-31

2020-04-08

0002

小紅

21

222221

2020-04-06

2020-04-08

2020-04-08

9999-12-31

2020-04-08

0003

李四

22

333333

2020-04-07

2020-04-07

2020-04-07

9999-12-31

2020-04-08

0004

王五

44

444445

2020-04-07

2020-04-08

2020-04-08

9999-12-31

2020-04-08

005

德瑪

55

555555

2020-04-08

2020-04-08

2020-04-08

9999-12-31

2020-04-08

查詢2020-04-07的歷史快照:

select * from  wedw_dwd.test_user_info_dz where date_id = ‘2020-04-08’ and start_time <= ‘2020-04-07’ and end_time >= ‘2020-04-07’;

用戶id

姓名

年齡

手機號

創建時間

修改時間

start_time

end_time

date_id

0001

張三

20

111222

2020-04-06

2020-04-07

2020-04-07

2020-04-07

2020-04-08

0002

小紅

21

222222

2020-04-06

2020-04-06

2020-04-06

2020-04-07

2020-04-08

0003

李四

22

333333

2020-04-07

2020-04-07

2020-04-07

9999-12-31

2020-04-08

0004

王五

44

444444

2020-04-07

2020-04-07

2020-04-07

2020-04-07

2020-04-08

加工邏輯:

注:第一次加工的時候需要初始化所有數據,start_time設置爲數據日期2020-04-06 ,end_time設置爲9999-12-31

--分桶
set hive.enforce.bucketing=FALSE;

--分區
set hive.exec.dynamic.partition=FALSE;
set hive.exec.dynamic.partition.mode=nostrick;
set hive.exec.compress.output=true;
set mapred.output.compress=true;
set mapred.output.compression.type=BLOCK;
set mapred.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec;



alter table wedw_dwd.test_user_info_dz drop if EXISTS PARTITION(date_id='${HIVE_DATA_DATE}');
-- wedw_dwd.test_user_info_dz 存在, wedw_ods.test_user_info_${DATA_DATE} 不存在的 
--或者都存在的閉鏈的 插入到 wedw_dwd.test_user_info_dz 下一個分區
insert overwrite table wedw_dwd.test_user_info_dz PARTITION(date_id='${HIVE_DATA_DATE}')
select 
     a.user_id
    ,a.user_name
    ,a.user_age
    ,a.user_cellphone
    ,a.create_time
    ,a.update_time
    ,a.start_time
    ,a.end_time
from wedw_dwd.test_user_info_dz a 
left join wedw_ods.test_user_info_${DATA_DATE} b on b.user_id=a.user_id and b.create_time < '${HIVE_DATA_DATE+1}'   
where a.date_id = '${HIVE_DATA_DATE-1}' 
and (b.user_id is null   
    or (b.user_id is not null and a.end_time <='${HIVE_DATA_DATE-1}')
  )
;

-- 把wedw_dwd.test_user_info_dz, wedw_ods.test_user_info_${DATA_DATE} 都存在的開鏈的 全部閉鏈  插入到 wedw_dwd.test_user_info_dz 下一個分區
insert into table wedw_dwd.test_user_info_dz PARTITION(date_id='${HIVE_DATA_DATE}')
select 
     a.user_id
    ,a.user_name
    ,a.user_age
    ,a.user_cellphone
    ,a.create_time
    ,a.update_time
    ,a.start_time
    ,'${HIVE_DATA_DATE-1}' end_time
from wedw_dwd.test_user_info_dz a 
inner join wedw_ods.test_user_info_${DATA_DATE} b on b.user_id=a.user_id and b.create_time < '${HIVE_DATA_DATE+1}'
where a.date_id = '${HIVE_DATA_DATE-1}'
and a.end_time >'${HIVE_DATA_DATE-1}'
;

-- 把wedw_ods.test_user_info_${DATA_DATE}, 插入到 wedw_dwd.test_user_info_dz 下一個分區
insert into table wedw_dwd.test_user_info_dz PARTITION(date_id='${HIVE_DATA_DATE}')
select
     a.user_id
    ,a.user_name
    ,a.user_age
    ,a.user_cellphone
    ,a.create_time
    ,a.update_time
    ,'${HIVE_DATA_DATE}' start_time,
    ,'9999-12-31' end_time
from wedw_ods.test_user_info_${DATA_DATE} b
where b.create_time < '${HIVE_DATA_DATE+1}';

--僅保留近7天的數據
alter table wedw_dwd.test_user_info_dz drop if EXISTS partition(date_id='${HIVE_DATA_DATE-7}');

四.流水錶

對於表中的每一個修改都會記錄,可以用於反映實際記錄的變更

五.快照表

每一天的數據都是截止到那一天mysql(數據源)的全量數據

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章