全部產品
Search
文件中心

E-MapReduce:Hive作業異常排查及處理

更新時間:Mar 05, 2025

本文介紹Hive作業異常的排查方法和解決方案。

異常排查

如果用戶端遇到作業異常或效能等問題,您可以按照如下步驟進行排查:

  1. 查看Hive用戶端日誌。

    • Hive CLI命令列提交的作業用戶端日誌位於叢集或Gateway節點的/tmp/hive/$USER/hive.log或者/tmp/$USER/hive.log

    • Hive Beeline或者JDBC提交的作業日誌位於HiveServer服務日誌中(一般位於/var/log/emr/hive或者/mnt/disk1/log/hive目錄)。

  2. 查看Hive作業提交的YARN Application日誌,使用yarn命令可以擷取日誌。

    yarn logs -applicationId application_xxx_xxx -appOwner userName

記憶體問題引起的報錯

Container記憶體不足引起的OOM

報錯日誌:java.lang.OutOfMemoryError: GC overhead limit exceeded或者java.lang.OutOfMemoryError: Java heap space

解決方案:調大Container的記憶體,Hive on MR作業需要同時調大JVM Heap Size。

  • Hive on MR:在YARN服務的配置頁面,單擊mapred-site.xml頁簽,調大maper和reducer的記憶體。

    mapreduce.map.memory.mb=4096
    mapreduce.reduce.memory.mb=4096

    同時修改mapreduce.map.java.optsmapreduce.reduce.java.opts的JVM參數-Xmxmapreduce.map.memory.mbmapreduce.reduce.memory.mb的80%。

    mapreduce.map.java.opts=-Xmx3276m (其他參數保持不變)
    mapreduce.reduce.java.opts=-Xmx3276m (其他參數保持不變)
  • Hive on Tez

    • 如果Tez container記憶體不足,則在Hive服務的配置頁面,單擊hive-site.xml頁簽,調大Tez container記憶體。

      hive.tez.container.size=4096
    • 如果Tez am記憶體不足,則在Tez服務的配置頁面,單擊tez-site.xml頁簽,調大Tez am記憶體。

      tez.am.resource.memory.mb=4096
  • Hive on Spark:在Spark服務的spark-defaults.conf中調大Spark Executor記憶體。

    spark.executor.memory=4g

因Container記憶體使用量過多被YARN Kill

報錯日誌:Container killed by YARN for exceeding memory limits

原因分析:Hive Task使用的記憶體(包括JVM堆內和堆外記憶體,以及子進程)超過了作業向YARN申請的記憶體。比如Hive on MR作業的Map Task JVM進程heap size(mapreduce.map.java.opts=-Xmx4g)超過了YARN記憶體申請量(mapreduce.map.memory.mb=3072,3G),會導致Container被YARN NodeManager Kill。

解決方案:

  1. Hive on MR作業可增大mapreduce.map.memory.mbmapreduce.reduce.memory.mb參數值,並確保大於mapreduce.map.java.optsmapreduce.reduce.java.opts的JVM參數-Xmx值的1.25倍及以上。

  2. Hive on Spark作業可增大spark.executor.memoryOverhead參數值,並確保大於spark.executor.memory參數值的25%及以上。

SortBuffer配置太大導致OOM

  • 報錯日誌:

    Error running child: java.lang.OutOfMemoryError: Java heap space
    at org.apache.hadoop.mapred.MapTask$MapOutputBuffer.init(MapTask.java:986)
  • 原因分析:Sort Buffer Size超過了Hive Task Container Size,例如:Container記憶體配了1300 MB,但Sortbuffer配了1024 MB。

  • 解決方案:調大Container記憶體,或調小Sortbuffer。

    tez.runtime.io.sort.mb (Hive on Tez)
    mapreduce.task.io.sort.mb (Hive on MR)

