|NO.Z.00052|——————————|^^ 案例 ^^|——|Hadoop&PB级数仓.V10|——|PB数仓.v10|周期性事实表|实现小结|

一、周期性事实表:有如下订单表,6月20号有3条记录(001/002/003):
订单创建日期 订单编号 订单状态
2020-06-20 001 创建订单
2020-06-20 002 创建订单
2020-06-20 003 支付完成
6月21日,表中有5条记录。其中新增2条记录(004/005),修改1条记录(001):
订单创建日期 订单编号 订单状态
2020-06-20 001 支付完成(从创建到支付)
2020-06-20 002 创建订单
2020-06-20 003 支付完成
2020-06-21 004 创建订单
2020-06-21 005 创建订单
6月22日,表中有6条记录。其中新增1条记录(006),修改2条记录(003/005):
订单创建日期 订单编号 订单状态
2020-06-20 001 支付完成
2020-06-20 002 创建订单
2020-06-20 003 已发货(从支付到发货)
2020-06-21 004 创建订单
2020-06-21 005 支付完成(从创建到支付)
2020-06-21 006 创建订单
二、订单表处理
### --- 订单事实表的处理方法:
### --- 历史拉链表数据

~~~     只保留一份全量。数据和6月22日的记录一样,如果需要查看6月21日订单001的状态,则无法满足;
~~~     每天都保留一份全量。在数据仓库中可以在找到所有的历史信息,
~~~     但数据量大了,而且很多信息都是重复的,会造成较大的存储浪费;
~~~     使用拉链表保存历史信息,会有下面这张表。
~~~     历史拉链表,既能满足保存历史数据的需求,也能节省存储资源。
订单创建日期 订单编号 订单状态 begin_date end_date
2020-06-20 001 创建订单 2020-06-20 2020-06-20
2020-06-20 001 支付完成 2020-06-21 9999-12-31
2020-06-20 002 创建订单 2020-06-20 9999-12-31
2020-06-20 003 支付完成 2020-06-20 2020-06-21
2020-06-20 003 已发货 2020-06-22 9999-12-31
2020-06-21 004 创建订单 2020-06-21 9999-12-31
2020-06-21 005 创建订单 2020-06-21 2020-06-21
2020-06-21 005 支付完成 2020-06-22 9999-12-31
2020-06-22 006 创建订单 2020-06-22 9999-12-31
三、周期性事实表:拉链表实现
### --- 前提条件

~~~     订单表的刷新频率为一天,当天获取前一天的增量数据;
~~~     如果一个订单在一天内有多次状态变化,只记录最后一个状态的信息;
~~~     订单状态包括三个:创建、支付、完成;
~~~     创建时间和修改时间只取到天,如果源订单表中没有状态修改时间,
~~~     那么抽取增量就比较麻烦,需要有个机制来确保能抽取到每天的增量数据;
### --- 数仓ODS层有订单表,数据按日分区,存放每天的增量数据:

DROP TABLE test.ods_orders;

CREATE TABLE test.ods_orders(
orderid INT,
createtime STRING,
modifiedtime STRING,
status STRING
) PARTITIONED BY (dt STRING)
row format delimited fields terminated by ',';
### --- 数仓DWD层有订单拉链表,存放订单的历史状态数据:

DROP TABLE test.dwd_orders;

CREATE TABLE test.dwd_orders(
orderid INT,
createtime STRING,
modifiedtime STRING,
status STRING,
start_date STRING,
end_date STRING
)
row format delimited fields terminated by ',';
四、周期性事实表拉链表的实现
### --- 全量初始化
~~~     # 数据文件order1.dat

[root@hadoop02 ~]# vim /data/yanqidw/data/order1.dat
001,2020-06-20,2020-06-20,创建
002,2020-06-20,2020-06-20,创建
003,2020-06-20,2020-06-20,支付
~~~     # 加载数据

hive (default)> load data local inpath '/data/yanqidw/data/order1.dat' 
into table test.ods_orders partition(dt='2020-06-20');

hive (default)> INSERT overwrite TABLE test.dwd_orders
SELECT orderid, createtime, modifiedtime, status,
createtime AS start_date,
'9999-12-31' AS end_date FROM test.ods_orders
WHERE dt='2020-06-20';
~~~     # 查看加载的数据

hive (default)> select * from test.ods_orders;
~~~输出参数
ods_orders.orderid  ods_orders.createtime   ods_orders.modifiedtime ods_orders.status   ods_orders.dt
1   2020-06-20  2020-06-20  创建  2020-06-20
2   2020-06-20  2020-06-20  创建  2020-06-20
3   2020-06-20  2020-06-20  支付  2020-06-20

