hive中拉链表

拉链表在数据量大且字段变化不频繁但需记录历史状态的场景下使用,能节省空间并满足统计需求。在数仓中通常通过begin_date和end_date字段表示记录的生命周期。本文以Hive为例,介绍了如何创建和更新拉链表,以保持订单状态的历史快照。

在有些情况下,为了保持历史的一些状态,需要用拉链表来做,这样做目的在可以保留所有状态的情况下可以节省空间。

拉链表适用于以下几种情况吧

数据量有点大,表中某些字段有变化,但是呢变化的频率也不是很高,业务需求呢又需要统计这种变化状态,每天全量一份呢,有点不太现实,

不仅浪费了存储空间,有时可能业务统计也有点麻烦,这时,拉链表的作用就提现出来了,既节省空间,又满足了需求。

一般在数仓中通过增加begin_date,en_date来表示,如下例,后两列是start_date和end_date.

1
2
3
4
5
6
7
8
9
10
1  2016-08-20  2016-08-20  创建 2016-08-20  2016-08-20
1  2016-08-20  2016-08-21  支付 2016-08-21  2016-08-21
1  2016-08-20  2016-08-22  完成 2016-08-22  9999-12-31
2  2016-08-20  2016-08-20  创建 2016-08-20  2016-08-20
2  2016-08-20  2016-08-21  完成 2016-08-21  9999-12-31
3  2016-08-20  2016-08-20  创建 2016-08-20  2016-08-21
3  2016-08-20  2016-08-22  支付 2016-08-22  9999-12-31
4  2016-08-21  2016-08-21  创建 2016-08-21  2016-08-21
4  2016-08-21  2016-08-22  支付 2016-08-22  9999-12-31
5  2016-08-22  2016-08-22  创建 2016-08-22  9999-12-31

begin_date表示该条记录的生命周期开始时间,end_date表示该条记录的生命周期结束时间;

end_date = ‘9999-12-31’表示该条记录目前处于有效状态;

如果查询当前所有有效的记录,则select * from order_his where dw_end_date = ‘9999-12-31′

如果查询2016-08-21的历史快照,则select * from order_his where begin_date <= ‘2016-08-21′ and end_date >= ‘2016-08-21’

再简单介绍一下拉链表的更新:

假设以天为维度,以每天的最后一个状态为当天的最终状态。

以一张订单表为例,如下是原始数据,每天的订单状态明细

1
2
3
4
5
6
7
8
9
10
1   2016-08-20  2016-08-20  创建
2   2016-08-20  2016-08-20  创建
3   2016-08-20  2016-08-20  创建
1   2016-08-20  2016-08-21  支付
2   2016-08-20  2016-08-21  完成
4   2016-08-21  2016-08-21  创建
1   2016-08-20  2016-08-22  完成
3   2016-08-20  2016-08-22  支付
4   2016-08-21  2016-08-22  支付
5   2016-08-22  2016-08-22  创建

根据拉链表我们希望得到的是

1
2
3
4
5
6
7
8
9
10
1  2016-08-20  2016-08-20  创建 2016-08-20  2016-08-20
1  2016-08-20  2016-08-21  支付 2016-08-21  2016-08-21
1  2016-08-20  2016-08-22  完成 2016-08-22  9999-12-31
2  2016-08-20  2016-08-20  创建 2016-08-20  2016-08-20
2  2016-08-20  2016-08-21  完成 2016-08-21  9999-12-31
3  2016-08-20  2016-08-20  创建 2016-08-20  2016-08-21
3  2016-08-20  2016-08-22  支付 2016-08-22  9999-12-31
4  2016-08-21  2016-08-21  创建 2016-08-21  2016-08-21
4  2016-08-21  2016-08-22  支付 2016-08-22  9999-12-31
5  2016-08-22  2016-08-22  创建 2016-08-22  9999-12-31

可以看出 1,2,3,4每个订单的状态都有,并且也能统计到当前的有效状态。

