一、union all 丢失数据问题
问题描述:(a union all b)两段sql单独执行都有数据,但是union all之后无数据或者少数据
其他:a&b均为从orc格式的表中取数,且执行计划explain显示无reduce算子
一般出现在orc格式的表union all中。a/b 表是Parquet/ORC格式,Schema演化(如新增/删除字段)导致合并时Schema不兼容,数据被丢弃。
解决方案:
1.set hive.optimize.index.filter=false;–关闭自动使用索引,将元数据优化关掉。或者刷新元数据REFRESH TABLE a; REFRESH TABLE b;
2.创建临时表,将数据insert into到临时表,再导入目标表。

二、decimal 数据问题
1、问题描述:使用decimal设置数据格式后,数据精度丢失
现象:在这里插入图片描述
解决方案:设置为double或者小数位调大。
2、问题描述:select cast(50000000 as decimal(19,2))*46,50000000*46;
现象:结果为2300000000 ,-1994967296
解决方案:数据超长(超过int精度),需要先转数据类型再计算。在这里插入图片描述
3、问题描述:使用decimal运算导致数据不正确
现象:

	with a as (select null as taa,1.01118 as taaa,cast(1.0111 as DECIMAL(5,4)) as taaaa,2.0222 as taaaaa)
select 
nvl(taa,0)+nvl(taaa,0) as result1
,cast(nvl(taaa,0) as DECIMAL(19,5))+cast(nvl(taaaa,0) as DECIMAL(19,5)) as result2
,taaa+taaaa as result3
,nvl(taaa,0)+nvl(taaaaa,0) as result4
,nvl(taaaa,0)+nvl(taaaaa,0) as result5
,taaaa+taaaaa as result6
,nvl(taa,0)+nvl(taaa,0)+nvl(taaaa,0) as result7
,nvl(taa,0)+nvl(taaa,0)+nvl(taaaa,0)+nvl(taaaaa,0) as result8
,cast(nvl(taa,0)+nvl(taaa,0)+nvl(taaaa,0) as DECIMAL(19,4)) as result9
 from a;

在这里插入图片描述

explain
with a as (select null as taa,1.01118 as taaa,cast(1.0111 as DECIMAL(5,4)) as taaaa,2.0222 as taaaaa)
select 
nvl(taa,0)+nvl(taaa,0) as col0
,cast(nvl(taaa,0) as DECIMAL(19,5))+cast(nvl(taaaa,0) as DECIMAL(19,5)) as col1
,taaa+taaaa as col2
,nvl(taaa,0)+nvl(taaaaa,0) as col3
,nvl(taaaa,0)+nvl(taaaaa,0) as col4
,taaaa+taaaaa as col5
,nvl(taa,0)+nvl(taaa,0)+nvl(taaaa,0) as col6
,nvl(taa,0)+nvl(taaa,0)+nvl(taaaa,0)+nvl(taaaaa,0) as col7
,cast(nvl(taa,0)+nvl(taaa,0)+nvl(taaaa,0) as DECIMAL(19,4)) as col8
 from a;

在这里插入图片描述
解决方案:
1、全转decimal相加,不然会被强制转decail,如result2:两个declimal计算不会造成精度丢失,double和decimal计算可能造成精度缺失,hive中double和decimal两个类型计算会返回double,有可能造成精度缺失。应该把两个计算值都转换成decimal类型。对于decimal类型来说,计算时应尽量让乘法在除法前计算,减少中间值无法精确表示的情况。

三、向量化执行报错 参考数据库火山模型与向量化执行引擎
描述:hive使用vectorized优化报错
现象:hive日志显示

org.apache.hadoop.hive.ql.exec.vector.VectorMapOperator.process(VectorMapOperator.java:52)
hive LongColumnVector cannot be cast to org.apache.hadoop.hive.ql.exec.vector.DecimalColumnVector

Map阶段的计算(如字段转换、过滤、函数调用)时,向量式处理逻辑遇到了无法处理的情况(数据异常、类型不匹配、函数不兼容等)。
解决方案:
1.关闭向量式执行(临时规避,验证是否是向量处理的问题) 默认情况下,矢量化执行是关闭的;

set hive.vectorized.execution.enabled=false;
set hive.vectorized.execution.reduce.enabled=false;

大小表关联,默认map join,申请本地内存巨大,导致报错退出
set hive.auto.convert.join=false;

