Hive拉链表、快照表

本文介绍了Hive中的拉链表和快照表概念及其使用场景。拉链表用于记录事物历史变化,适用于数据仓库中需要获取特定时间点历史数据的情况。在Hive中,通过每日增量更新实现拉链表,提供了获取最新数据和历史数据的能力。快照表则是按日分区,保存截止分区日期的全量数据,但可能造成存储空间浪费。拉链表可以优化存储并提供更灵活的查询选项。

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

拉链表

  拉链表记录一个事物从开始,一直到当前状态的所有变化的信息。可以使用这张表拿到最新的当天的最新数据以及之前的历史数据。
在这里插入图片描述
拉链表的使用场景
在数据仓库的数据模型设计过程中,经常会遇到下面这种表的设计:

  1. 有一些表的数据量很大,比如一张用户表,大约10亿条记录,50个字段,这种表即使使用ORC压缩,单张表的存储也会超过100G,在HDFS使用双备份或者三备份的话就更大一些
  2. 表中的部分字段会被update更新操作,如用户联系方式,产品的描述信息,订单的状态等等
  3. 需要查看某一个时间点或者时间段的历史快照信息,比如,查看某一个订单在历史某一个时间点的状态
  4. 表中的记录变化的比例和频率不是很大,比如,总共有10亿的用户,每天新增和发生变化的有200万左右,变化的比例占的很小

针对以上表设计,拉链表满足既能获取最新的数据,也能添加筛选条件并获取历史的数据的要求。

在Hive中实现拉链表
  目前Hive的表只能进行删除和添加操作,而不能进行update。基于这个前提,我们来实现拉链表。在实现拉链表之前,需要先确定一下有哪些数据源可以用:
1、需要一张ODS层的用户全量表,需要用它来初始化
2、每日的用户更新表

而且还需要确定拉链表的时间粒度,比如说拉链表每天只取一个状态,也就是说如果一天有3个状态变更只取最后一个状态,这种天粒度的表其实已经能解决大部分的问题了。
  另外,对于每日的用户更新表该怎么获取,有以下方式拿到或者间接拿到每日的用户增量:

  1. 可以监听Mysql数据的变化,比如说用Canal,最后合并每日的变化,获取到最后的一个状态
  2. 假设每天都会获得一份切片数据,可以通过取两天切片数据的不同来作为每日更新表,这种情况下可以对所有的字段先进行concat,再取md5
  3. 流水表,有每日的变更流水表
  4. 通过etl工具对操作型数据库按照时间字段增量抽取到ods或者数据仓库(每天抽取前一天的数据),形成每天的增量数据(实际中使用最多的情形)。

拉链表实现方式一:
ods层的user表
ods层的用户资料切片表的结构:

CREATE EXTERNAL TABLE ods.user ( 
  user_num STRING COMMENT '用户编号', 
  mobile STRING COMMENT '手机号码', 
  reg_date STRING COMMENT '注册日期' 
COMMENT '用户资料表' 
PARTITIONED BY (dt string) 
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' 
STORED AS ORC 
LOCATION '/ods/user'; 
) 

### Hive拉链的创建与使用 #### 什么是拉链拉链是一种常见的数据仓库设计模式,用于记录历史变更情况并保留每条记录的有效时间段。它通常包含两个时间字段:`start_date` `end_date`,分别示某一条记录生效的时间范围。 在Hive中实现拉链的核心在于通过ETL过程更新现有数据集,并维护每条记录的历史版本及其有效时间区间[^1]。 --- #### 创建拉链的基本结构 假设我们需要为一张订单 (`orders`) 构建拉链,以下是其基本结构: ```sql CREATE TABLE zipper_orders ( orderid INT, createdate STRING, modifiedtime STRING, status STRING, start_date TIMESTAMP, -- 记录生效的起始时间 end_date TIMESTAMP -- 记录失效的结束时间,默认值为 '9999-12-31' ); ``` 上述的设计中,`start_date` 示该记录何时开始生效,而 `end_date` 则标记记录何时停止生效。对于当前有效的记录,`end_date` 的默认值可以设置为 `'9999-12-31'` 或其他远期日期[^4]。 --- #### 数据加载与初始化 首次加载数据时,需将原始数据转换为初始状态下的拉链形式。例如,给定以下原始数据文件 `orders.txt`[^2]: | orderid | createdate | modifiedtime | status | |---------|------------|--------------|--------| | 1 | 2023-01-01 | NULL | OPEN | | 2 | 2023-01-02 | NULL | CLOSED | 将其转化为拉链的形式: ```sql INSERT INTO zipper_orders SELECT orderid, createdate, modifiedtime, status, CAST(createdate AS TIMESTAMP) AS start_date, -- 设置生效时间为createdate TO_DATE('9999-12-31', 'yyyy-MM-dd') AS end_date -- 默认失效时间为远期 FROM orders; ``` 此时,`zipper_orders` 中存储的是所有记录的初始状态。 --- #### 更新拉链逻辑 当有新的业务数据到达时,需要对比旧数据新数据,识别新增、删除以及修改的操作,并相应调整拉链的内容。具体流程如下: 1. **构建临时** 将最新的业务数据存入临时 `tmp_zipper` 中。此应具有相同的列结构作为目标拉链。 2. **处理新增记录** 对于那些存在于最新数据集中但不在拉链中的记录,直接插入到拉链中。 ```sql INSERT INTO zipper_orders SELECT t.orderid, t.createdate, t.modifiedtime, t.status, CURRENT_TIMESTAMP AS start_date, TO_DATE('9999-12-31', 'yyyy-MM-dd') AS end_date FROM tmp_zipper t LEFT JOIN zipper_orders z ON t.orderid = z.orderid AND z.end_date = '9999-12-31' WHERE z.orderid IS NULL; ``` 3. **处理已更改记录** 如果某些记录的状态发生了变化,则需要先关闭这些记录的老版本(即将它们的 `end_date` 修改为当前时间),再插入对应的新版本。 关闭老版本: ```sql UPDATE zipper_orders SET end_date = DATE_SUB(CURRENT_DATE, INTERVAL 1 DAY) WHERE orderid IN (SELECT DISTINCT orderid FROM tmp_zipper) AND end_date = '9999-12-31'; ``` 插入新版本: ```sql INSERT INTO zipper_orders SELECT t.orderid, t.createdate, t.modifiedtime, t.status, CURRENT_TIMESTAMP AS start_date, TO_DATE('9999-12-31', 'yyyy-MM-dd') AS end_date FROM tmp_zipper t; ``` 4. **清理冗余数据**(可选) 删除不再存在的记录或标记其终止时间。 --- #### 查询拉链 查询当前有效的记录可以通过过滤条件来完成: ```sql SELECT * FROM zipper_orders WHERE end_date = '9999-12-31'; ``` 如果需要查看某个特定时间点的历史快照,也可以加入额外的时间约束: ```sql WITH history_snapshot AS ( SELECT *, ROW_NUMBER() OVER (PARTITION BY orderid ORDER BY start_date DESC) AS rn FROM zipper_orders WHERE start_date <= '指定时间' AND ('指定时间' < end_date OR end_date = '9999-12-31') ) SELECT * FROM history_snapshot WHERE rn = 1; ``` --- ### 总结 以上展示了如何在Hive中创建操作拉链的过程,包括结构调整、数据初始化、增量更新及高效查询等多个方面。这种技术广泛应用于金融、电商等领域,能够帮助分析人员更好地理解数据随时间的变化趋势[^3]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值