使用Hive SQL插入动态分区的Orc表OOM异常分析

259 阅读3分钟

一、问题描述

执行语句‘insert into table xxx partition(dt) select …’ 向ORC格式的表中插入数据时报错:

1、'PHYSICAL' memory limit.

pid=21694,containerID=container_e122_1623983552034_0002_01_000279 is running 276889600B beyond the 'PHYSICAL' memory limit. Current usage: 16.3 GB of 16 GB physical memory used; 19.5 GB of 33.6 GB virtual memory used. Killing container.

2、java.lang.OutOfMemoryError: Java heap space

Error: Error while running task ( failure ) : java.lang.OutOfMemoryError: Java heap space

二、问题解决思路

1、解决'PHYSICAL' memory limit.

调整Tez Container Size

由原先16G 调整至20GB,解决了'PHYSICAL' memory limit问题,但是执行过程中报了另外的oom问题,参考第一章第2点。

2、解决java.lang.OutOfMemoryError: Java heap space

解决java.lang.OutOfMemoryError: Java heap space这个用异常花费时长较多,因为没有太多有用信息,先进行内存相关的调整:

调整:mapreduce.map.memory.mb 由4g调整至8g

调整:mapreduce.reduce.memory.mb由4g调整至8g

调整:mapreduce.map.java.opts 由-Xmx3276m调整至-Xmx6553m

调整:mapreduce.reduce.java.opts 由-Xmx3276m调整至-Xmx6553m

上述参数仍然报oom,后调整为16g依然报oom异常。

调整一下方向,拆分HSQL语句:

仅执行select …部分,查询没有问题。

执行insert into table xxx partition(dt) select …加上限制取1/2数据,依然报oom

执行insert into table xxx partition(dt) select …加上限制取1/4数据,依然报oom

后限制1/10执行插入成功。

问题成功定位,数据插入过程中map任务task内存不足,但是不可能无限增加内存,而且数据量并不大,还需要另辟蹊径。

查阅资料:

hive Insert to Dynamic Partition query Generating ... - Cloudera Community - 244855icon-default.png?t=LA92https://community.cloudera.com/t5/Community-Articles/hive-Insert-to-Dynamic-Partition-query-Generating-too-many/ta-p/244855

Hive on Tez Performance Tuning - Determining Reduc... - Cloudera Community - 245680icon-default.png?t=LA92https://community.cloudera.com/t5/Community-Articles/Hive-on-Tez-Performance-Tuning-Determining-Reducer-Counts/ta-p/245680

使用Hive SQL插入动态分区的Parquet表OOM异常分析 - 云+社区 - 腾讯云icon-default.png?t=LA92https://cloud.tencent.com/developer/article/1079007

启用hive.optimize.sort.dynamic.partition 参数后,问题得到解决

最终关键参数:

Tez Container Size 20g

For Map Join, per Map memory threshold 3822m

Map Memory 4g

Reduce Memory 4g

Sort Allocation Memory 2047m

MR Map Java Heap Size -Xmx3276m

MR Reduce Java Heap Size -Xmx3276m

Sort Partitions Dynamically true

hive.map.aggr false

如有需要可以在HSQL临时配置相关参数

三、问题思考

参考:使用Hive SQL插入动态分区的Parquet表OOM异常分析 - 云+社区 - 腾讯云icon-default.png?t=LA92https://cloud.tencent.com/developer/article/1079007

> show partitions  test5;

> show create table test5;

ORC是列式批处理文件格式,格式要求在写入文件之前将批次的行(batches of rows)缓存在内存中。在执行INSERT语句时,动态分区目前实现是:至少为每个动态分区目录打开一个文件写入器(file writer)。由于缓冲区是按分区维护,因此在运行时所需的内存量随着分区数量的增加而增加。所以会导致mappers或reducers的OOM,具体取决于打开的文件写入器(file writer)的数量。

通过INSERT语句插入数据到动态分区表中,也可能会超过HDFS同时打开文件数的限制。

如果没有join或聚合,INSERT ... SELECT…语句会被转换为map任务作业。mapper任务会读取输入记录然后将它们发送到目标分区目录。在这种情况下,每个mapper必须为遇到的每个动态分区创建一个新的文件写入器(file writer),mapper在运行时所需的内存量随着分区数量的增加而增加。