2.清洗脏数据,增加类型校验
3.单批次处理的数据量过大,或数据分区不均匀,导致向量式处理内存溢出/数组越界。

//调整向量式执行的批次大小(默认4096,减小试试)
spark.conf.set("spark.sql.execution.vectorized.batchSize","1024")
//重新分区,均衡数据分布
df.repartition(10) //根据集群资源调整分区数

不使用向量化执行可以解决vector强转报错的问题 或者将数据字段转变为对应的数据格式。 要使用向量化查询执行,hive表格式必须是orc。
在标准的查询执行系统中,每次只处理一行数据,在执行的内部循环中涉及长代码路径和重要的元数据解释,从而导致CPU使用率非常低。
向量化查询执行(Vectorized query) 是 Hive 的一项功能,每次处理数据时会将1024行数据组成一个batch进行处理简化操作,每一批数据中的每一列都会被存储为一个向量(一个原始数据类型的数组),诸如算术和比较之类的简单操作是通过在一个紧密的循环中快速迭代向量而完成的,循环内没有或只有很少的函数调用或条件分支,通过有效地使用处理器管道和高速缓存,这些循环以精简的方式进行编译,该方式使用相对较少的指令,并平均在较少的时钟周期内完成每条指令,这就极大地减少了执行过程中的方法调用、反序列化和不必要的if-else操作,大大减少典型查询操作(如扫描,过滤器,聚合和联接)的 CPU 使用率,大大减少CPU的使用时间,,显著提高执行速度。但是容易出现OOM。默认情况下,矢量化执行是关闭的。

-- 要使用向量化查询执行,必须以ORC格式存储数据
set hive.vectorized.execution.enabled = true;
-- 默认情况下,矢量化执行是关闭的;禁用向量化执行命令:
set hive.vectorized.execution.enabled = false;

四、Hive添加字段-移动字段
描述:hive增加及移动字段位置

drop table if EXISTS tmp.kgl_test ;
	create table tmp.kgl_test(
    a string ,
    b string comment 'b'
	);
	--增加字段
	alter table tmp.kgl_test add columns (c string) ;
	show create table tmp.kgl_test;
	--指定移动位置
	alter table  tmp.kgl_test change c c string comment'c'  after a ;
	show create table tmp.kgl_test;  --正常
	drop table if EXISTS tmp.kgl_tet ;
	create table tmp.kgl_tet(
    a string ,
    b string
	) STORED AS orc;
	--hive表增加字段
	alter table tmp.kgl_tet add columns (c string); --分区表建议加上CASCADE 
	alter table tmp.kgl_tet add columns(g string,h string); --一次新增多个字段
	show create table tmp.kgl_tet;
	--指定移动位置
	alter table  tmp.kgl_tet change c c string  after a ;
	show create table tmp.kgl_tet;

hive orc格式的表(事务表),使用注意事项
使用orc格式的表可以使用alter table tmp.kgl_tet add columns (c string);进行添加字段,字段会添加到末尾,查询也没有问题。但是不能调整字段的位置,执行alter table tmp.kgl_tet change c c string after a;, 报错信息如下:hive SerDe may be incompatible orc表不支持对列进行重新排序。(数据存储的复杂(base 文件,delete 文件,delta 文件)事务表不运行改列位置。)所以如果在数仓中,ods层的数据不建议使用orc格式,因为业务可能不断发生变化,业务表结构可能频繁变动。
CASCADE的作用是将表级的Schema修改同步到该表的所有分区/子表(如物化视图、分区表的分区元数据);不加CASCADE时,仅修改表的元数据Schema,分区/子表的元数据不会同步更新。
不加cascade

-- 仅修改表级元数据
ALTER TABLE tmp.kgl_tet ADD COLUMNS (c string);
-- 查看表级Schema(能看到c字段)
DESCRIBE tmp.kgl_tet;  -- 输出包含 c string
-- 查看具体分区的Schema(仍看不到c字段)
DESCRIBE tmp.kgl_tet PARTITION (dt='20260212');  -- 无c字段
-- 查询数据时的问题:
SELECT c FROM tmp.kgl_tet WHERE dt='20260212';  -- 结果全为NULL(分区元数据无c字段,Hive解析时直接填NULL)

加cascade

