Hive优化Hive Multi Insert 引起的GC overhead limit exceeded笔记

当你有这么个需求从某张hive表里做各类统计,完了之后落到各个分类的统计表里存储。自然而然我们会想到使用hive的Multi Insert 语句来实现。因为使用Multi Insert 语句可以避免多次扫描同一份原始表数据。本文记录一次使用Multi Insert 语句出现的GC overhead limit exceeded问题。
问题描述

我有这么个需求从某个域名相关的表里统计各个维度的数据落到相应的表里面。下面是我的SQL实例代码:

+ expand source
上述语句会产生6个Job,你可以使用explain hsql来查看执行解析流程:

+ expand source
从上面可以看到Stage-6 is a root stage。Stage-6是第一个需要完成的job,然而问题就出现在这里。GC overhead limit exceeded !!!
从失败的jobhistory里可以看到失败是发生在map阶段。

...
map = 99%,  reduce = 33%, Cumulative CPU 9676.12 sec
map = 100%,  reduce = 100%, Cumulative CPU 9686.12 sec
也就是发现在map阶段。我们先看看错误堆栈:

2015-12-01 18:21:02,424 INFO [communication thread] org.apache.hadoop.mapred.Task: Communication exception: java.lang.OutOfMemoryError: GC overhead limit exceeded
 at java.nio.HeapByteBuffer.(HeapByteBuffer.java:57)
 at java.nio.ByteBuffer.allocate(ByteBuffer.java:331)
 at sun.nio.cs.StreamDecoder.(StreamDecoder.java:250)
 at sun.nio.cs.StreamDecoder.(StreamDecoder.java:230)
 at sun.nio.cs.StreamDecoder.forInputStreamReader(StreamDecoder.java:69)
 at java.io.InputStreamReader.(InputStreamReader.java:74)
 at java.io.FileReader.(FileReader.java:72)
 at org.apache.hadoop.yarn.util.ProcfsBasedProcessTree.constructProcessInfo(ProcfsBasedProcessTree.java:381)
 at org.apache.hadoop.yarn.util.ProcfsBasedProcessTree.updateProcessTree(ProcfsBasedProcessTree.java:162)
 at org.apache.hadoop.mapred.Task.updateResourceCounters(Task.java:839)
 at org.apache.hadoop.mapred.Task.updateCounters(Task.java:978)
 at org.apache.hadoop.mapred.Task.access$500(Task.java:77)
 at org.apache.hadoop.mapred.Task$TaskReporter.run(Task.java:727)
 at java.lang.Thread.run(Thread.java:745)
map阶段OutOfMemoryError: GC overhead limit exceeded。

问题分析

OMM的通用原因大家都知道。加内存嘛!呵呵,咱不是土豪,而且OMM的原因加内存不一定能解决,还是找找内因。那么解决OMM该怎么做呢?首先我们得清楚OMM的原因的可能。1. 内存确实不够程序使用。2. 程序存在内存泄露或者程序的不够高效。作为立志成为资深程序猿的人应该从第二个入手。好,我们先分析分析:

hive程序运行环境:

系统46台 Ubuntu12.04, 8核心,32G Mem。Hadoop版本2.2.0 ,hive 0.12。数据100G+ Text。使用的队列最大大概是总体的40%。上述hive程序启动map数380左右,reduce数120左右。按理说这样的数量应该不算大。但问题是它确实OMM了。应为使用的时hive程序,不是自己写的。应该不大可能存在内存泄露的代码。那么应该是hive sql不合理,首先想到的是Multi Insert的效率问题。测试:分别跑单个Insert语句,即删掉一些Insert语句。
实例代码如下:

+ expand source
结果都是能够跑出来的。也就是说Multi Insert是比较耗费内存导致OMM,并不是sql程序的问题。那么最大的原因是我们给程序(mapreduce)的内存过小。那么先看下我们到底配置了多大的内存。在hive cli里执行下面命令:

hive> set mapreduce.map.java.opts;
mapreduce.map.java.opts=-Xmx1500m

hive> set mapreduce.reduce.java.opts;
mapreduce.reduce.java.opts=-Xmx2048m

hive> set mapreduce.map.memory.mb;
mapreduce.map.memory.mb=2048

hive> set mapreduce.reduce.memory.mb;
mapreduce.reduce.memory.mb=3072
我们的程序问题出现在map阶段OMM,所以应该是map的内存设置小了(mapreduce.map.java.opts=1.5g)。也是设置大点,但是不能操作map允许的最大值 mapreduce.map.memory.mb(这里为2g)。

总结:

对于内存问题导致的OMM我们需要从两点入手:

程序是否有内存泄露
内存是否确实设置过小
对于第一个首先排查程序问题。在上面案例中我们使用了Multi Insert导致内存不够Gc。这里你就会问了什么是GC overhead limit exceeded 而不是Java heap space?

