目录
适用场景
优缺点
案例
适用场景
当数据量较大,表中某些字段有变化,但变化频率不是很高,而业务需求又需要统计这种变化状态,如果每天存储一份全量数据,不仅浪费存储空间,且不便于业务统计;这时,拉链表的作用就体现出来了,既节省空间,又满足需求。
优缺点
- 优点:(1)保留了数据的历史信息;(2)节省存储空间;
- 缺点:同步和回滚逻辑复杂
案例
假设业务系统中 存有 一张 “商家信息表” ==》 shops ,每天会有新增、修改(假设哈),
而我们数仓中需要取这张表来做分析
字段 | 类型 | 描述 |
shopid | int | 商铺id |
userid | int | 商铺负责人id |
areaid | int | 区域id |
shopname | varchar | 商铺名称 |
shoplevel | int | 商铺等级 |
status | int | 商铺状态 |
createtime | varchar | 创建日期 |
modifytime | varchar | 修改日期 |
(采集的第一天)原始数据为:
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"
首先在创建 一张 增量分区表:
create table ods_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 (`ds` string);
从业务系统采集数据到仓库中,指定数据分区。2023-03-01
创建拉链表:
create table dwd_shops_his
(
`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 '修改日期',
`start_date` string COMMENT '生效起始日期',
end_date string COMMENT '失效日期'
) COMMENT '商家信息表'
PARTITIONED BY (`dt` string);
把首日的数据加载到拉链表中:第一次的数据 闭链时间都给默认 最大值 9999-12-31
insert overwrite table dwd_shops_his
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' , //闭链时间
'9999-12-31' //分区,以闭链时间做分区,9999-12-31分区存储的数据 为有效数据 ,其他时间分区存储的数据都为当天失效的数据 as enddate
from ods_shops
where ds = '2023-03-01';
(采集的第二天)原始数据发生了变化:
//业务修改的数据
100050,1,100225,"WSxxx营超市",10,10,"2020-06-28","2023-03-02 13:22:22","2023-03-02"
100052,2,100236,"新鲜xxx旗舰店",10,10,"2020-06-28","2023-03-02 13:22:22","2023-03-02"
//业务新增的数据
100054,10,100012,"华为xxx旗舰店1",1,1,"2023-03-02","","2023-03-02"
根据创建时间和修改时间 抽取 数据到 ods_shops增量表分区中 2023-03-02
这时候增量表中 有两个分区:包含修改前、修改后、没修改、新增的数据
(修改后2条+未修改1条+新增1条+修改前2条)
把2023-03-02分区的 数据 装载到 拉链表 ,同时修改 闭链时间
代码为:
insert overwrite table dwd_shops_his
SELECT *,T.end_date FROM
(
SELECT
A.shopid,
A.userid,
A.areaid,
A.shopname,
A.shoplevel,
A.status,
A.createtime,
A.modifytime,
A.start_date,
CASE
WHEN A.end_date = '9999-12-31' AND B.shopid IS NOT NULL THEN current_date()
ELSE A.end_date
END AS end_date
FROM dwd_shops_his AS A
LEFT JOIN ods_shops AS B
ON A.shopid = B.shopid and A.dt='9999-12-31' and B.ds='2023-03-02'
UNION all
SELECT C.shopid,
C.userid,
C.areaid,
C.shopname,
C.shoplevel,
C.status,
C.createtime,
C.modifytime,
c.ds AS start_date,
'9999-12-31' AS end_date
FROM ods_shops AS C where ds='2023-03-02'
) AS T ;
(修改后2条+未修改1条+新增1条)共计 4条 有效数据
查询有效数据:
select * from dwd_shops_his where dt='9999-12-31';
查看所有数据
select * from dwd_shops_his;
拉链记录:有两条数据在 2023-03-02 失效