拉链表(hive)

 

目录

1、什么是拉链表

2、拉链表是怎么存储的

3、Hive中拉链表的存储过程


1、什么是拉链表

拉链表是我们存储数据时为了处理某些情况而设计的一种表结构,是一种存储数据的方法。

在数据仓库的数据模型设计过程中,经常会遇到下面这种表的设计:

    1.有一些表的数据量很大,比如一张用户表,大约10亿条记录,50个字段,这种表,即使使用ORC压缩,单张表的存储也会超过100G,在HDFS使用双备份或者三备份的话就更大一些。 

            2.表中的部分字段会被update更新操作,如用户联系方式,产品的描述信息,订单的状态等等。 应用时需要查看某一个时间点或者时间段的历史快照信息,比如,查看某一个订单在历史某一个时间点的状态。 

            3.表中的记录变化的比例和频率不是很大,比如,总共有10亿的用户,每天新增和发生变化的有200万左右,变化的比例占的很小。 

这种情况下,我们如果每天保存一份全量数据,但是数据量很大,每天都抽一份全量数据,再有钱的公司可能也支付不起数据库的费用,而且表中记录变化的比例和频率都不是很大,全量抽取数据库中会有大量的重复数据,没有意义;我们如果每天先drop掉前一天的数据,再重新抽取一份新的,这样解决了物理存储费用的问题,但是这样不能查看某一个订单在历史某一个时间点的状态,不能满足业务需求;所以我们需要是当数据发生变化时仅对该数据进行记录并修改的,可以存储历史数据的存储方法。有人就设计出了拉链表。

为了更直观的感受拉链表,请仔细观察下面表的变化,注意start_dt和end_dt是拉链表的精髓

开始的时候

UserID

UserName

Height

start_dt

end_dt

000000001

张三

176

2015-05-14

2999-12-31

000000002

李四

170

2015-05-14

2999-12-31

UserID为000000001的这条数据的Height字段发生变化

UserID

UserName

Height

start_dt

end_dt

000000001

张三

176

2015-05-14

2016-07-24

000000001

张三

180

2016-07-24

2999-12-31

000000002

李四

170

2015-05-14

2999-12-31

UserID为000000001的这条数据的UserName字段发生变化

UserID

UserName

Height

start_dt

end_dt

000000001

张三

176

2015-05-14

2016-07-24

000000001

张三

180

2016-07-24

2018-10-13

000000001

SanZhang

180

2018-10-13

2999-12-31

000000002

李四

170

2015-05-14

2999-12-31

应该都能感受的到,start_dt和end_dt字段,在数据发生变化的时候就像一条拉链,所以都叫它拉链表。

2、拉链表是怎么存储的

其实明白了什么是拉链表,它的存储就非常简单。

首先,我们要和前一日的数据进行对比,看看哪一条数据发生了变化,我们要看看它是增加了新的数据?修改了数据,还是删除了数据。

如果是新增的数据,我们仅需要像新建拉链表时一样,给数据添加一个开始时间和结束时间,并将数据插入拉链表。开始时间就是新增数据当天,结束时间一般都是2999-12-31(有的公司觉得2999-12-31不够久,用9999-12-31,其实都是一样的);

如果是修改的数据,我们除了需要像上面将新数据插入拉链表,还需要找到该数据对应的历史数据,因为历史数据的结束日期还是2999-12-31呢,我们要把它改成修改数据当天的日期;

如果时删除了数据,那么这个数据在删除当天就无效了,我们仅仅需要将结束日期改成删除当天即可。

一般的,我们把插入数据的的动作叫做开链,把修改结束日期的动作叫做关链

3、Hive中拉链表的存储过程

由于Hive的特点是批量处理数据,在HQL中,通常不使用Update对数据进行修改。

所以我们在Hive上建拉链表,写的HQL和SQL还是有一定的差别的,由于2只是说了个思路,所以这里我说的详细点 。

假设我现在又两个表,ods_source和dw_target,我要将数据从ods_source表存储到dw_target表。

第一步,我们将ods_source和dw_target的非历史数据进行对比,得到新增的数据和修改的数据,并进行开链,存在一个临时表中。

create table if not exists tmp_increment as

  select *,hash(a.*) as hashcode,date'2018-10-13' as strat_dt,date'2999-12-31' as end_dt

  from osd_source a

  left join dw_target b 
         on a.主键=b.主键 
        and b.end_dt=date'2999-12-31'
        and hash(a.*)=b.hashcode

  where b.其它字段 is null

其中hashcode是为了比出修改的数据,如果不懂请自行解决,我就不再细说了。

第二步,我们将第一步中修改的数据进行关链,存在一个临时表中。

create table if not exists tmp_update as

  select *,hash(*) as hashcode,strat_dt,date'2018-10-13' as end_dt

  from tmp_increment a

  inner join dw_target b on a.主键=b.主键 and b.end_dt=date'2999-12-31'

第三步,我们ods_source和dw_target的非历史数据进行对比,得到ods_source表中删除的数据,或者是失效的数据,并进行关链,存在一个临时表。

create table if not exists tmp_delete as

  select *,hash(*) as hashcode,strat_dt,date'2999-12-31' as end_dt

  from dw_target a

  left join osd_source b on a.主键=b.主键 and a.end_dt=date'2999-12-31'

  where b.其它字段 is null

第四步,我们将ods_source和dw_target的非历史数据进行对比,得到没有变化的数据,存在一个临时表。

create table if not exists tmp_nochang as

select *,hash(*) as hashcode,date'2018-10-13' as strat_dt,date'2999-12-31' as end_dt

  from osd_source a

  left join dw_target b on a.主键=b.主键 and b.end_dt=date'2999-12-31'

  where b.其它字段 is not null

第五步,我们找出dw_target表中的历史数据,存在一个临时表。

create table if not exists tmp_history as

select * from dw_target where end_dt <> date'2999-12-31'

第六步,我们将前五步的临时表合在一起,形成一个新的拉链表,并drop掉临时表和原来的拉链表,这就是Hive中拉链表的做法。

 

以上都是本人自己整理的,如果有错误,请私信我或者在下面评论指出,谢谢!!!

 

你可能感兴趣的:(拉链表(hive))