在现在的大数据场景下,大部分的公司都会选择以Hdfs和Hive为主的数据仓库架构。目前的Hdfs版本来讲,其文件系统中的文件是不能做改变的,也就是说Hive的只能进行删除和添加操作,而不能进行update。基于这个前提,我们来实现拉链表。
1 数据介绍
以一张订单表为例,如下是原始数据,每天的订单状态明细,放到order.txt中:
根据拉链表我们希望得到的是:
2 实现步骤
拉链表整体实现过程一般分为三步:
先增量采集所有新增数据【增加的数据和发生变化的数据】放入一张增量表。
创建一张临时表,用于将老的拉链表与增量表进行合并。
最后将临时表的数据覆盖写入拉链表中。
3 如何获取增量数据
可以监听Mysql数据的变化,比如说用Canal,最后合并每日的变化,获取到最后的一个状态。
假设我们每天都会获得一份切片数据,我们可以通过取两天切片数据的不同来作为每日更新表,这种情况下我们可以对所有的字段先进行concat,再取md5,这样就ok了。
流水表!有每日的变更流水表。
4 实战
在实现它之前,我们需要先确定一下我们有哪些数据源可以用。
我们需要一张ODS层的用户全量表。至少需要用它来初始化。
每日的用户更新表。
而且我们要确定拉链表的时间粒度,比如说拉链表每天只取一个状态,也就是说如果一天有3个状态变更,我们只取最后一个状态,这种天粒度的表其实已经能解决大部分的问题了。
假设以天为维度,以每天的最后一个状态为当天的最终状态。本例只考虑到实现与性能无关。我们来看一下上面的拉链表是怎么一步步实现的。
以处理 2021-08-21 的数据为例。
4.1 初始化数据
首先,创建ods层用户全量表ods_orders,模拟MYSQL中变化的数据。
载入数据:
把2021-08-21号之前的数据写入增量表:
最后,把增量表中的数据写入拉链表(结果表):
数据初始化完毕!!!
4.2 获取增量表数据
4.3 数据写入临时表
4.4 临时表写入拉链表
处理2021-08-22 的数据:
5 如何使用拉链表
查看某一天的全量历史快照数据。
取一段时间的变化记录集合,如在2021-08-21-2021-08-22变化的记录。
查看某一订单历史变化情况。
取最新的数据。
6 补充
好了,我们分析了拉链表的原理、设计思路、并且在Hive环境下实现了一份拉链表,下面对拉链表做一些小的补充。
6.1 拉链表和流水表
流水表存放的是一个用户的变更记录,比如在一张流水表中,一天的数据中,会存放一个用户的每条修改记录,但是在拉链表中只有一条记录。
这是拉链表设计时需要注意的一个粒度问题。我们当然也可以设置的粒度更小一些,一般按天就足够。
6.2 查询性能
拉链表当然也会遇到查询性能的问题,比如说我们存放了5年的拉链数据,那么这张表势必会比较大,当查询的时候性能就比较低了,个人认为两个思路来解决:
在一些查询引擎中,我们对start_date和end_date做索引,这样能提高不少性能。
保留部分历史数据,比如说我们一张表里面存放全量的拉链表数据,然后再对外暴露一张只提供近3个月数据的拉链表。
6.3 淘汰机制
关于淘汰机制,其实和性能也是有关系的,一方面是因为所有数据的积累会导致计算越来越慢,另一方面是业务侧其实对历史数据的需求也有一定的优先级的。
因此在设计拉链表的时候可以制定一些数据的淘汰机制。淘汰的数据不一定要删除,比如我们建立两张拉链表,一张拉链表中只保存最新的十条数据,其它的数据会存入一张历史拉链表中。
6.4 心得体会
使用拉链表的时候可以不加t_end_date,即失效日期,但是加上之后,能优化很多查询。
可以加上当前行状态标识,能快速定位到当前状态。
在拉链表的设计中可以加一些内容,因为我们每天保存一个状态,如果我们在这个状态里面加一个字段,比如如当天修改次数,那么拉链表的作用就会更大。
领取专属 10元无门槛券
私享最新 技术干货