Amazon EMR で Hive クエリ結果を出力する際に発生する Hive Java ヒープスペースの例外「OutOfMemoryError」の解決方法を教えてください。

最終更新日: 2020 年 5 月 18 日

Amazon EMR で Apache Hive クエリを実行していて、Hive はクエリ結果の出力中に OutOfMemoryError 例外をスローします。どうすればこのエラーを解決できますか?

簡単な説明

OutOfMemoryError 例外は、通常、INSERT OVERWRITE コマンド中に、hive-server2、Hive メタストア、またはクライアント側に十分なヒープスペースがない場合に発生します。この問題を解決するには、JVM の最大メモリ割り当てを増やすか、HADOOP_HEAPSIZE を増やします。

解決方法

OutOfMemoryError 例外を解決するには、以下のソリューションをご使用ください。

注: この解決方法では、Apache Tez コンテナメモリのチューニング中に発生する OutOfMemoryError 例外は対象外です。

JVM の最大メモリ割り当てを増加する

Hive シェルを起動すると、デフォルトで 1 GB のメモリが割り当てられます。最大メモリ割り当ては、-Xmx パラメータで定義されます。プロセスが最大値を超える値を使用しようとすると、Hive はプロセスを強制終了し、OutOfMemoryError 例外をスローします。この問題を解決するには、Hive シェルスクリプト (MB 単位) の -Xmx 値を増やしてから、Hive クエリを再度実行します。

HADOOP_HEAPSIZE を増やす

/mnt/var/log/hive/user/hadoop/hive.log に次のエラーがないか確認します。

# java.lang.OutOfMemoryError: Java heap space
# -XX:OnOutOfMemoryError="kill -9 %p"
#   Executing /bin/sh -c "kill -9 12345"...
Killed

このエラーメッセージが表示された場合、JVM ヒープスペースのメモリが不足しています。次の例に示すように、/etc/hive/conf/hive-env.sh の Hive CLI サービスの HADOOP_HEAPSIZE を増やします。デフォルト値は 1000 です。ユースケースに応じて増やします。次に、Hive クエリを再度実行します。

export HADOOP_HEAPSIZE=2000

重要: この設定は、サービスの再起動後に hive-server2、Hive メタストア、および Hive CLI に適用されます。必要の応じて、これらのサービスごとに個別の値を設定できます。

Beeline または SQL Workbench/J

1.    Beeline または SQL Workbench/J から同じクエリを実行している場合は、/mnt/var/log/hive/hive-server2.log および hive-server2.out をチェックして、ヒープスペースガベージコレクションエラーがないか確認します。例:

Transaction isolation: TRANSACTION_REPEATABLE_READ
0: jdbc:hive2://emr-analytics_master.abc.aws.> select id, name, x.* from mydb.location a, curated_admin.nxpepnd1_tpn_prvdr_pra_fclt b, curated_admin.test_table c where a.test = b._id and a._id = b._id and b._prod_id = c.prod_f_id;
#
# java.lang.OutOfMemoryError: Java heap space
# -XX:OnOutOfMemoryError="kill -9 %p"
#   Executing /bin/sh -c "kill -9 27745"...
Killed

2.    このようなエラーが見つかった場合は、/etc/hive/conf/hive-env.sh の hive-server2 の HADOOP_HEAPSIZE を増やします。この設定は、Hive メタストアと Hive クライアントにも適用されます。

export HADOOP_HEAPSIZE=2048

必要に応じて、条件ステートメントを使用して、hive-server2、メタストア、およびクライアントに異なるヒープサイズを指定します。例:

export HIVE_CLIENT_HEAPSIZE=1024
export HIVE_METASTORE_HEAPSIZE=2048
export HIVE_SERVER2_HEAPSIZE=3072 
if [ "$SERVICE" = "metastore" ]
then
export HADOOP_HEAPSIZE=$HIVE_METASTORE_HEAPSIZE
elif [ "$SERVICE" = "hiveserver2" ]
then
export HADOOP_HEAPSIZE=$HIVE_SERVER2_HEAPSIZE
export HADOOP_OPTS="$HADOOP_OPTS -server -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/hive"
else
export HADOOP_HEAPSIZE=$HIVE_CLIENT_HEAPSIZE
fi

3.    これらの設定を更新した後、Hive クエリを再度実行します。引き続き OutOfMemoryError 例外が発生し、同時に複数のクライアントを実行している場合は、ステップ 4 に進みます。引き続き OutOfMemoryError 例外が発生し、同時に複数のクライアントを実行していない場合は、ステップ 8 に進みます。

4.    ユースケースに応じて、クライアントごとに -Xmx パラメータを増やします。

5.    次の例に示すように、HADOOP_OPTS 行に -XX:+UseParNewGC (新しい並列ガベージコレクタ) または -XX:+UseConcMarkSweepGC (同時マークスイープガベージコレクタ) を追加して、ユースケースに適したガベージコレクタを選択します。ガベージコレクタの選択の詳細については、Java ドキュメントのガベージコレクションおよび Java HotSpot VM オプションをご参照ください。

