Hive 踩坑之 GC overhead limit exceeded

一.引言

使用Hive执行 select count(*) from table 这种基础语法竟然爆出 GC overhead limit exceeded,于是开始了新的踩坑之旅

二.hive语句与报错

hive -e "select count(*) from $table where day between '20201101' and '20201130';"

统计一下总数结果报错,一脸懵逼

三.解决方案尝试

1.增加内存

既然是内存不足,那就增加堆内存尝试一下,尝试失败:

set mapreduce.map.java.opts=-Xmx4096m -XX:+UseConcMarkSweepGC;

2.数据倾斜

第一个是map阶段groupBy阶段防止倾斜的,第二个是防止join阶段出现数据倾斜设置的,在count(*)场景下显然都没有用:

set hive.groupby.skewindata=true
set hive.optimize.skewjoin=true

3.小文件过多

查看原始表的文件数达到3w+,加起来30天可想而知小文件有多少。小文件多会开很多map,一个map开一个JVM去执行,大量任务的初始化,启动,执行会浪费大量的资源,所以报内存溢出,所以解决需要从源头解决即将原始表生成的文件数量减少。

如果原始任务是map-reduce,最简单的直接设置 reduce 的数量:

set mapred.reduce.tasks = 100

我的原始任务是纯map,没有reduce所有需要通过控制map的量去控制输出文件个数:

之前hive常用参数整理详细介绍了怎么调整map的个数,这里简单写一下,主要调大hive.merge.size.per.task 提高每个task处理的数据量即可减小map,参数调大一倍,map数量少一倍。原始文件数调小后,再运行之前的count任务就可以正常执行了。当时以为count(*)任何时候都有可以无压力运行还是太天真了。

set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
set hive.merge.mapfiles = true;
set hive.merge.size.per.task = 256000000;

四.总结

1.为什么只有map的原始任务生成的小文件太多?

原表的生成脚本是从一个小分区很多的大表中筛选一部分数据出来,所以原表的数据就很分散,如果原表不执行小文件合并则会导致map出很多小文件,所以在生成原表时就要注意控制文件数量。

2.怎么判断 GC overhead limit exceeded 的缘由?

内存溢出有很多情况,如果像上面遇到的情况一样,无法开始正常的MR任务,无法显示启动了多少个map reduce,则可能是因为启动资源过大造成的内存溢出,这时候就要看表原始的数据,数据量是不是有问题;如果是map和reduce执行了一段时间显示内存溢出的问题,很有可能是脚本设计不合理或者原始数据倾斜,则需要通过set参数来进行调整,最常见的就是group by,或者map,reduce处理的数据量不均匀导致。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BIT_666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值