如何解決在 Hive 輸出查詢結果時 Amazon EMR 上發生的「OutOfMemoryError」Hive Java 堆積空間例外?

4 分的閱讀內容
0

我在 Amazon EMR 上執行 Apache Hive 查詢。Hive 在輸出查詢結果時擲回 OutOfMemoryError 例外。

簡短說明

當 hive-server2、Hive 中繼儲存或用戶端沒有足夠的堆積空間時,執行 INSERT OVERWRITE 命令期間通常會發生 OutOfMemoryError 例外。若要解決此問題,請增加 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.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 目錄中。例如,若要將應用程式可用的記憶體容量增加一倍,請將值從 -Xmx1024m 變更為 -Xmx2048m。然後,再次執行查詢。
  • 對於 Windows:建立 INI 檔案,然後將 vm.heapsize.preferred 參數新增至 INI 檔案,以增加應用程式可用的記憶體容量。

如果您使用的是 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 年前