Hive 执行动态插入分区时,在MapReduce日志中报“java.lang.OutOfMemoryError: GC overhead limit exceeded”错误

执行动态插入分区时,在MapReduce日志中报“java.lang.OutOfMemoryError: GC overhead limit exceeded”错误

现象描述

在HiveServer服务正常的情况下,执行动态插入分区时,在MapReduce日志中报“java.lang.OutOfMemoryError: GC overhead limit exceeded”错误。

可能原因

产生OOM的原因是单个任务处理的分区数过多,需要针对具体场景,减少单个task处理的分区数。

定位思路

参照如下样例进行操作。

样例建表语句如下:

create table test(id int )partitioned by (dt int);

create table test1(id int, dt int);

正常的动态插入分区语句为:

insert overwrite table test partition (dt) select id, dt from test;

处理步骤

  1. 由于dt是分区字段,减少单个task处理分区数的办法是,将分区字段distribute到不同的task来处理。 修改后的语句: insert overwrite table test partition (dt) select id, dt from test1 distribute by dt;
  2. 当distribute by的分区字段存在倾斜时,比如值为NULL的占了很大部分,那么还可以将其打散处理。 存在倾斜字段为NULL时的优化后语句: insert overwrite table test partition (dt) select id, dt from test1 distribute by nvl(dt,round(rand()*50)); 说明: nvl函数是一个将null转换为需要的值的hive内置udf。内置udf的使用,可参考https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF。其中rand返回一个0-1之间的随机数,乘以一个常数50(也可以是其他数字,根据自己任务的并发度合理选取,以能在合理的时间处理完为宜)。 然后通过round函数取整,就能够将值为NULL的分区,分散到多个不同的task中处理。

关注公众号“大模型全栈程序员”回复“小程序”获取1000个小程序打包源码。更多免费资源在http://www.gitweixin.com/?p=2627

发表评论

邮箱地址不会被公开。 必填项已用*标注