本例以hive为例,只考虑到实现,与性能无关

首先创建表

Hive 中更新拉链数据时,处理数据冲突可采用以下方法: ### 主键冲突处理 当新数据与历史数据的主键重复时,需要根据业务需求决定如何处理。 - **覆盖更新**:如果业务要求以最新数据为准,可直接用新数据覆盖旧数据。示例代码如下: ```sql -- 创建临时表 tmp 用于存放合并后的数据 CREATE TABLE tmp AS SELECT CASE WHEN new.id IS NOT NULL THEN new.id ELSE old.id END AS id, CASE WHEN new.name IS NOT NULL THEN new.name ELSE old.name END AS name, -- 其他字段类似处理 CASE WHEN new.start_time IS NOT NULL THEN new.start_time ELSE old.start_time END AS start_time, CASE WHEN new.end_time IS NOT NULL THEN new.end_time ELSE old.end_time END AS end_time FROM dwd.dwd_zip old FULL OUTER JOIN update new ON old.id = new.id; -- 将临时表数据覆盖到拉链中 INSERT OVERWRITE TABLE dwd.dwd_zip SELECT * FROM tmp; ``` - **保留历史记录**:若需保留历史记录,可将旧数据的 `end_time` 更新为冲突发生前一刻,新数据的 `end_time` 设为 "9999-12-31"。示例代码如下: ```sql -- 创建临时表 tmp 用于存放合并后的数据 CREATE TABLE tmp AS SELECT old.id, old.name, -- 其他字段 old.start_time, -- 将旧数据的 end_time 更新为冲突发生前一刻 '冲突发生日期' AS end_time FROM dwd.dwd_zip old JOIN update new ON old.id = new.id UNION ALL SELECT new.id, new.name, -- 其他字段 '冲突发生日期' AS start_time, '9999-12-31' AS end_time FROM update new; -- 将临时表数据覆盖到拉链中 INSERT OVERWRITE TABLE dwd.dwd_zip SELECT * FROM tmp; ``` ### 业务规则冲突处理 不同业务规则可能导致数据冲突,如数据的状态、权限等。需根据具体业务规则进行处理。 - **优先级判断**:为不同数据来源或数据类型设置优先级,当发生冲突时,优先保留优先级高的数据。示例代码如下: ```sql -- 创建临时表 tmp 用于存放合并后的数据 CREATE TABLE tmp AS SELECT CASE WHEN new.priority > old.priority THEN new.id ELSE old.id END AS id, CASE WHEN new.priority > old.priority THEN new.name ELSE old.name END AS name, -- 其他字段类似处理 CASE WHEN new.priority > old.priority THEN new.start_time ELSE old.start_time END AS start_time, CASE WHEN new.priority > old.priority THEN new.end_time ELSE old.end_time END AS end_time FROM dwd.dwd_zip old FULL OUTER JOIN update new ON old.id = new.id; -- 将临时表数据覆盖到拉链中 INSERT OVERWRITE TABLE dwd.dwd_zip SELECT * FROM tmp; ``` - **人工干预**:对于复杂的业务规则冲突,可通过人工审核的方式处理。将冲突数据标记出来,由业务人员根据实际情况决定如何处理。 ### 数据一致性冲突处理 在更新拉链数据时,可能会出现数据一致性问题,如数据的完整性、准确性等。可通过以下方法处理: - **数据校验**:在更新数据前,对新数据进行校验,确保数据的完整性和准确性。示例代码如下: ```sql -- 创建临时表 valid_update 用于存放校验通过的数据 CREATE TABLE valid_update AS SELECT * FROM update WHERE -- 校验条件,如字段不能为空等 id IS NOT NULL AND name IS NOT NULL; -- 后续处理与正常更新流程相同 ``` - **事务处理**:若 Hive 支持事务,可使用事务来保证数据的一致性。在更新数据时,将相关操作封装在一个事务中,若出现冲突,可回滚事务。但 Hive 的事务支持有一定限制,需根据实际情况使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值