数仓中的全量表、增量表、快照表、切片表和拉链表区别和使用场景

一、全量表: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;

 

 

 

posted @ 2021-12-18 23:59  Shydow  阅读(14743)  评论(0编辑  收藏  举报