🔝Hive实现时间拉链功能

使用Hive实现时间拉链功能 - 菠萝大数据梦工厂(Free World) - 博客频道 - CSDN.NET http://blog.csdn.net/jiangshouzhuang/article/details/50659408

背景:
在数据仓库的数据模型设计过程中,经常会遇到如下的业务需求:1. 表的数据量很大,大几千万或上亿;2. 表中的部分字段会被update更新操作,如用户的上级领导,产品的描述信息,订单的状态等等;3. 需要查看某一个时间点或者时间段的历史快照信息,比如,查看某一个订单在历史某一个时间点的状态;4. 变化的比例和频率不是很大,比如,总共有8000万的用户,每天新增和发生变化的有30万左右;5. 如果对这边表每天都保留一份全量,那么每次全量中会保存很多不变的信息,对存储是极大的浪费;6. 时间拉链历史表,既能满足反应数据的历史状态,又可以最大程度的节省存储空间。

一. 演示的数据

2015-08-21 以及之前的订单表数据:
1|2015-08-18|2015-08-18|创建
2|2015-08-18|2015-08-18|创建
3|2015-08-19|2015-08-21|支付
4|2015-08-19|2015-08-21|完成
5|2015-08-19|2015-08-20|支付
6|2015-08-20|2015-08-20|创建
7|2015-08-20|2015-08-21|支付
8|2015-08-21|2015-08-21|创建

2015-08-22 订单表数据:
1|2015-08-18|2015-08-22|支付
2|2015-08-18|2015-08-22|完成
6|2015-08-20|2015-08-22|支付
8|2015-08-21|2015-08-22|支付
9|2015-08-22|2015-08-22|创建
10|2015-08-22|2015-08-22|支付

2015-08-23 订单表数据:
1|2015-08-18|2015-08-23|完成
3|2015-08-19|2015-08-23|完成
5|2015-08-19|2015-08-23|完成
8|2015-08-21|2015-08-23|完成
11|2015-08-23|2015-08-23|创建
12|2015-08-23|2015-08-23|创建
13|2015-08-23|2015-08-23|支付

将上面所有的数据全部保存到如下文件中:
/home/Hadoop/hivetestdata/Time_zipper/orders.txt

二. 表结构
源系统中订单表结构:

[sql] view plain copy

派生到我的代码片
派生到我的代码片

use timezipper;
create table orders (
orderid int,
createtime string,
modifiedtime string,
status string
) row format delimited fields terminated by '|';

load data local inpath "file:///home/hadoop/hivetestdata/Time_zipper/orders.txt" into table orders;

在数据仓库的ODS层,有一张订单的增量数据表,按天分区,存放每天的增量数据:

[sql] view plain copy

派生到我的代码片
派生到我的代码片

create table t_ods_orders_inc (
orderid int,
createtime string,
modifiedtime string,
status string
) partitioned by (day string) row format delimited fields terminated by '|';

在数据仓库的DW层,有一张订单的历史数据拉链表,存放订单的历史状态数据:

[sql] view plain copy

派生到我的代码片
派生到我的代码片

create table t_dw_orders_his (
orderid int,
createtime string,
modifiedtime string,
status string,
dw_start_date string,
dw_end_date string
);

三. 全量数据初始化
在数据从源业务系统每天正常抽取和刷新到DW订单历史表之前,
需要做一次全量的初始化,就是从源订单表中指定某一天以前的数据全部抽取到ODW,并刷新到DW。

以上面的数据为例,比如在2015-08-22这天做全量初始化,那么我需要将2015-08-21以及之前的所有的数据都抽取并刷新到DW,步骤如下:
第一步:抽取全量数据到ODS:

[sql] view plain copy

派生到我的代码片
派生到我的代码片

use timezipper;
INSERT overwrite TABLE t_ods_orders_inc PARTITION (day='2015-08-21')
SELECT orderid,createtime,modifiedtime,status
FROM orders
WHERE modifiedtime <= '2015-08-21';

第二步:从ODS刷新到DW:

[sql] view plain copy

派生到我的代码片
派生到我的代码片

use timezipper;
INSERT overwrite TABLE t_dw_orders_his
SELECT orderid,createtime,modifiedtime,status,
createtime AS dw_start_date,
'9999-12-31' AS dw_end_date
FROM t_ods_orders_inc
WHERE day = '2015-08-21';

四. 增量抽取历史数据并计算生成时间拉链结果表
从2015-08-23开始,需要每天正常刷新前一天(2015-08-22)的增量数据到历史表,步骤如下:
第一步:通过增量抽取,将2015-08-22的数据抽取到ODS:

[sql] view plain copy

派生到我的代码片
派生到我的代码片

INSERT overwrite TABLE t_ods_orders_inc PARTITION (day = '2015-08-22')
SELECT orderid,createtime,modifiedtime,status
FROM orders
WHERE modifiedtime = '2015-08-22';

第二步:通过DW历史数据(数据日期为2015-08-21(包含2015-08-21以及之前的数据)),和ODS增量数据(2015-08-22),刷新历史表:
先把数据放到一张临时表中:

[sql] view plain copy

派生到我的代码片
派生到我的代码片

