hive上一种通用的拉链记历史方法

本文介绍了一种在数据仓库中记录历史数据的拉链表方法,并详细解释了如何通过分区和代码复用来提高下游任务的效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据仓库中针对历史数据的记录方法一般有3种方法
1.保存最新记录,用最新数据计算历史数据
2.快照,针对每天保留全量数据
3.拉链记历史,每天针对变化的数据记录其生命周期
上面3种各有优势,主要体现的存储空间占用、下游任务使用成本、是否能回溯历史,整体上是不同应用场景下要有不同选择。
针对拉链记历史一种通用的方法是对每条数据记录下生命周期begin_date,end_date;这咱在日常工作中最常用。在这种情况下
就要考虑两个点。一是数据由于同一条记录在整个生命周期有可能存在多条,如何存储能保证下游的使用方便和利用成本最低;
二是当这种需求多时,如何利用统一的代码来把这种需求归一;不是重复性的代码。
针对上面这两点考虑,我们在生产环境中设计思路如下
1.采用生命周期来分区,这样能有效利用数据库的分区裁剪功能,提高下游利用效率;这是就要考虑分区字段的选择,一般情况
是按天(end_date,begin_date)这样二级分区,这样利用效率最高。这里注意一定要把end_date放前面,原因是你使用时,一般
是取某一天的记录,就是end_date>某天。这里考虑到按天分区,虽然效率高,但是造成子分区过多,整个的数据碎片化严重,而且
在ODPS上导致的子目录过多,这里分区字段归化到月
2.考虑代码通用性,这里把源表名、delta表名、日期作为参数,然后读取元数据,来拼接SQL;再调用接口执行。保持了代码的封装。

一个ODPS的事例代码.注意顺序不可改
1.取有变更的记录,把end_date 换成当天,分区字段归一到当月

insert into table wcq_lc_wjs_claim_reserve_dev partition(pt1_end_month,pt2_begin_month)
select
 a.id                    
,a.reserve_type          
,a.outstanding_amount    
,a.settled_amount        
,a.remark                
,a.operator              
,a.op_date               
,a.claim_id              
,a.policy_id             
,a.is_deleted            
,a.gmt_created           
,a.creator               
,a.gmt_modified          
,a.modifier              
,a.begin_date         
,a.end_date
,TO_CHAR(DATETRUNC(DATEADD(TO_DATE('${bizdate}','yyyymmdd'),-1,'dd'),'MM'),'yyyymmdd000000')  pt1_end_month
,TO_CHAR(DATETRUNC(a.begin_date,'MM'),'yyyymmdd000000')          pt2_begin_month
from (
select 
 ,b.id                         
 ,b.reserve_type                 
 ,b.outstanding_amount           
 ,b.settled_amount               
 ,b.remark                       
 ,b.operator                     
 ,b.op_date                      
 ,b.claim_id                     
 ,b.policy_id                    
 ,b.is_deleted                   
 ,b.gmt_created                  
 ,b.creator                      
 ,b.gmt_modified                 
 ,b.modifier                     
 ,b.begin_date                   
 ,DATEADD(TO_DATE('${bizdate}','yyyymmdd'),-1,'dd')  end_date                     
from (select * from wcq_ods_wjs_claim_reserve_delta where pt='${bizdate}000000') a 
join (select * from wcq_lc_wjs_claim_reserve where pt1_end_month='30001201000000' ) b on (a.id=b.id)
)a
left outer join  (select * from wcq_lc_wjs_claim_reserve where pt1_end_month=TO_CHAR(DATETRUNC(DATEADD(TO_DATE('${bizdate}','yyyymmdd'),-1,'dd'),'MM'),'yyyymmdd000000')) b on (a.id=b.id)
where b.id is null;

2.把新增、变化的数据begin_date,改成当天。别的不改

insert overwrite table wcq_lc_wjs_claim_reserve_dev partition(pt1_end_month='30001201000000',pt2_begin_month='19000101000000')
select 
  case when  a.id  is not null then a.id                 else b.id                 end as id                            
 ,case when  a.id  is not null then a.reserve_type       else b.reserve_type       end as reserve_type                  
 ,case when  a.id  is not null then a.outstanding_amount else b.outstanding_amount end as outstanding_amount            
 ,case when  a.id  is not null then a.settled_amount     else b.settled_amount     end as settled_amount                
 ,case when  a.id  is not null then a.remark             else b.remark             end as remark                        
 ,case when  a.id  is not null then a.operator           else b.operator           end as operator                      
 ,case when  a.id  is not null then a.op_date            else b.op_date            end as op_date                     
 ,case when  a.id  is not null then a.claim_id           else b.claim_id           end as claim_id                      
 ,case when  a.id  is not null then a.policy_id          else b.policy_id          end as policy_id                     
 ,case when  a.id  is not null then a.is_deleted         else b.is_deleted         end as is_deleted                    
 ,case when  a.id  is not null then a.gmt_created        else b.gmt_created        end as gmt_created                 
 ,case when  a.id  is not null then a.creator            else b.creator            end as creator                       
 ,case when  a.id  is not null then a.gmt_modified       else b.gmt_modified       end as gmt_modified                
 ,case when  a.id  is not null then a.modifier           else b.modifier           end as modifier 
 ,case when  a.id  is not null then to_date('${bizdate}','yyyymmdd')  else b.begin_date    end as begin_date  
 ,case when  a.id  is not null then to_date('30001231','yyyymmdd')    else b.end_date      end as end_date

from (select * from wcq_ods_wjs_claim_reserve_delta where pt='${bizdate}000000') a 
full outer join (select * from wcq_lc_wjs_claim_reserve where pt1_end_month='30001201000000' and end_date>='${bizdate}' and begin_date<='${bizdate}') b on (a.id=b.id)
;

最后,如何使用

select * from wcq_lc_wjs_claim_reserve_dev 
   where pt1_end_month>=to_char(to_date('${bizdate}','yyyymmdd'),'yyyymm01000000') 
     and pt2_begin_month<=to_char(to_date('${bizdate}','yyyymmdd'),'yyyymm01000000') 
     and begin_date<=to_date('${bizdate}','yyyymmdd')
     and end_date>=to_date('${bizdate}','yyyymmdd')
     ;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值