部分GroupBy語句引起的OOM

  • 報錯日誌:

    22/11/28 08:24:43 ERROR Executor: Exception in task 1.0 in stage 0.0 (TID 0)
    java.lang.OutOfMemoryError: GC overhead limit exceeded
        at org.apache.hadoop.hive.ql.exec.GroupByOperator.updateAggregations(GroupByOperator.java:611)
        at org.apache.hadoop.hive.ql.exec.GroupByOperator.processHashAggr(GroupByOperator.java:813)
        at org.apache.hadoop.hive.ql.exec.GroupByOperator.processKey(GroupByOperator.java:719)
        at org.apache.hadoop.hive.ql.exec.GroupByOperator.process(GroupByOperator.java:787)
        at org.apache.hadoop.hive.ql.exec.Operator.forward(Operator.java:897)
        at org.apache.hadoop.hive.ql.exec.SelectOperator.process(SelectOperator.java:95)
        at org.apache.hadoop.hive.ql.exec.Operator.forward(Operator.java:897)
        at org.apache.hadoop.hive.ql.exec.TableScanOperator.process(TableScanOperator.java:130)
        at org.apache.hadoop.hive.ql.exec.MapOperator$MapOpCtx.forward(MapOperator.java:148)
        at org.apache.hadoop.hive.ql.exec.MapOperator.process(MapOperator.java:547)
  • 原因分析:GroupBy的HashTable佔用太多記憶體導致OOM。

  • 解決方案:

    1. 減小Split Size至128 MB、64 MB或更小,增大作業並發度:mapreduce.input.fileinputformat.split.maxsize=134217728mapreduce.input.fileinputformat.split.maxsize=67108864

    2. 增大Mapper、Reducer的並發度。

    3. 增大Container的記憶體。具體方法,請參見Container記憶體不足引起的OOM

讀取Snappy檔案出現OOM

  • 原因分析:LogService等服務寫入的標準Snappy檔案和Hadoop生態的Snappy檔案格式不同,EMR預設處理的是Hadoop修改過的Snappy格式,處理標準格式時會報錯OutOfMemoryError。

  • 解決方案:對Hive作業配置如下參數。

    set io.compression.codec.snappy.native=true;

中繼資料相關報錯

Drop大分區表逾時

  • 報錯日誌:

    FAILED: Execution ERROR, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. org.apache.thrift.transport.TTransportException: java.net.SocketTimeoutException: Read timeout
  • 原因分析:作業異常的可能原因是表分區太多,Drop耗時較長,導致Hive Metastore client網路逾時。

  • 解決方案:

    1. 在EMR控制台Hive服務的配置頁面,單擊hive-site.xml頁簽,調大Client訪問metastore的逾時時間。

      hive.metastore.client.socket.timeout=1200s
    2. 大量刪除分區,例如多次執行帶條件的分區。

      alter table [TableName] DROP IF EXISTS PARTITION (ds<='20220720')

insert overwrite動態分區導致作業失敗

  • 報錯日誌:通過insert overwrite操作動態分區或執行類似存在insert overwrite操作的作業時,出現Exception when loading xxx in table報錯,HiveServer日誌中出現了以下報錯日誌。

    Error in query: org.apache.hadoop.hive.ql.metadata.HiveException: Directory oss://xxxx could not be cleaned up.;
  • 原因分析:中繼資料和資料不一致,中繼資料中存在某個分區的記錄,但資料存放區系統中沒有該路徑,導致使用cleanup方法的時候報錯找不到路徑。

  • 解決方案:您可以嘗試修複中繼資料問題之後再重新執行作業。

