數倉中的全量表、增量表、快照表、切片表和拉鏈表區別和使用場景


一、全量表:df表,有無變化都要上報,只有一個分區或者沒有分區,每次往全量表里面寫數據都會覆蓋之前的數據,不能記錄數據的歷史變化,只能截止到當前最新、全量的數據

 

二、增量表:每天新增的數據和改變的數據都會存儲在當日的分區中;增量表記錄每次增加的量,只報變化量,無變化的不用報;增量表設計過程,假設以18號與19號數據為例

-- 1、找出19號未修改的數據,寫入當前分區
INSERT OVERWARITE dwd.user_info_di PARTITION(p_dymd='2021-12-19')
WITH t1 AS (
    SELECT *
    FROM dwd.user_info_di
    WHERE p_dymd = '2021-12-18'
), t2 AS (
    SELECT *
    FROM ods.user_info
    WHERE p_dymd = '2021-12-19'   
)
SELECT *
FROM t1 LEFT OUTER JOIN t2
ON t1.user_id = t2.user_id
WHERE t2.user_id is null

-- 2、將19號新增和變化的數據寫入當前分區
INSERT INTO TABLE dwd.user_info_di PARTITION(p_dymd='2021-12-19')
SELECT *
FROM ods.user_info
WHERW p_dymd = '2021-12-19'

-- 3、一般增量表只保存7天的數量
ALTER TABLE dwd.user_info_di DROP IF EXIST PARTITION(p_dymd='2021-12-19')

 

  特殊增量表:da表,一般是埋點日志等,每天的數據存儲在當天的分區里面,數據產生之后就不會再發生變化了。

 

三、快照表:因為全量表無法反映歷史的變化,這時快照表就可以使用了,快照表記錄截止數據日期的全量數據(每個分區都是記錄截止當前分區日期的全量數據),但是在數據量大的情況下,每個分區存儲的都是全量數據,數據冗余和浪費存儲空間;

  

四、切片表:根據基礎表,往往只反映某一個維度的相應數據,數據只有一個維度或者某一事實條件數據;

 

五、拉鏈表:能夠解決快照表數據冗余問題,還能維護數據歷史狀態和最新狀態,記錄截止數據日期的全量數據,一個事物從開始,一直到當前狀態的所有變化信息;

  • 緩慢變化維(SCD):拉鏈表不是SCD,它只是用來處理緩慢變化維的一種手段而已。將分析的角度存放在維度表中,但維度表里的數據可能發生一些變化,盡管可能跨越很久,例如用戶信息表;緩慢變化維處理的方式一般如下:

    1)重寫覆蓋:與業務系統保持一致,直接更新為最新的狀態數據即可;適用於:數據必須正確,比如客戶的身份證;不需要考慮歷史變化維度,沒有意義沒有價值的維度;優點是直接更新即可,缺點無法恢復,不能查看歷史變化

    2)增加新行:更新歷史數據時間戳,新增新行記錄新值;適用於僅需保持歷史數據的業務場景,相應的事實表的的關聯需要更新為最新的id 

    3)增加新列:如果某個維度發生多次變化,會產生列爆炸

    4)拉鏈表

  • 拉鏈表的具體使用

1)同步ods層數據

drop table if exists ods.ods_trade_shops;
create table ods.ods_trade_shops(
  `shopid` int COMMENT '商鋪ID',
  `userid` int COMMENT '商鋪負責人', 
  `areaid` int COMMENT '區域ID',
  `shopname` string COMMENT '商鋪名稱',
  `shoplevel` int COMMENT '商鋪等級',
  `status` int COMMENT '商鋪狀態',
  `createtime` string COMMENT '創建日期',
  `modifytime` string COMMENT  '修改日期'
) COMMENT '商家信息表'
PARTITIONED BY (`dt` string)
row format delimited fields terminated by ',';

../shops/shop-2020-07-01.dat
100050,1,100225,WSxxx營超市,1,1,2020-06-28,2020-07-01 13:22:22
100052,2,100236,新鮮xxx旗艦店,1,1,2020-06-28,2020-07-01 13:22:22
100053,3,100011,華為xxx旗艦店,1,1,2020-06-28,2020-07-01 13:22:22
100054,4,100159,小米xxx旗艦店,1,1,2020-06-28,2020-07-01 13:22:22
100055,5,100211,蘋果xxx旗艦店,1,1,2020-06-28,2020-07-01 13:22:22

../shops/shop-2020-07-02.dat
100057,7,100311,三只xxx鼠零食,1,1,2020-06-28,2020-07-02 13:22:22
100058,8,100329,良子xxx鋪美食,1,1,2020-06-28,2020-07-02 13:22:22
100054,4,100159,小米xxx旗艦店,2,1,2020-06-28,2020-07-02 13:22:22
100055,5,100211,蘋果xxx旗艦店,2,1,2020-06-28,2020-07-02 13:22:22

-- 加載數據
load data local inpath '/app/softwares/2020-07-01.dat' into table ods.ods_trade_shops partition(dt='2020-07-01')

 

2)創建拉鏈表

drop table if exists dim.dim_trade_shops_dz;
create table dim.dim_trade_shops_dz(
  `shopid` int COMMENT '商鋪ID',
  `userid` int COMMENT '商鋪負責人', 
  `areaid` int COMMENT '區域ID',
  `shopname` string COMMENT '商鋪名稱',
  `shoplevel` int COMMENT '商鋪等級',
  `status` int COMMENT '商鋪狀態',
  `createtime` string COMMENT '創建日期',
  `modifytime` string COMMENT  '修改日期',
  -- 拉鏈表新增兩列,生效起始時間和失效結束時間
  `startdate` string  COMMENT '生效起始日期',
  `enddate` string  COMMENT '失效結束日期'
) comment '商家信息表';

 

3)初始化拉鏈表

-- 初始化拉鏈表
insert overwrite table dim.dim_trade_shops_dz
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-07-01'; 

-- 2號維表發生變化:1、取出當天記錄與前一天關聯,存在表示維表更新,將失效時間記為前一天
insert overwrite table dim.dim_trade_shops_dz
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-07-02' 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-07-02',-1) ELSE b.enddate end as enddate from (select * from ods.ods_trade_shops where dt='2020-07-02') a right join dim.dim_trade_shops b on a.shopid = b.shopid;

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM