Hive分区表指定日期范围重复数据删除报错求助
问题分析与解决方案
核心问题修正:SQL条件逻辑错误
你当前执行的SQL中,WHERE条件写了两个dt >=,这会导致实际只筛选出dt >= '2023-07-10'的分区,完全不符合处理2023-03-26至2023-07-10数据的需求,这也是日志中出现dt=2023-07-11分区的原因。
修正后的基础SQL
set hive.exec.dynamic.partition.mode=nonstrict; INSERT OVERWRITE TABLE db.table_name PARTITION(dt) select distinct * from db.table_name where dt >= '2023-03-26' AND dt <= '2023-07-10';
警告问题处理
1. CombineHiveRecordReader多分区警告
这个警告是Hive 2.3.3中LLAP IO读取多分区时的兼容性提示,不会导致任务失败,若要消除它,可添加以下参数:
set hive.llap.io.allowed.partition.specs=true;
添加后完整SQL:
set hive.exec.dynamic.partition.mode=nonstrict; set hive.llap.io.allowed.partition.specs=true; INSERT OVERWRITE TABLE db.table_name PARTITION(dt) select distinct * from db.table_name where dt >= '2023-03-26' AND dt <= '2023-07-10';
2. mapreduce.Counters过时警告
这个警告仅提示旧Counter类已废弃,不影响任务执行,若要抑制该警告,可添加:
set mapreduce.job.counters.group.name=org.apache.hadoop.mapreduce.TaskCounter;
更高效的去重方案(推荐)
select distinct *在大表场景下效率偏低,推荐用row_number()窗口函数按业务主键分区,保留最新/最早数据,示例如下(假设业务主键为id, order_no,按dt分区,保留最新一条):
set hive.exec.dynamic.partition.mode=nonstrict; set hive.llap.io.allowed.partition.specs=true; set mapreduce.job.counters.group.name=org.apache.hadoop.mapreduce.TaskCounter; INSERT OVERWRITE TABLE db.table_name PARTITION(dt) select col1, col2, col3, dt -- 明确列出所有字段,避免*带来的分区字段重复问题 from ( select *, row_number() over(partition by id, order_no, dt order by create_time desc) as rn from db.table_name where dt >= '2023-03-26' AND dt <= '2023-07-10' ) t where rn = 1;
注:需将
id, order_no替换为实际业务主键,create_time替换为判断数据新旧的字段,无需按时间筛选可省略order by部分。
额外注意事项
- 执行覆盖写入前,建议先备份目标分区数据,避免数据丢失。
- 若表数据量极大,可分批次处理单个分区,避免一次性处理过多数据导致任务失败。
内容的提问来源于stack exchange,提问作者hive hadoop
相关产品推荐
相关产品推荐