GC overhead limit exceeded的解释:
一、异常描述:
Exception in thread “main” java.lang.OutOfMemoryError: GC overhead limit exceeded
二、解释:
JDK6新增错误类型。当GC为释放很小空间占用大量时间时抛出。 一般是因为堆太小。
导致异常的原因:没有足够的内存。
三、解决方案:
1、查看系统是否有使用大内存的代码或死循环。
2、可以添加JVM的启动参数来限制使用内存:-XX:-UseGCOverheadLimit
所以对于本案例来说我的优化如下:

set mapreduce.map.java.opts=-Xmx1800m -XX:-UseGCOverheadLimit
本文不是讨论JVM的,所以就不深表。对于Multi Insert 的优化,如果是insert 同一个表我们也可以使用union all来代替

时间: 2024-11-10 08:26:09

Hive优化Hive Multi Insert 引起的GC overhead limit exceeded笔记的相关文章

java.lang.OutOfMemoryError:GC overhead limit exceeded填坑心得

我遇到这样的问题,本地部署时抛出异常java.lang.OutOfMemoryError:GC overhead limit exceeded导致服务起不来,查看日志发现加载了太多资源到内存,本地的性能也不好,gc时间消耗的较多.解决这种问题两种方法是,增加参数,- XX:-UseGCOverheadLimit,关闭这个特性,同时增加heap大小,-Xmx1024m.坑填了,but why? OOM大家都知道,就是JVM内存溢出了,那GC overhead limit exceed呢? GC o

An internal error occurred during: "Retrieving archetypes:". GC overhead limit exceeded

An internal error occurred during: "Retrieving archetypes:".GC overhead limit exceeded 异常,分享牛系列,分享牛专栏,分享牛. 出现这种情况是什么原因造成的呢? 1.肯定是jvm抛出的异常. 2.eclipse或者myeclipse配置的文件在安装的目录下myeclipse.ini或者eclipse.ini.所有能配置的大概就在这个地方了. 3.修改文件如下: -vmargs-Xmx1024m-Xms

android studio Error:java.lang.OutOfMemoryError: GC overhead limit exceeded

android studio Error:java.lang.OutOfMemoryError: GC overhead limit exceeded 在app下的build.gradle中找到android,并添加如下配置 dexOptions { javaMaxHeapSize "4g" } 如: android { ... ... dexOptions { javaMaxHeapSize "4g" } ... ... }  

java.lang.OutOfMemoryError: GC overhead limit exceeded 问题分析和解决(转)

在项目历史数据导入过程中,出现了应用无法访问的情况.立刻对Weblogic进行分析,发现Weblogic的内存.线程等性能良好,Server也是Running的状态.随后查看了Weblogic日志,在日志中发现下述错误   通过排查问题后得出造成此类问题的原因是,项目的一个模块在批量导入数据,程序需要New一个很大的对象,GC发现内存不够后,对内存进行回收,但是发现回收后的内存还不能满足大对象的需要.应此造成了内存溢出.   解决方案:调大Weblogic的启动内存即可.   http://bl

eclipse报错GC overhead limit exceed,卡顿

在使用Eclipse的Build Project功能时,提示以下错误: An internal error occurred during: "Build Project". GC overhead limit exceeded 如图: 搜索的一下,是属于java.lang.OutOfMemoryError. OOM大家都知道,就是JVM内存溢出了,那GC overhead limit exceed呢? GC overhead limt exceed检查是Hotspot VM 1.6定

Hive基本操作,DDL操作(创建表,修改表,显示命令),DML操作(Load Insert Select),Hive Join,Hive Shell参数(内置运算符、内置函数)等

1.  Hive基本操作 1.1  DDL操作 1.1.1    创建表 建表语法 CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name    [(col_name data_type[COMMENT col_comment], ...)] +    [COMMENT table_comment]    [PARTITIONED BY (col_namedata_type [COMMENT col_comment], ...)]    [CLUST

Hive优化以及执行原理

Hive优化以及执行原理 数据平台   杨新彦 2014-01-13 1.整体架构优化 2. MR阶段优化 3. JOB优化 4. SQL作业优化 5.平台优化 Hive优化以及执行原理

Hive之Hive快捷查询(避免Mapruduce查询)

避免Mapruduce查询 如果你想查询某个表的某一列,Hive默认是会启用MapReduce Job来完成这个任务.但是,我们可以设置参数来避免Mapruduce查询,下面先介绍一下几个小的知识点,并不Mapruduce查询. hive (zb_dwd)> select * from user_id limit 1; OK 14510812944 Time taken: 1.608 seconds, Fetched: 1 row(s) 这种情况下,Hive可以简单地读取user_id对应的存储

Hive简介、什么是Hive、为什么使用Hive、Hive的特点、Hive架构图、Hive基本组成、Hive与Hadoop的关系、Hive与传统数据库对比、Hive数据存储(来自学习资料)

1.1 Hive简介 1.1.1   什么是Hive Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供类SQL查询功能. 1.1.2   为什么使用Hive Ø  直接使用hadoop所面临的问题 人员学习成本太高 项目周期要求太短 MapReduce实现复杂查询逻辑开发难度太大   Ø  为什么要使用Hive 操作接口采用类SQL语法,提供快速开发的能力. 避免了去写MapReduce,减少开发人员的学习成本. 功能扩展很方便. 1.1.3   H