hive (default)> select * from  test.dwd_orders;
~~~输出参数
dwd_orders.orderid  dwd_orders.createtime   dwd_orders.modifiedtime dwd_orders.status   dwd_orders.start_date   dwd_orders.end_date
1   2020-06-20  2020-06-20  创建  2020-06-20  9999-12-31
2   2020-06-20  2020-06-20  创建  2020-06-20  9999-12-31
3   2020-06-20  2020-06-20  支付  2020-06-20  9999-12-31
### --- 增量抽取
~~~     # 数据文件order2.dat

[root@hadoop02 ~]# vim /data/yanqidw/data/order2.dat
001,2020-06-20,2020-06-21,支付
004,2020-06-21,2020-06-21,创建
005,2020-06-21,2020-06-21,创建
~~~     # 加载数据

hive (default)> load data local inpath '/data/yanqidw/data/order2.dat' 
into table test.ods_orders partition(dt='2020-06-21');
~~~     # 查看加载的数据

hive (default)> select * from test.ods_orders;
~~~输出参数
ods_orders.orderid  ods_orders.createtime   ods_orders.modifiedtime ods_orders.status   ods_orders.dt
1   2020-06-20  2020-06-20  创建  2020-06-20
2   2020-06-20  2020-06-20  创建  2020-06-20
3   2020-06-20  2020-06-20  支付  2020-06-20
1   2020-06-20  2020-06-21  支付  2020-06-21
4   2020-06-21  2020-06-21  创建  2020-06-21
5   2020-06-21  2020-06-21  创建  2020-06-21
### --- 增量刷新历史数据
~~~     # 拉链表中的数据分两部实现:新增数据(ods_orders)、历史数据(dwd_orders)
~~~     # 处理新增数据

hive (default)> SELECT orderid,
createtime,
modifiedtime,
status,
modifiedtime AS start_date,
'9999-12-31' AS end_date
FROM test.ods_orders
where dt='2020-06-21';
~~~输出参数
orderid createtime  modifiedtime    status  start_date  end_date
1   2020-06-20  2020-06-21  支付  2020-06-21  9999-12-31
4   2020-06-21  2020-06-21  创建  2020-06-21  9999-12-31
5   2020-06-21  2020-06-21  创建  2020-06-21  9999-12-31
~~~     # 处理历史数据。历史数据包括:有修改、无修改的数据
~~~     ods_orders 与 dwd_orders 进行表连接
~~~     连接上,说明数据被修改
~~~     未连接上,说明数据未被修改

hive (default)> select A.orderid,
A.createtime,
A.modifiedtime,
A.status,
A.start_date,
case when B.orderid is not null and A.end_date>'2020-06-21'
then '2020-06-20'
else A.end_date
end end_date
from test.dwd_orders A
left join (select * from test.ods_orders where dt='2020-06-21')
B on A.orderid=B.orderid;
~~~输出参数
a.orderid   a.createtime    a.modifiedtime  a.status    a.start_date    end_date
1   2020-06-20  2020-06-20  创建  2020-06-20  2020-06-20
2   2020-06-20  2020-06-20  创建  2020-06-20  9999-12-31
3   2020-06-20  2020-06-20  支付  2020-06-20  9999-12-31
~~~     # 用以上信息覆写拉链表

hive (default)> insert overwrite table test.dwd_orders
SELECT orderid,
createtime,
modifiedtime,
status,
modifiedtime AS start_date,
'9999-12-31' AS end_date
FROM test.ods_orders
where dt='2020-06-21'
union all
select A.orderid,
A.createtime,
A.modifiedtime,
A.status,
A.start_date,
case when B.orderid is not null and A.end_date>'2020-06-21'
then '2020-06-20'
else A.end_date
end end_date
from test.dwd_orders 
A left join (select * from test.ods_orders where dt='2020-06-21') 
B on A.orderid=B.orderid;
~~~     # 查看

hive (default)> select * from test.dwd_orders;
~~~输出参数
dwd_orders.orderid  dwd_orders.createtime   dwd_orders.modifiedtime dwd_orders.status   dwd_orders.start_date   dwd_orders.end_date
1   2020-06-20  2020-06-20  创建  2020-06-20  2020-06-20
2   2020-06-20  2020-06-20  创建  2020-06-20  9999-12-31
3   2020-06-20  2020-06-20  支付  2020-06-20  9999-12-31
1   2020-06-20  2020-06-21  支付  2020-06-21  9999-12-31
4   2020-06-21  2020-06-21  创建  2020-06-21  9999-12-31
5   2020-06-21  2020-06-21  创建  2020-06-21  9999-12-31

附录一:拉链表小结

 
 
 
 
 
 
 
 
 

Walter Savage Landor:strove with none,for none was worth my strife.Nature I loved and, next to Nature, Art:I warm'd both hands before the fire of life.It sinks, and I am ready to depart
                                                                                                                                                   ——W.S.Landor

 

posted on   yanqi_vip  阅读(21)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示