You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Hive写入Parquet分区表报错,添加LIMIT后异常消失

Hive Insert Overwrite 无LIMIT时报错,加LIMIT后正常的问题排查

最近我在处理Hive数据插入时遇到了一个奇怪的问题:执行全量Insert Overwrite语句时会抛出异常,但给查询加上LIMIT 100后就能正常运行。

问题重现

报错的执行语句:

insert overwrite table stage_dfqp.user_currency partition (dt='2018-05-16') select fuid, fbpid, fgamefsk from stage_dfqp.pb_gamecoins

添加LIMIT后正常执行的语句:

insert overwrite table stage_dfqp.user_currency partition (dt='2018-05-16') select fuid, fbpid, fgamefsk from stage_dfqp.pb_gamecoins limit 100

目标表结构信息

目标表stage_dfqp.user_currency的建表语句如下:

CREATE TABLE `stage_dfqp.user_currency`( `fuid` bigint , `coin_type` string , `coin_num` bigint ) PARTITIONED BY ( `dt` string) ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' STORED AS INPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'

可能的原因及解决方案

1. 字段映射与类型不匹配

第一眼就发现一个关键问题:目标表的字段是fuid, coin_type, coin_num,但我查询选择的是fuid, fbpid, fgamefsk。这三个字段的类型大概率和目标表的对应字段不兼容。

  • 比如fbpid如果不是字符串类型,写入coin_type(string类型)就会报错;fgamefsk如果无法转成bigint,写入coin_num也会失败。
  • 加LIMIT后可能刚好前100条数据的类型能勉强兼容,但全量数据里存在不符合要求的记录,触发了报错。

解决办法
先查询源表字段类型,再做显式类型转换:

-- 先查看源表字段类型
desc stage_dfqp.pb_gamecoins;

-- 执行插入时做类型转换,匹配目标表字段
insert overwrite table stage_dfqp.user_currency partition (dt='2018-05-16') 
select 
  fuid, 
  cast(fbpid as string) as coin_type, 
  cast(fgamefsk as bigint) as coin_num 
from stage_dfqp.pb_gamecoins;

2. 源表存在脏数据

源表中可能存在空值、格式错误或者不符合目标表类型的数据,全量扫描时这些脏数据会触发Parquet SerDe的解析失败,而LIMIT 100刚好没扫到这些问题数据。

解决办法
先校验源表数据,定位脏数据:

-- 检查字段是否为空
select count(*) from stage_dfqp.pb_gamecoins where fuid is null or fbpid is null or fgamefsk is null;

-- 检查fbpid能否转为string类型
select fbpid from stage_dfqp.pb_gamecoins where try_cast(fbpid as string) is null;

-- 检查fgamefsk能否转为bigint类型
select fgamefsk from stage_dfqp.pb_gamecoins where try_cast(fgamefsk as bigint) is null;

找到脏数据后进行清理(删除或修正),再执行插入操作。

3. 任务资源不足

全量插入需要的内存、CPU资源超过了Hive的默认配置,导致任务崩溃;而LIMIT后数据量小,资源需求低,所以能顺利完成。

解决办法
执行语句前调整资源参数(根据集群实际情况调整数值):

set mapreduce.map.memory.mb=4096;
set mapreduce.reduce.memory.mb=8192;
set hive.exec.dynamic.partition.mode=nonstrict;
-- 可根据数据量增加reduce数量
set mapreduce.job.reduces=10;

4. Parquet序列化问题

目标表是Parquet格式,全量写入时可能遇到大字段、特殊字符导致的序列化失败,小量数据时不会触发这类问题。

解决办法
开启Hive的类型安全检查,提前发现问题:

set hive.strict.checks.type.safety=true;

同时可以调整Parquet相关配置,优化写入:

set parquet.compression=SNAPPY;
set hive.exec.dynamic.partition=true;

内容的提问来源于stack exchange,提问作者vasili

火山引擎 最新活动