【Hive】使用临时表保留全量数据

本文探讨在Hive环境中如何利用临时表保留全量数据。针对a全量表和b增量表,提出两种方案:一是通过左外关联筛选a表独有数据并合并;二是合并a、b表后,利用row_number()分析函数去重保留最新数据。在数据量较小的情况下,比较两种方案的优劣。

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

hive使用临时表保留全量数据

需求:
在hive环境下,a表为全量表,b表为增量表(只有当天跑的数据),

假设需要将a表中有的但b表中没有的数据仍然保留在a表,

而且需要将b表中有的但a表中没有的数据追加到a表


方案一:
使用左外关联先将a表中有的数据但b表中没有的数据过滤出来,
然后再将b表的数据与过滤出来的数据合并
---------------------创建数据(在oracle演示)

--查询b表在a表的信息
with a as(
select 1 as id, 'Lisi' as name ,'2019-10-01' as time from dual
union all
select 2 as id, 'Wangmen' as name,'2019-10-01' as time from dual
union all
select 3 as id, 'Zhaoliu' as name,'2019-10-01' as time from dual
union all
select 4 as id, 'Pangsan' as name,'2019-10-01' as time from dual
),
b as(
select 1 as id, 'Lisi' as name,'2019-10-03' as time from dual
union all
select 2 as id, 'Wangmen' as name,'2019-10-03' as time from dual
union all
select 5 as id, 'Huangsan' as name,'2019-10-03' as time from dual
)

--使用连接
select a.id, a.name,a.time
 
