需要存储历史数据时使用场景:
- 有一些表的数据量很大,比如一张用户表,大约10亿条记录,50个字段,这种表,即使使用ORC压缩,单张表的存储也会超过100G,在HDFS使用双备份或者三备份的话就更大一些。
- 表中的部分字段会被update更新操作,如用户联系方式,产品的描述信息,订单的状态等等。
- 需要查看某一个时间点或者时间段的历史快照信息,比如,查看某一个订单在历史某一个时间点的状态。
- 表中的记录变化的比例和频率不是很大,比如,总共有10亿的用户,每天新增和发生变化的有200万左右,变化的比例占的很小。
针对上述场景的解决方案:
- 方案一:每天只留最新的一份,比如我们每天用Sqoop抽取最新的一份全量数据到Hive中。
- 方案二:每天保留一份全量的切片数据。
- 方案三:使用拉链表。
各种方案及可行性分析:
- 方案一:每天只留最新的一份,比如我们每天用Sqoop抽取最新的一份全量数据到Hive中。
实现方式:实现起来很简单,每天drop掉前一天的数据,重新抽一份最新的。
优点:节省空间,使用方便,不用在选择表的时候加一个时间分区什么的。
缺点:没有历史数据,要想翻旧账只能通过其它方式,比如从流水表里面抽。 - 方案二:每天保留一份全量的切片数据。
实现方式:每天一份全量的切片是一种比较稳妥的方案,而且历史数据也在。(类似于针对每天固定时间点的全量备份) - 方案三:使用拉链表。
拉链表在使用上基本兼顾了我们的需求。
首先它在空间上做了一个取舍,虽说不像方案一那样占用量那么小,但是它每日的增量可能只有方案二的千分之一甚至是万分之一。
其实它能满足方案二所能满足的需求,既能获取最新的数据,也能添加筛选条件也获取历史的数据。
所以我们还是很有必要来使用拉链表的。
下面将详尽解析如何创建拉链表
下面我们来举个栗子详细看一下拉链表。
我们先看一下在ORACLE数据库里的U_USER表中的一张历史表。
DROP TABLE U_USER; CREATE TABLE U_USER( U_DATE VARCHAR2(10), U_ID VARCHAR2(10), U_PHONE VARCHAR2(10) ); --- 插入 2017-01-01 初始状态的第一批数据 INSERT INTO U_USER VALUES('2017-01-01','001','11111'); INSERT INTO U_USER VALUES('2017-01-01','002','22222'); INSERT INTO U_USER VALUES('2017-01-01','003','33333'); INSERT INTO U_USER VALUES('2017-01-01','004','44444'); COMMIT;
执行以上语句后,可得在2017-01-01这一天表中的数据为下图所示: