Amazon EMR에서 Hive가 쿼리 결과를 출력할 때 발생하는 "OutOfMemoryError" Hive Java 힙 공간 예외를 해결하려면 어떻게 해야 합니까?

최종 업데이트 날짜: 2020년 5월 18일

Amazon EMR에서 Apache Hive 쿼리를 실행하고 있습니다. Hive에서 쿼리 결과를 출력하는 동안 OutOfMemoryError 예외가 발생합니다. 이 오류를 해결하려면 어떻게 해야 합니까?

간략한 설명

OutOfMemoryError 예외는 일반적으로 INSERT OVERWRITE 명령 도중 hive-server2, Hive 메타스토어 또는 클라이언트 측에서 힙 공간이 충분하지 않을 때 발생합니다. 이 문제를 해결하려면 JVM에 대한 최대 메모리 할당을 늘리거나 HADOOP_HEAPSIZE를 늘리십시오.

해결 방법

다음 솔루션 중 하나 이상을 사용하여 OutOfMemoryError 예외를 해결합니다.

참고: 이 해결 방법은 Apache Tez 컨테이너 메모리 튜닝 중에 발생하는 OutOfMemoryError 예외는 다루지 않습니다.

JVM의 최대 메모리 할당 증가

Hive 셸을 시작하면 기본적으로 1GB의 메모리가 할당됩니다. 최대 메모리 할당은 -Xmx 파라미터로 정의됩니다. 프로세스가 최댓값보다 많은 값을 사용하려고 하면 Hive에서 프로세스가 종료되고 OutOfMemoryError 예외가 발생합니다. 이 문제를 해결하려면 Hive 셸 스크립트에서 -Xmx값(MB)을 늘린 다음 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를 늘립니다. 기본값은 1,000입니다. 사용 사례에 맞게 늘립니다. 그런 다음 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.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비트 JRE(Java 런타임 환경)에서 애플리케이션은 기본적으로 최대 1GB의 메모리를 사용할 수 있습니다. 64비트 JRE에서 애플리케이션은 기본적으로 사용 가능한 물리적 메모리의 최대 65%를 사용할 수 있습니다. 애플리케이션에 사용 가능한 메모리 양을 확인하려면 [도움말]을 선택한 다음 [정보]를 선택합니다.

  • macOS의 경우 필요에 따라 Info.plist 파일에서 -Xmx1024m 값을 늘립니다. Info.plist는 일반적으로 /Applications/SQLWorkbenchJ2.app/Contents 디렉터리에 있습니다. 예를 들어, 애플리케이션에 사용 가능한 메모리 양을 두 배로 늘리려면 값을 -Xmx1024m에서 -Xmx2048m으로 변경합니다. 그런 다음 쿼리를 다시 실행합니다.
  • Windows의 경우 INI 파일을 생성한 다음 vm.heapsize.preferred 파라미터를 INI 파일에 추가하여 애플리케이션에 사용할 수 있는 메모리 양을 늘립니다.

셸 또는 배치 스크립트를 사용하는 경우 SQL Workbench/J를 설치할 때 사용 가능한 메모리를 늘릴 수 있습니다. 다음 예제의 명령은 설치 중에 사용 가능한 메모리를 3GB 생성합니다.

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