<think>Hive本身不支持行级别的插入、更新和删除操作(由引用[1]解释),但支持通过INSERT语句批量插入数据。在插入数据前检查是否存在重复数据以避免重复插入,是数据仓库中常见的需求。以下是几种在Hive实现避免重复插入的方法: ### 方法1:使用`INSERT OVERWRITE` + 去重查询(推荐) 通过重新写入整个分区或,并在写入前进行去重,可以避免重复。这种方法适合每天全量覆盖的场景。 ```sql INSERT OVERWRITE TABLE target_table SELECT * FROM ( -- 合并旧数据和新数据,然后去重 SELECT * FROM target_table -- 已存在的数据 UNION ALL SELECT * FROM new_data -- 待插入的新数据 ) combined QUALIFY ROW_NUMBER() OVER (PARTITION BY key_column ORDER BY update_time DESC) = 1; ``` **说明**: - 使用`UNION ALL`合并旧数据和新数据 - 通过`ROW_NUMBER()`按时间戳降序排列,保留最新记录 - `OVERWRITE`会覆盖原有数据,确保无重复 > 此方法适合分区,可结合`PARTITION`子句使用[^1]。 ### 方法2:使用`LEFT ANTI JOIN`检查不存在的数据(增量插入) 若需要增量插入,可在插入前用`LEFT ANTI JOIN`过滤掉已存在的记录: ```sql INSERT INTO TABLE target_table SELECT n.* FROM new_data n LEFT ANTI JOIN target_table t ON n.key_column = t.key_column; ``` **优势**: - 直接排除已存在的键值 - 执行效率较高(尤其当`key_column`有索引时) ### 方法3:创建临时表去重后插入 适用于需要复杂去重逻辑的场景: ```sql -- 创建临时表存放去重后的新数据 CREATE TEMPORARY TABLE deduped_new_data AS SELECT * FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY key_column ORDER BY update_time DESC) AS rn FROM new_data ) WHERE rn = 1; -- 插入到目标(排除已存在键值) INSERT INTO TABLE target_table SELECT d.* FROM deduped_new_data d WHERE NOT EXISTS ( SELECT 1 FROM target_table t WHERE d.key_column = t.key_column ); ``` --- ### 注意事项 1. **Hive事务支持** Hive从0.14版本开始支持事务(需为分桶且存储格式为ORC),可通过`INSERT INTO`实现增量插入,但需开启配置: ```sql SET hive.support.concurrency=true; SET hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager; ``` 2. **性能优化** - 对大使用`LEFT ANTI JOIN`时,确保`key_column`是分桶字段或分区字段 - 启用向量化查询:`SET hive.vectorized.execution.enabled=true;` 3. **替代方案** 若数据量极大,考虑使用Spark SQL替代Hive执行去重插入,性能可提升数倍。 --- ### 示例:分区场景 假设目标按`dt`分区,插入新分区数据时去重: ```sql INSERT OVERWRITE TABLE target_table PARTITION (dt='2023-10-01') SELECT * FROM ( SELECT * FROM target_table WHERE dt='2023-10-01' -- 原有分区数据 UNION ALL SELECT * FROM new_data -- 新增数据 ) tmp QUALIFY ROW_NUMBER() OVER (PARTITION BY id ORDER BY update_time DESC) = 1; ``` > 引用[2]指出Hive在读时检查模式,因此插入时无需预先检查字段类型[^2]。 §§相关问题§§ 1. Hive中如何更新已有数据记录? 2. 如何提高Hive的`LEFT ANTI JOIN`查询性能? 3. Hive事务使用限制有哪些?</think>在 Hive实现插入数据前检查是否存在以避免重复插入,需要结合 Hive 的特性来设计解决方案。由于 Hive 不支持行级别的更新和删除操作(如引用[1]所述),我们需要采用批量处理的方式来实现去重插入。以下是几种有效的实现方法: --- ### 方法一:使用 `INSERT OVERWRITE` + 去重查询(推荐) 这是最高效的去重插入方式,特别适合全量数据更新: ```sql INSERT OVERWRITE TABLE target_table SELECT * FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY unique_key ORDER BY update_time DESC) AS rn FROM ( SELECT * FROM target_table -- 原有数据 UNION ALL SELECT * FROM new_data -- 新增数据 ) combined ) ranked WHERE rn = 1; ``` **原理**: 1. 使用 `UNION ALL` 合并旧数据和新数据 2. 通过 `ROW_NUMBER()` 窗口函数按唯一键分组并排序 3. 只保留每个键的最新记录(`rn=1`) 4. 用 `OVERWRITE` 覆盖整个 > 优势:完全避免重复,且能保留最新数据[^1] --- ### 方法二:使用 `LEFT ANTI JOIN` 过滤已存在数据 适合增量插入场景: ```sql INSERT INTO TABLE target_table SELECT n.* FROM new_data n LEFT ANTI JOIN target_table t ON n.unique_key = t.unique_key; ``` **说明**: - `LEFT ANTI JOIN` 会返回**只存在于左**(新数据)但**不存在于右**(目标)的记录 - 确保 `unique_key` 是能唯一标识记录的字段(如ID、组合键) --- ### 方法三:分区 + 动态分区插入 针对分区的优化方案(按日期分区示例): ```sql INSERT OVERWRITE TABLE target_table PARTITION (dt) SELECT *, dt -- 分区字段必须放在最后 FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY unique_key, dt ORDER BY update_time DESC) AS rn FROM new_data ) tmp WHERE rn = 1; ``` --- ### 注意事项 1. **性能优化**: - 对 `unique_key` 创建索引(Hive 3.0+ 支持) ```sql CREATE INDEX idx_key ON TABLE target_table(unique_key) AS 'COMPACT' WITH DEFERRED REBUILD; ``` - 启用向量化查询(提升JOIN性能) ```sql SET hive.vectorized.execution.enabled = true; ``` 2. **事务支持**(Hive 0.14+): 需满足以下条件: - 必须是分桶(`CLUSTERED BY`) - 存储格式为 ORC - 启用事务配置: ```sql SET hive.support.concurrency=true; SET hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager; ``` 3. **替代方案**: - 使用 **Spark SQL**:如果性能要求高,可切换到 Spark 执行去重插入 - 使用 **HBase**:需要强一致性检查时考虑(如引用[2]对比) --- ### 完整示例流程 ```sql -- 步骤1: 创建接收新数据临时表 CREATE TEMPORARY TABLE new_data_temp AS SELECT * FROM source_table WHERE dt='2023-10-01'; -- 步骤2: 去重插入(使用窗口函数) INSERT OVERWRITE TABLE target_table SELECT col1, col2, unique_key, update_time FROM ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY unique_key ORDER BY update_time DESC ) AS rn FROM ( SELECT * FROM target_table -- 原有数据 UNION ALL SELECT * FROM new_data_temp -- 新增数据 ) combined ) ranked WHERE rn = 1; ``` > 引用[2]指出Hive在读时检查字段的特性,因此插入前无需预先检查字段类型[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值