export HADOOP_HEAPSIZE=2048
if [ "$SERVICE" = "cli" ]; then
if [ -z "$DEBUG" ]; then
export HADOOP_OPTS="$HADOOP_OPTS -XX:NewRatio=12 -Xmx12288m -Xms10m -XX:MaxHeapFreeRatio=40 -XX:MinHeapFreeRatio=15 -XX:+useParNewGC -XX:-useGCOverheadLimit"
else
export HADOOP_OPTS="$HADOOP_OPTS -XX:NewRatio=12 -Xmx12288m -Xms10m -XX:MaxHeapFreeRatio=40 -XX:MinHeapFreeRatio=15 -XX:-useGCOverheadLimit"
fi
fi

6.    指定された時間内にガベージコレクションが成功しなかった場合、Hive は OutOfMemoryError 例外をスローします。制限時間を削除するには、-XX:-UseGCOverheadLimit を削除するか、-XX:+UseGCOverheadLimit に置き換えます。必要に応じて、 -XX:-UseGCOverheadLimit を変更して、ガベージコレクションの新しい時間制限を指定します。詳細については、Java ドキュメントの並列コレクターを参照してください。

7.    Hive クエリを再度実行します。実行時に Hive がターミナルでヒープスペースエラーをスローし、hive.log または hive-server2.log にエラーがない場合は、Hive クライアントのメモリが不足している可能性があります。例:

Transaction isolation: TRANSACTION_REPEATABLE_READ
0: jdbc:hive2://emr-analytics_master.abc.aws.> select id, name, x.* from mydb.location a, curated_admin.nxpepnd1_tpn_prvdr_pra_fclt b, curated_admin.test_table c where a.test = b._id and a._id = b._id and b._prod_id = c.prod_f_id;
#
# java.lang.OutOfMemoryError: Java heap space
# -XX:OnOutOfMemoryError="kill -9 %p"
#   Executing /bin/sh -c "kill -9 27745"...
Killed

8.    このエラーを解決するには、クライアントメモリを増やしてから、クエリを再度実行します。

9.    Hive が引き続き OutOfMemoryError 例外をスローする場合は、クライアントに対して次のステップを実行します。

Beeline:

デフォルトでは、Beeline は 出力関係全体をバッファしてから、stdoutに出力しようとします。この動作は、出力関係が大きい場合に OutOfMemoryError 例外を発生させ可能性があります。Beeline で OutOfMemoryError 例外を解決するには、次のコマンドを使用して Beeline を起動し、Hive クエリを再試行します。

beeline --incremental=true

SQL Workbench/J:

32 ビット Java ランタイム環境 (JRE) では、アプリケーションはデフォルトで最大 1 GB のメモリを使用できます。64 ビット JRE では、アプリケーションはデフォルトで使用可能な物理メモリの最大 65% を使用できます。アプリケーションで使用できるメモリの量を確認するには、[ヘルプ] を選択し、[バージョン情報] を選択します。

  • macOS の場合は、必要に応じて Info.plist ファイルの -Xmx1024m 値を増やします。Info.plist は通常、/Applications/SQLWorkbenchJ2.app/Contents ディレクトリにあります。例えば、アプリケーションで使用できるメモリ容量を 2 倍にするには、その値を -Xmx1024m から -Xmx2048m に変更します。次に、クエリを再度実行します。
  • Windows の場合はINI ファイルを作成しvm.heapsize.preferred パラメータを INI ファイルに追加して、アプリケーションで使用できるメモリの量を増やします。

シェルスクリプトまたはバッチスクリプトを使用している場合は、SQL Workbench/J をインストールするときに使用可能なメモリを増やすことができます。以下の例のコマンドは、インストール中に 3 GB の使用可能なメモリを作成します。

java -Xmx3g -jar sqlworkbench.jar

注: OutOfMemoryError 例外が hive-server2 や Hive CLI ではなくクライアント側にある場合は、出力を Amazon Simple Storage Service (Amazon S3) または HDFS に保存します。クエリの結果を表示するのに Beeline または SQL Workbench/J を使用しないでください。

Hive の再起動

hive-site.xml または hive-env.sh の Hive プロパティを変更した場合、更新された設定を有効にするには Hive を再起動する必要がある場合があります。

Amazon EMR リリースバージョン 4.7.0 以降の場合:

1.    SSH を使用してマスターノードに接続します

2.    メタストアを再起動します。

sudo stop hive-hcatalog-server
sudo start hive-hcatalog-server
sudo status hive-hcatalog-server

注: sudo restart hive-hcatalog-server コマンドを使用してメタストアの再起動を試みないでください。

3.    hive-server2 を再起動します。

sudo stop hive-server2
sudo start hive-server2
sudo status hive-server2

Amazon EMR リリースバージョン 4.0~4.6:

1.    SSH を使用してマスターノードに接続します

2.    メタストアを再起動します。

sudo stop hive-metastore
sudo start hive-metastore
sudo status hive-metastore

3.    hive-server2 を再起動します。

sudo stop hive-server2
sudo start hive-server2
sudo status hive-server2