先歸納下,Hive中出現OOM的異常緣由大體分爲如下幾種:
1. Map階段OOM。
2. Reduce階段OOM。
3. Driver提交Job階段OOM。
java
1. 發生OOM的概率很小,除非你程序的邏輯不正常,亦或是程序寫的不高效,產生垃圾太多。
shell
data skew是引起這個的一個緣由。
key分佈不均勻,致使某一個reduce所處理的數據超過預期,致使jvm頻繁GC。
jvm
某個reduce中的value堆積的對象過多,致使jvm頻繁GC。spa
錯誤信息以下:Container [pid=26845,containerID=container_1419056923480_0212_02_000001] is running beyond virtual memory limits. Current usage: 262.8 MB of 2 GB physical memory used; 4.8 GB of 4.2 GB virtual memory used. Killing container.
解決辦法:code
1. 增長reduce個數,set mapred.reduce.tasks=300,。xml
2. 在hive-site.xml中設置,或者在hive shell裏調大參數對象
set mapreduce.map.memory.mb=1024; set mapreduce.map.java.opts=-Xmx819m; set mapreduce.reduce.memory.mb=2048; set mapreduce.reduce.java.opts=-Xmx1638m;
mapreduce.map.memory.mb是向RM申請的內存資源大小內存
mapreduce.reduce.java.opts 通常只用於配置JVM參數資源
JVM大小通常是所申請內存的0.75it
3. 使用map join 代替 common join. 能夠set hive.auto.convert.join = true
4. 設置 hive.optimize.skewjoin = true 來解決數據傾斜問題
job產生的執行計劃的條目太多,好比掃描的分區過多,上到4k-6k個分區的時候,而且是好幾張表的分區都不少時,這時作join。
究其緣由,是 由於序列化時,會將這些分區,即hdfs文件路徑,封裝爲Path對象,這樣,若是對象太多了,並且Driver啓動的時候設置的heap size過小,則會致使在Driver內序列化這些MapRedWork時,生成的對象太多,致使頻繁GC,則會引起以下異常:
java.lang.OutOfMemoryError: GC overhead limit exceeded at sun.nio.cs.UTF_8.newEncoder(UTF_8.java:53) at java.beans.XMLEncoder.createString(XMLEncoder.java:572)
解決思路:
1. 減小分區數量,將歷史數據作成一張整合表,作成增量數據表,這樣分區就不多了。
2. 調大Hive CLI Driver的heap size, 默認是256MB,調節成512MB或者更大。
具體作法是在bin/hive bin/hive-config裏能夠找到啓動CLI的JVM OPTIONS。
這裏咱們設置
export HADOOP_HEAPSIZE=512