如何在 Hive 输出查询结果时解决 Amazon EMR 上的“OutOfMemoryError”Hive Java 堆空间异常?

4 分钟阅读
0

我在 Amazon EMR 上运行 Apache Hive 查询。Hive 在输出查询结果时引发 OutOfMemoryError 异常。

简短描述

OutOfMemoryError 异常通常在 hive-server2、Hive 元存储或客户端没有足够的堆空间时在 INSERT OVERWRITE 命令期间发生。要解决此问题,请增加 JVM 的最大内存分配或提高 HADOOP_HEAPSIZE。

解决方法

使用以下一个或多个解决方案解决 OutOfMemoryError 异常。

**注意:**这些解决方法不涵盖在 Apache Tez 容器内存优化期间发生的 OutOfMemoryError 异常。

增加 JVM 的最大内存分配

当您启动 Hive shell 时,默认会分配 1 GB 内存。最大内存分配由 -Xmx 参数定义。如果进程尝试使用超过最大值的内存,则 Hive 会尝试终止该进程并引发 OutOfMemoryError 异常。要解决此问题,请在 Hive shell 脚本中增大 -Xmx 值(单位 MB),然后再次运行 Hive 查询。

识别日志中的 OutOfMemoryError

检查您的日志位置是否存在以下错误(例如:/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,如下例中所示。您还可以使用进行 hive-env 分类的 Amazon EMR 重新配置 API 增加 HADOOP_HEAPSIZE。默认值是 1000。根据使用案例的需要增加它。然后,再次运行 Hive 查询。

export HADOOP_HEAPSIZE=2048

**重要提示:**重启这些服务后,此设置将应用于 hive-server2、Hive 元存储和 Hive CLI。(可选)您可以为这些服务中的每一个设置单独的值。

创建集群时更新内存分配

Amazon EMR 提供配置 API 操作,以便在您使用配置对象更新集群时更新默认配置。根据您的使用场景更新 HADOOP_HEAPSIZE 值:

{
  "Classification": "hive-env",
  "Properties": {},
  "Configurations": [
    {
      "Classification": "export",
      "Properties": {
        "HADOOP_HEAPSIZE": "2048"
      },
      "Configurations": []
    }
  ]
}

更新正在运行的集群上的内存分配

您可以通过使用 SSHAmazon EMR 重新配置 API 连接到主模式来增加正在运行的集群上的 HADOOP_HEAPSIZE 的值。Amazon EMR 重新配置 API 仅适用于 Amazon EMR 发行版 5.21 及更高版本。如果内存更新是通过 SSH 对集群进行的,则必须重新启动 Hive 服务才能使更改生效。

Beeline 或 SQL Workbench/J

1.    如果您从 Beeline 或 SQL Workbench/J 运行相同的查询,请检查 /mnt/var/log/hive/hive-server2.loghive-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 目录下。例如,要将应用程序的可用内存量增加一倍,请将值从 -Xmx1024m 更改为 -Xmx2048m。然后,再次运行查询。
  • 对于 Windows:请创建 INI 文件,然后向该 INI 文件添加 vm.heapsize.preferred 参数,以增加应用程序的可用内存量。

如果您使用的是 Shell 脚本或批处理脚本,则可以在安装 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。重新启动 Hive-server 2 会影响集群上正在运行的查询。最佳实践是在没有查询运行时或在计划的维护时段内重新启动进程。

用于重新启动 Hive 进程的命令因 Amazon EMR 发行版本而异。有关更多信息,请参阅如何在 Amazon EMR 中重启服务?

对于 Amazon EMR 发行版 5.30 和更高版本或 6.0 和更高版本:

1.    使用 SSH 连接到主节点

2.    重启元存储:

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

3.    重启 hive-server 2:

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

对于 Amazon EMR 发行版 4.7.0 到 5.29:

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.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

相关信息

如何使用日志排查 Amazon EMR 中的 Hive 查询问题?

扩展集群资源

任务配置

AWS 官方
AWS 官方已更新 2 年前