Hive讀表或者刪除表時報錯java.lang.IllegalArgumentException: java.net.UnknownHostException: emr-header-1.xxx

  • 原因分析:當EMR叢集使用DLF統一中繼資料或者統一meta資料庫(舊版功能)時,建立的資料庫初始路徑是EMR當前叢集的HDFS路徑(例如hdfs://master-1-1.xxx:9000/user/hive/warehouse/test.db或者hdfs://emr-header-1.cluster-xxx:9000/user/hive/warehouse/test.db)。Hive表路徑會繼承資料庫路徑,同樣也會使用當前叢集的HDFS路徑(例如hdfs://master-1-1.xxx:9000/user/hive/warehouse/test.db/test_tbl)。當啟用一個新EMR叢集,同時使用Hive讀寫舊叢集建立的Hive表或者資料庫時,新叢集可能無法串連舊叢集或者因舊叢集已釋放,會出現java.net.UnknownHostException異常。

  • 解決方案:

    • 方法1:如果確認Hive表資料是臨時或者測試資料,可以嘗試修改Hive表路徑為某個OSS路徑,並且再次調用drop tabledrop database命令。

      -- Hive SQL
      alter table test_tbl set location 'oss://bucket/not/exists'
      drop table test_tbl;
      
      alter table test_pt_tbl partition (pt=xxx) set location 'oss://bucket/not/exists';
      alter table test_pt_tbl drop partition pt=xxx);
      
      alter database test_db set location 'oss://bucket/not/exists'
      drop datatabase test_db
    • 方法2:如果確認Hive表資料是有效資料,但在新叢集上無法訪問。此時EMR舊叢集上的Hive表資料儲存在HDFS上,可以先嘗試將 HDFS資料轉移到OSS上,並且建立新表。

      hadoop fs -cp hdfs://emr-header-1.xxx/old/path oss://bucket/new/path
      hive -e "create table new_tbl like old_tbl location 'oss://bucket/new/path'"

Hive UDF和第三方包

Hive lib目錄下放置三方包導致衝突

  • 原因分析:在Hive lib目錄($HIVE_HOME/lib)下放置三方包或者替換Hive包經常會導致各種衝突問題,請避免此類操作。

  • 解決方案:把放在$HIVE_HOME/lib裡的三方包移除,恢複替換為原始的Hive JAR包。

Hive無法使用reflect函數

  • 原因分析:在Ranger鑒權開啟的情況下可能無法使用reflect函數。

  • 解決方案:將reflect函數從黑名單移除,在hive-site.xml中配置。

    hive.server2.builtin.udf.blacklist=empty_blacklist

自訂UDF導致作業運行慢

  • 原因分析:Hive作業運行慢,但未發現異常日誌,可能原因是Hive自訂UDF效能存在問題。

  • 解決方案:可以通過對Hive task進行thread dump定位問題,根據thread dump發現的效能熱點針對性最佳化自訂UDF。

grouping()使用異常

  • 異常現象:在使用grouping()函數時,遇到以下報錯資訊。

    grouping() requires at least 2 argument, got 1

    該錯誤表明 grouping() 函數的調用參數解析異常。

  • 原因分析:此問題是由開源版本 Hive 的一個已知Bug導致的。Hive 對 grouping() 函數的解析是大小寫敏感的。當使用小寫 grouping() 時,Hive 可能無法正確識別該函數,從而導致參數解析錯誤。

  • 解決方案:將 SQL 中的 grouping() 函數改為大寫的 GROUPING()即可解決問題。

引擎相容問題

Hive和Spark時區不一致導致結果不一致

  • 異常現象:Hive的from_unix_time時區固定為UTC,而Spark使用的是本地時區,如果兩者的時區不一致會導致結果不一致。

  • 解決方案:修改Spark時區為UTC,在Spark SQL中插入如下代碼:

    set spark.sql.session.timeZone=UTC;

    或者修改Spark設定檔,添加新的配置:

    spark.sql.session.timeZone=UTC

歷史Hive版本缺陷

Hive on Spark開啟動態分區執行慢(已知缺陷)

  • 原因分析:Hive開源版本的缺陷,Beeline的方式把spark.dynamicAllocation.enabled開啟了,導致Hive在計算Shuffle的Partition的時候總是算成1。

  • 解決方案:Hive on Spark作業關閉動態資源伸縮或者使用Hive on Tez。

    spark.dynamicAllocation.enabled=false

