このトピックでは、Hive ジョブが失敗した場合のトラブルシューティングと解決策について説明します。
障害発生時のトラブルシューティング
クライアントでジョブの失敗やパフォーマンスの問題が発生した場合は、次の手順に従ってください。
-
Hive クライアントのログを確認します。
-
Hive CLI 経由でサブミットされたジョブの場合、クライアントログはクラスターまたはゲートウェイノード上の /tmp/hive/$USER/hive.log または /tmp/$USER/hive.log に格納されています。
-
Hive Beeline または JDBC 経由でサブミットされたジョブのログは、HiveServer のサービスログ (通常は /var/log/emr/hive または /mnt/disk1/log/hive) にあります。
-
-
yarn コマンドを使用して、Hive ジョブの YARN アプリケーションログを確認します。
yarn logs -applicationId application_xxx_xxx -appOwner userName
メモリ関連のエラー
コンテナのメモリ不足によるメモリ不足 (OOM) エラー
エラーログ: java.lang.OutOfMemoryError: GC overhead limit exceeded または java.lang.OutOfMemoryError: Java heap space。
解決策:コンテナのメモリを増やします。Hive on MapReduce (MR) ジョブの場合は、JVM ヒープサイズも増やします。
-
Hive on MR:YARN サービスの設定ページで、[mapred-site.xml] タブをクリックし、マッパーとリデューサーのメモリを増やします。
mapreduce.map.memory.mb=4096 mapreduce.reduce.memory.mb=4096また、
mapreduce.map.java.optsとmapreduce.reduce.java.opts内の JVM パラメーター-Xmxを、mapreduce.map.memory.mbとmapreduce.reduce.memory.mbの値の 80% に更新します。mapreduce.map.java.opts=-Xmx3276m (その他のパラメーターは変更しません) mapreduce.reduce.java.opts=-Xmx3276m (その他のパラメーターは変更しません) -
Hive on Tez
-
Tez コンテナのメモリが不足した場合、Hive サービスの設定ページで [hive-site.xml] タブをクリックし、Tez コンテナのメモリを増やします。
hive.tez.container.size=4096 -
Tez AM のメモリが不足した場合、Tez サービスの設定ページで [tez-site.xml] タブをクリックし、Tez AM のメモリを増やします。
tez.am.resource.memory.mb=4096
-
-
Hive on Spark:
spark-defaults.confで Spark Executor のメモリを増やします。spark.executor.memory=4g
メモリの過剰使用による YARN からのコンテナ強制終了
エラーログ: Container killed by YARN for exceeding memory limits。
根本原因:Hive タスクが、YARN に要求したメモリ (JVM ヒープ、オフヒープメモリ、子プロセスを含む) よりも多くのメモリを使用するためです。たとえば、Hive on MR で、Map タスクの JVM ヒープサイズ (mapreduce.map.java.opts=-Xmx4g) が YARN のメモリ割り当て (mapreduce.map.memory.mb=3072、つまり 3 GB) を超えると、YARN NodeManager はコンテナを強制終了します。
解決策:
-
Hive on MR ジョブの場合、
mapreduce.map.memory.mbとmapreduce.reduce.memory.mbを増やし、mapreduce.map.java.optsとmapreduce.reduce.java.opts内の-Xmx値の少なくとも 1.25 倍になるようにします。 -
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) -
根本原因:ソートバッファサイズが Hive タスクのコンテナサイズを超えているためです。たとえば、コンテナのメモリが 1300 MB に設定されているにもかかわらず、ソートバッファが 1024 MB に設定されている場合などです。
-
解決策:コンテナのメモリを増やすか、ソートバッファのサイズを減らします。
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 が発生するためです。
-
解決策:
-
分割サイズを 128 MB、64 MB、またはそれ以下に減らして、ジョブの同時実行数を増やします:
mapreduce.input.fileinputformat.split.maxsize=134217728またはmapreduce.input.fileinputformat.split.maxsize=67108864。 -
マッパーとリデューサーの同時実行数を増やします。
-
コンテナのメモリを増やします。詳細については、「コンテナのメモリ不足によるメモリ不足 (OOM) エラー」をご参照ください。
-
Snappy ファイル読み取り時のメモリ不足 (OOM)
-
根本原因:LogService などのサービスによって書き込まれた標準の Snappy ファイルは、Hadoop エコシステムの Snappy ファイルとは異なる形式を使用します。E-MapReduce (EMR) はデフォルトで Hadoop 向けに変更された Snappy 形式を使用するため、標準の Snappy ファイルを処理する際に OutOfMemoryError をスローします。
-
解決策:Hive ジョブに次のパラメーターを設定します。
set io.compression.codec.snappy.native=true;
メタデータ関連のエラー
大規模なパーティションテーブルを削除する際のタイムアウト
-
エラーログ:
FAILED: Execution ERROR, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. org.apache.thrift.transport.TTransportException: java.net.SocketTimeoutException: Read timeout -
根本原因:テーブルのパーティションが多すぎるため、削除に時間がかかり、Hive Metastore クライアントのネットワークタイムアウトが発生します。
-
解決策:
-
EMR コンソールの Hive サービス設定ページで、[hive-site.xml] タブをクリックし、メタストアクライアントのソケットタイムアウトを増やします。
hive.metastore.client.socket.timeout=1200s -
条件付き削除コマンドを複数回実行するなどして、パーティションをバッチで削除します。
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.; -
根本原因:メタデータとデータの間に不整合があるためです。メタデータにはパーティションレコードが含まれているものの、データストレージシステムに対応するパスが存在しないため、クリーンアップ中に "path not found" エラーが発生します。
-
解決策:ジョブを再実行する前に、メタデータの問題を修正します。
テーブル読み取り/削除時の Hive による java.lang.IllegalArgumentException のスロー
-
根本原因:EMR クラスターが DLF 統合メタデータまたは統合メタデータベース (レガシー機能) を使用する場合、作成されたデータベースの初期パスは現在の 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 を使用して、古い EMR クラスターによって作成された Hive テーブルまたはデータベースからデータを読み書きしようとすると、新しいクラスターが古いクラスターに接続できない場合があります。さらに、古いクラスターが解放されている場合、"java.net.UnknownHostException" エラーが返されます。 -
解決策:
-
方法1:Hive テーブルのデータが一時データまたはテストデータである場合は、Hive テーブルの場所を OSS パスに変更し、
drop tableまたはdrop 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 database test_db -
方法2:Hive テーブルのデータは有効ですが、新しいクラスターからアクセスできない場合は、古い EMR クラスターから OSS に HDFS データを転送し、新しいテーブルを作成します。
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 JAR を置き換えたりすると、競合が発生することがよくあります。このような操作は避けてください。
-
解決策: $HIVE_HOME/lib からサードパーティパッケージを削除し、元の Hive JAR を復元します。
Hive における reflect 関数の使用不可
-
根本原因:Ranger 認証が有効になっている場合、reflect 関数が利用できないことがあります。
-
解決策:
hive-site.xmlを設定して、ブラックリストから reflect を削除します。hive.server2.builtin.udf.blacklist=empty_blacklist
カスタム UDF (ユーザー定義関数) によるジョブ実行の低速化
-
根本原因:Hive ジョブの実行が遅く、明確なエラーログがない場合、カスタム UDF (ユーザー定義関数) のパフォーマンスが低いことが原因である可能性があります。
-
解決策:Hive タスクでスレッドダンプを実行してパフォーマンスのホットスポットを特定し、それに応じてカスタム UDF を最適化します。
grouping() 関数の失敗
-
症状:
grouping()関数を使用すると、次のエラーが発生します:grouping() requires at least 2 argument, got 1このエラーは、
grouping()関数の呼び出しで解析エラーが発生したことを示しています。 -
根本原因:これはオープンソースの Hive における既知のバグです。Hive のパーサーは
grouping()関数で大文字と小文字を区別するため、小文字のgrouping()を使用すると、Hive が関数を誤って識別し、引数の解析が正しく行われなくなります。 -
解決策:SQL 内の
grouping()関数を大文字のGROUPING()に変更します。
エンジン互換性の問題
Hive と Spark のタイムゾーンの違いによる結果の不整合
-
症状:Hive の
from_unix_timeは UTC を使用しますが、Spark はローカルタイムゾーンを使用します。タイムゾーンが一致しないため、結果が異なります。 -
解決策:Spark SQL に次のコードを追加して、Spark のタイムゾーンを UTC に設定します:
set spark.sql.session.timeZone=UTC;または、この設定を Spark の設定ファイルに追加します:
spark.sql.session.timeZone=UTC
古い Hive バージョンの既知のバグ
動的パーティションを使用する Hive on Spark 実行の低速化 (既知のバグ)
-
根本原因:オープンソースの Hive のバグにより、Beeline が
spark.dynamicAllocation.enabledを有効にすると、Hive がシャッフルパーティションを 1 として計算してしまうためです。 -
解決策:Hive on Spark ジョブの動的リソース割り当てを無効にするか、代わりに Hive on Tez を使用します。
spark.dynamicAllocation.enabled=false
hive.optimize.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 のスロー (既知のバグ)
-
エラーログ:
2022-05-06 18:37:26,664 ERROR [main] org.apache.hadoop.hive.ql.exec.mr.ExecMapper: java.lang.NullPointerException at org.apache.hadoop.hive.ql.exec.MapJoinOperator.loadHashTable(MapJoinOperator.java:313) at org.apache.hadoop.hive.ql.exec.MapJoinOperator.cleanUpInputFileChangedOp(MapJoinOperator.java:345) at org.apache.hadoop.hive.ql.exec.Operator.cleanUpInputFileChanged(Operator.java:1124) at org.apache.hadoop.hive.ql.exec.Operator.cleanUpInputFileChanged(Operator.java:1128) at org.apache.hadoop.hive.ql.exec.Operator.cleanUpInputFileChanged(Operator.java:1128) at org.apache.hadoop.hive.ql.exec.MapOperator.process(MapOperator.java:540) at org.apache.hadoop.hive.ql.exec.mr.ExecMapper.map(ExecMapper.java:148) at org.apache.hadoop.mapred.MapRunner.run(MapRunner.java:54) at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:453) at org.apache.hadoop.mapred.MapTask.run(MapTask.java:343) at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:175) 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:1911) at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:169) -
根本原因: hive.auto.convert.join.noconditionaltask を有効にすると、このエラーがトリガーされます。
-
Solution: Disable the related setting.
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 AM の再利用が有効な場合に発生する、オープンソースの Hive のバグです。EMR Hive はまだこの問題を修正していません。
-
解決策:個々のジョブに対して Tez ApplicationMaster の再利用を無効にします。
set tez.am.container.reuse.enabled=false;
その他のエラー
「select count(1)」が 0 を返す問題
-
根本原因:
select count(1)は Hive テーブルの統計情報を使用しますが、その統計が不正確なためです。 -
解決策:統計情報の使用を無効にします。
hive.compute.query.using.stats=falseまたは、
analyzeコマンドを使用してテーブルの統計情報を再計算します。analyze table <table_name> compute statistics;
セルフマネージド ECS インスタンスでの Hive ジョブ送信の失敗
セルフマネージド ECS インスタンス (EMR 外部) から Hive ジョブを送信すると、予測不能なエラーが発生することがあります。EMR ゲートウェイクラスターを使用するか、EMR-CLI を使用してゲートウェイ環境をデプロイしてください。詳細については、「EMR-CLIを使用したゲートウェイ環境のデプロイ」をご参照ください。
データスキューによるジョブの失敗
-
現象:
-
シャッフルデータがディスク容量を使い果たします。
-
特定のタスクの実行に非常に時間がかかります。
-
特定のタスクまたはコンテナでメモリ不足 (OOM) が発生します。
-
-
解決策:
-
Hive のスキュー結合最適化を有効にします。
set hive.optimize.skewjoin=true; -
マッパーとリデューサーの同時実行数を増やします。
-
コンテナのメモリを増やします。詳細については、「コンテナのメモリ不足によるメモリ不足 (OOM) エラー」をご参照ください。
-
「Too many counters: 121 max=120」への対処方法
-
説明:Tez または MR エンジンで Hive SQL ジョブを実行すると、このエラーが発生することがあります。
-
分析:ジョブがデフォルトのカウンター制限を超えているためです。
-
解決策:EMR コンソールの YARN サービス Configure タブで、
mapreduce.job.counters.maxパラメーターを検索してその値を増やします。更新後、Hive ジョブを再送信します。Beeline または JDBC 経由でジョブを送信する場合は、HiveServer サービスを再起動してください。