drop table if exists t_dw_orders_his_tmp;
create table t_dw_orders_his_tmp as
select oo.orderid,
oo.createtime,
oo.modifiedtime,
oo.status,
oo.dw_start_date,
oo.dw_end_date
from (select
tt.orderid,
tt.createtime,
tt.modifiedtime,
tt.status,
tt.dw_start_date,
tt.dw_end_date,
row_number() over(distribute by tt.orderid,tt.createtime,tt.modifiedtime,status sort by tt.dw_end_date desc) rn
from (
select a.orderid,
a.createtime,
a.modifiedtime,
a.status,
a.dw_start_date,
-- 2015-08-21保存的都是历史数据
case when b.orderid is not null and a.dw_end_date > '2015-08-22' then '2015-08-21'
else a.dw_end_date end as dw_end_date
from t_dw_orders_his a
left outer join (select * from t_ods_orders_inc where day = '2015-08-22') b
on (a.orderid = b.orderid)

    union all   
   
    select orderid,  
           createtime,  
           modifiedtime,  
           status,  
           modifiedtime as dw_start_date,  
           '9999-12-31' as dw_end_date   
      from t_ods_orders_inc   
    where day = '2015-08-22') tt   

) oo where oo.rn =1;

说明:
UNION ALL的两个结果集中,
第一个是用历史表left outer join 日期为 ${yyy-MM-dd} 的增量表,能关联上的,并且dw_end_date > ${yyy-MM-dd},说明状态有变化,则把原来的dw_end_date置为(${yyy-MM-dd} – 1),
关联不上的,说明状态无变化,dw_end_date无变化。
第二个结果集是直接将增量数据插入历史表,并将dw_end_date设为9999-12-31​。

最后把临时表中数据插入历史表:

[sql] view plain copy

派生到我的代码片
派生到我的代码片

INSERT overwrite TABLE t_dw_orders_his
SELECT * FROM t_dw_orders_his_tmp;

五. 同上面的步骤一样,增量抽取历史数据并计算生成时间拉链结果表
再看将2015-08-23的增量数据刷新到历史表:

[sql] view plain copy

派生到我的代码片
派生到我的代码片

insert overwrite table t_ods_orders_inc partition (day = '2015-08-23')
select orderid,createtime,modifiedtime,status
from orders
where modifiedtime = '2015-08-23';

drop table if exists t_dw_orders_his_tmp;
create table t_dw_orders_his_tmp as
select oo.orderid,
oo.createtime,
oo.modifiedtime,
oo.status,
oo.dw_start_date,
oo.dw_end_date
from (select
tt.orderid,
tt.createtime,
tt.modifiedtime,
tt.status,
tt.dw_start_date,
tt.dw_end_date,
row_number() over(distribute by tt.orderid,tt.createtime,tt.modifiedtime,status sort by tt.dw_end_date desc) rn
from (
select a.orderid,
a.createtime,
a.modifiedtime,
a.status,
a.dw_start_date,
-- 2015-08-20保存的都是历史数据
case when b.orderid is not null and a.dw_end_date > '2015-08-23' then '2015-08-22'
else a.dw_end_date end as dw_end_date
from t_dw_orders_his a
left outer join (select * from t_ods_orders_inc where day = '2015-08-23') b
on (a.orderid = b.orderid)

union all   

select orderid,  
       createtime,  
       modifiedtime,  
       status,  
       modifiedtime as dw_start_date,  
       '9999-12-31' as dw_end_date   
  from t_ods_orders_inc   
where day = '2015-08-23') tt   

) oo where oo.rn =1;

insert overwrite table t_dw_orders_his
select * from t_dw_orders_his_tmp;

六. 查看上面步骤生成的时间拉链结果表
按照上面的方法刷新完后,生成的时间拉链的历史表数据如下:
1 2015-08-18 2015-08-18 创建 2015-08-182015-08-211 2015-08-18 2015-08-22 支付 2015-08-222015-08-221 2015-08-18 2015-08-23 完成 2015-08-239999-12-312 2015-08-18 2015-08-18 创建 2015-08-182015-08-212 2015-08-18 2015-08-22 完成 2015-08-229999-12-313 2015-08-19 2015-08-21 支付 2015-08-192015-08-223 2015-08-19 2015-08-23 完成 2015-08-239999-12-314 2015-08-19 2015-08-21 完成 2015-08-199999-12-315 2015-08-19 2015-08-20 支付 2015-08-192015-08-225 2015-08-19 2015-08-23 完成 2015-08-239999-12-316 2015-08-20 2015-08-20 创建 2015-08-202015-08-216 2015-08-20 2015-08-22 支付 2015-08-229999-12-317 2015-08-20 2015-08-21 支付 2015-08-209999-12-318 2015-08-21 2015-08-21 创建 2015-08-21 2015-08-218 2015-08-21 2015-08-22 支付 2015-08-22 2015-08-228 2015-08-21 2015-08-23 完成 2015-08-23 9999-12-319 2015-08-22 2015-08-22 创建 2015-08-229999-12-3110 2015-08-22 2015-08-22 支付 2015-08-229999-12-3111 2015-08-23 2015-08-23 创建 2015-08-239999-12-3112 2015-08-23 2015-08-23 创建 2015-08-239999-12-3113 2015-08-23 2015-08-23 支付 2015-08-239999-12-31

比如我们查看订单8, 可以发现订单8从2015-08-21-2015-08-23号,状态变化了三次(创建->支付->完成),因此历史表中有三条记录。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容