-- 同步更新表级+所有分区的元数据
ALTER TABLE tmp.kgl_tet ADD COLUMNS (c string) CASCADE;
-- 查看分区Schema(已包含c字段)
DESCRIBE tmp.kgl_tet PARTITION (dt='20260212');  -- 显示 c string
-- 查询数据时:
SELECT c FROM tmp.kgl_tet WHERE dt='20260212';  -- 能正确读取Parquet文件中的c字段(若文件有值)

五、tez资源不足问题

hive on tez执行任务报错,did not succeed due to VERTEX_FAILURE
diagnostics=[Vertex vertex_1711699974810_818019_2_00 [Map 8] killed/failed due to:ROOT_INPUT_INIT_FAILURE, Vertex Input: t initializer failed
set hive.tez.container.size=100000;
set tez.am.resource.memory.mb=10000;

六、udf报错与HiveServer2的联系

org.apache.hive.service.cli.HiveSQLException: Error while compiling statement: FAILED: SemanticException Line 0:-1 Wrong arguments '20260105':org.apache.hadoop.hive.ql.metadata.HiveException: Unable to execute method public org.apache.hadoop.io.Text org.apache.hadoop.hive.ql.udf.XSSUDFYearFirstCloseDay.evaluate(org.apache.hadoop.io.Text) throws org.apache.hadoop.hive.ql.metadata.HiveException:index out of closeDateList[20260102]

原因是自定义UDF XSSUDFYearFirstCloseDay内部的closeDateList数组下标越界,传入参数20260105触发了数组访问超出长度的问题。
直接可执行的排查与解决步骤
1.检查UDF源码中closeDateList的初始化逻辑
确认该数组是否包含2026年的交易日数据,报错中仅显示20260102,大概率缺少 0260105对应的元素或数组长度不足。
2.验证参数格式与UDF入参要求是否匹配
确认传入的20260105是Text类型,且格式符合UDF预期的日期格式(如yyyyMMdd),避免因类型转换或格式错误间接导致下标计算异常。
3.重新编译部署UDF并刷新Hive函数
修正代码后重新打包为JAR包,上传至Hive的函数依赖路径,执行DROP FUNCTION IF EXISTS XSSUDFYearFirstCloseDay;和CREATE FUNCTION XSSUDFYearFirstCloseDay AS ‘com.xxx.XSSUDFYearFirstCloseDay’;刷新函数。
4.HiveServer2会对加载的UDF类及依赖数据(如交易日历)进行内存缓存,当UDF依赖的交易日历更新但未重启HiveServer2时,缓存的旧数据不会自动刷新,导致部分节点仍使用旧版本的日历数据,进而触发下标越界等报错。
4.1. 重启所有HiveServer2节点
直接清除内存缓存,是最直接有效的方法。执行集群管理命令(如 systemctl restart hive-server2或 yarn集群的stop/start脚本),确保所有节点都完成重启。
4.2. 刷新函数元数据(非彻底方案)
若无法重启服务,可在Hive客户端执行以下命令刷新函数定义:

DROP FUNCTION IF EXISTS XSSUDFYearFirstCloseDay;
CREATE FUNCTION XSSUDFYearFirstCloseDay AS 'com.xxx.XSSUDFYearFirstCloseDay';

注意:该方法仅刷新元数据,若UDF依赖的日历数据已打包进JAR,仍需替换JAR并重启。
4.3. 替换更新后的UDFJAR包
将包含新交易日历的UDFJAR包替换掉集群中旧的JAR文件,确保所有HiveServer2节点的JAR版本一致,再执行重启操作。

注意!!!

4.4.1.将交易日历外置存储
不要将日历数据硬编码在UDF中,改为从外部存储(如HDFS文件、MySQL表)读取。UDF每次执行时动态加载最新数据,避免缓存导致的不一致。
4.4.2.配置Hive缓存失效策略
调整Hive配置参数,缩短UDF类加载的缓存有效期(需结合Hive版本,部分版本支持hive.udf.cache.expire.time等参数)。
4.4.3.建立UDF发布与更新规范
每次更新UDF或依赖数据时,强制重启所有HiveServer2节点。
使用版本化管理UDF JAR包(如在文件名中加入版本号),避免覆盖导致的版本混乱。
4.4.4.使用 Hive 持久化函数(Persistent Function)
创建函数时指定WITH SERDEPROPERTIES,确保函数元数据持久化到Hive Metastore,减少节点间元数据不一致的概率。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