開啟dynamic.partition.hashjoin後tez報錯(已知缺陷)

  • 報錯日誌:

    Vertex failed, vertexName=Reducer 2, vertexId=vertex_1536275581088_0001_5_02, diagnostics=[Task failed, taskId=task_1536275581088_0001_5_02_000009, diagnostics=[TaskAttempt 0 failed, info=[Error: Error while running task ( failure ) : attempt_1536275581088_0001_5_02_000009_0:java.lang.RuntimeException: java.lang.RuntimeException: cannot find field _col1 from [0:key, 1:value]
        at org.apache.hadoop.hive.ql.exec.tez.TezProcessor.initializeAndRunProcessor(TezProcessor.java:296)
        at org.apache.hadoop.hive.ql.exec.tez.TezProcessor.run(TezProcessor.java:250)
  • 原因分析:Hive開源版本缺陷。

  • 解決方案:臨時解決方案是關閉配置。

    hive.optimize.dynamic.partition.hashjoin=false

MapJoinOperator報錯NullPointerException(已知缺陷)

  • 報錯日誌:日誌

  • 原因分析:開啟了hive.auto.convert.join.noconditionaltask會導致報錯。

  • 解決方案:關閉相關配置。

    hive.auto.convert.join.noconditionaltask=false

Hive on Tez報錯IllegalStateException(已知缺陷)

  • 報錯日誌:

    java.lang.RuntimeException: java.lang.IllegalStateException: Was expecting dummy store operator but found: FS[17]
            at org.apache.hadoop.hive.ql.exec.tez.TezProcessor.initializeAndRunProcessor(TezProcessor.java:296)
            at org.apache.hadoop.hive.ql.exec.tez.TezProcessor.run(TezProcessor.java:250)
            at org.apache.tez.runtime.LogicalIOProcessorRuntimeTask.run(LogicalIOProcessorRuntimeTask.java:374)
            at org.apache.tez.runtime.task.TaskRunner2Callable$1.run(TaskRunner2Callable.java:73)
            at org.apache.tez.runtime.task.TaskRunner2Callable$1.run(TaskRunner2Callable.java:61)
            at java.security.AccessController.doPrivileged(Native Method)
            at javax.security.auth.Subject.doAs(Subject.java:422)
            at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1730)
            at org.apache.tez.runtime.task.TaskRunner2Callable.callInternal(TaskRunner2Callable.java:61)
            at org.apache.tez.runtime.task.TaskRunner2Callable.callInternal(TaskRunner2Callable.java:37)
            at org.apache.tez.common.CallableWithNdc.call(CallableWithNdc.java:36)
  • 原因分析:Hive開源版本缺陷,在開啟Hive am reuse之後出現,目前EMR Hive暫未解決該問題。

  • 解決方案:在單個作業層面把Tez ApplicationMaster reuse功能關掉。

    set tez.am.container.reuse.enabled=false;

其他異常

select count(1)結果為0

  • 原因分析:select count(1)使用的是Hive表統計資訊(statistics),但這張表的統計資訊不準確。

  • 解決方案:修改配置不使用統計資訊。

    hive.compute.query.using.stats=false

    或者使用analyze命令重新統計表統計資訊。

    analyze table <table_name> compute statistics;

在自建ECS上提交Hive作業異常

在自建ECS上提交Hive作業(不在EMR產品範圍內),會出現不可預期報錯。請使用EMR Gateway叢集或者使用EMR-CLI自訂部署Gateway環境。更多資訊,請參見使用EMR-CLI自訂部署Gateway環境

資料扭曲導致的作業異常

  • 異常現象:

    • Shuffle資料把磁碟打滿。

    • 某些Task執行時間特別長。

    • 某些Task或Container出現OOM。

  • 解決方案:

    1. 開啟Hive skewjoin最佳化。

      set hive.optimize.skewjoin=true;
    2. 增大Mapper、Reducer的並發度。

    3. 增大Container的記憶體。具體方法,請參見Container記憶體不足引起的OOM

報錯“Too many counters: 121 max=120”,該如何處理?

  • 問題描述:使用Tez或MR引擎,在使用Hive SQL執行作業時報錯。

  • 報錯分析:當前作業的counters數量超過預設的counters限制。

  • 解決方案:您可以在EMR控制台YARN服務的配置頁簽,搜尋mapreduce.job.counters.max參數,調大該參數值,修改完後重新提交Hive作業,如果使用Beeline或者JDBC提交作業,需要重啟HiveServer服務。