简体   繁体   English

使用 hive.optimize.sort.dynamic.partition 选项避免单个文件

[英]Avoid single file with hive.optimize.sort.dynamic.partition option

I'm using hive.我正在使用蜂巢。

When I write dynamic partitions with INSERT query and turn on hive.optimize.sort.dynamic.partition option( SET hive.optimize.sort.dynamic.partition=true ), always there is single file in each partition.当我使用 INSERT 查询编写动态分区并打开 hive.optimize.sort.dynamic.partition 选项( SET hive.optimize.sort.dynamic.partition=true )时,每个分区中始终只有一个文件。

But if I turn of that option( SET hive.optimize.sort.dynamic.partition=false ), I got out of memory exception like this.但是,如果我关闭该选项( SET hive.optimize.sort.dynamic.partition=false ), SET hive.optimize.sort.dynamic.partition=false出现这样的内存不足异常。

TaskAttempt 3 failed, info=[Error: Error while running task ( failure ) : attempt_1534502930145_6994_1_01_000008_3:java.lang.RuntimeException: java.lang.OutOfMemoryError: Java heap space
        at org.apache.hadoop.hive.ql.exec.tez.TezProcessor.initializeAndRunProcessor(TezProcessor.java:194)
        at org.apache.hadoop.hive.ql.exec.tez.TezProcessor.run(TezProcessor.java:168)
        at org.apache.tez.runtime.LogicalIOProcessorRuntimeTask.run(LogicalIOProcessorRuntimeTask.java:370)
        at org.apache.tez.runtime.task.TaskRunner2Callable$1.run(TaskRunner2Callable.java:73)
        at org.apache.tez.runtime.task.TaskRunner2Callable$1.run(TaskRunner2Callable.java:61)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.security.auth.Subject.doAs(Subject.java:422)
        at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1836)
        at org.apache.tez.runtime.task.TaskRunner2Callable.callInternal(TaskRunner2Callable.java:61)
        at org.apache.tez.runtime.task.TaskRunner2Callable.callInternal(TaskRunner2Callable.java:37)
        at org.apache.tez.common.CallableWithNdc.call(CallableWithNdc.java:36)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.OutOfMemoryError: Java heap space
        at org.apache.parquet.column.values.dictionary.IntList.initSlab(IntList.java:90)
        at org.apache.parquet.column.values.dictionary.IntList.<init>(IntList.java:86)
        at org.apache.parquet.column.values.dictionary.DictionaryValuesWriter.<init>(DictionaryValuesWriter.java:93)
        at org.apache.parquet.column.values.dictionary.DictionaryValuesWriter$PlainBinaryDictionaryValuesWriter.<init>(DictionaryValuesWriter.java:229)
        at org.apache.parquet.column.ParquetProperties.dictionaryWriter(ParquetProperties.java:131)
        at org.apache.parquet.column.ParquetProperties.dictWriterWithFallBack(ParquetProperties.java:178)
        at org.apache.parquet.column.ParquetProperties.getValuesWriter(ParquetProperties.java:203)
        at org.apache.parquet.column.impl.ColumnWriterV1.<init>(ColumnWriterV1.java:83)
        at org.apache.parquet.column.impl.ColumnWriteStoreV1.newMemColumn(ColumnWriteStoreV1.java:68)
        at org.apache.parquet.column.impl.ColumnWriteStoreV1.getColumnWriter(ColumnWriteStoreV1.java:56)
        at org.apache.parquet.io.MessageColumnIO$MessageColumnIORecordConsumer.<init>(MessageColumnIO.java:184)
        at org.apache.parquet.io.MessageColumnIO.getRecordWriter(MessageColumnIO.java:376)
        at org.apache.parquet.hadoop.InternalParquetRecordWriter.initStore(InternalParquetRecordWriter.java:109)
        at org.apache.parquet.hadoop.InternalParquetRecordWriter.<init>(InternalParquetRecordWriter.java:99)
        at org.apache.parquet.hadoop.ParquetRecordWriter.<init>(ParquetRecordWriter.java:100)
        at org.apache.parquet.hadoop.ParquetOutputFormat.getRecordWriter(ParquetOutputFormat.java:327)
        at org.apache.parquet.hadoop.ParquetOutputFormat.getRecordWriter(ParquetOutputFormat.java:288)
        at org.apache.hadoop.hive.ql.io.parquet.write.ParquetRecordWriterWrapper.<init>(ParquetRecordWriterWrapper.java:67)
        at org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat.getParquerRecordWriterWrapper(MapredParquetOutputFormat.java:128)
        at org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat.getHiveRecordWriter(MapredParquetOutputFormat.java:117)
        at org.apache.hadoop.hive.ql.io.HiveFileFormatUtils.getRecordWriter(HiveFileFormatUtils.java:286)
        at org.apache.hadoop.hive.ql.io.HiveFileFormatUtils.getHiveRecordWriter(HiveFileFormatUtils.java:271)
        at org.apache.hadoop.hive.ql.exec.FileSinkOperator.createBucketForFileIdx(FileSinkOperator.java:619)
        at org.apache.hadoop.hive.ql.exec.FileSinkOperator.createBucketFiles(FileSinkOperator.java:563)
        at org.apache.hadoop.hive.ql.exec.FileSinkOperator.createNewPaths(FileSinkOperator.java:867)
        at org.apache.hadoop.hive.ql.exec.FileSinkOperator.getDynOutPaths(FileSinkOperator.java:975)
        at org.apache.hadoop.hive.ql.exec.FileSinkOperator.process(FileSinkOperator.java:715)
        at org.apache.hadoop.hive.ql.exec.Operator.forward(Operator.java:897)
        at org.apache.hadoop.hive.ql.exec.SelectOperator.process(SelectOperator.java:95)
        at org.apache.hadoop.hive.ql.exec.tez.ReduceRecordSource$GroupIterator.next(ReduceRecordSource.java:356)
        at org.apache.hadoop.hive.ql.exec.tez.ReduceRecordSource.pushRecord(ReduceRecordSource.java:287)
        at org.apache.hadoop.hive.ql.exec.tez.ReduceRecordProcessor.run(ReduceRecordProcessor.java:317)
]], Vertex did not succeed due to OWN_TASK_FAILURE, failedTasks:1 killedTasks:299, Vertex vertex_1534502930145_6994_1_01 [Reducer 2] killed/failed due to:OWN_TASK_FAILURE]Vertex killed, vertexName=Map 1, vertexId=vertex_1534502930145_6994_1_00, diagnostics=[Vertex received Kill while in RUNNING state., Vertex did not succeed due to OTHER_VERTEX_FAILURE, failedTasks:0 killedTasks:27, Vertex vertex_1534502930145_6994_1_00 [Map 1] killed/failed due to:OTHER_VERTEX_FAILURE]DAG did not succeed due to VERTEX_FAILURE. failedVertices:1 killedVertices:1

I guess this exception raised because reducer write to many partitions simultaneously.我猜这个异常是因为 reducer 同时写入许多分区而引发的。 But I can't find how to control that.但我找不到如何控制它。 And I followed this article , but it doesn't help me.我关注了这篇文章,但这对我没有帮助。

My environment is it:我的环境是这样的:

  • AWS EMR 5.12.1 AWS EMR 5.12.1
  • Use tez as execution engine使用 tez 作为执行引擎
  • hive version is 2.3.2, and tez version is 0.8.2 hive 版本是 2.3.2,tez 版本是 0.8.2
  • HDFS Block size is 128MB HDFS 块大小为 128MB
  • There are about 30 dynamic partitions to write with INSERT query使用 INSERT 查询可以写入大约 30 个动态分区

Here is my sample query.这是我的示例查询。

SET hive.exec.dynamic.partition.mode=nonstrict;
SET hive.optimize.sort.dynamic.partition=true;
SET hive.exec.reducers.bytes.per.reducer=1048576;
SET mapred.reduce.tasks=300;
FROM raw_data
INSERT OVERWRITE TABLE idw_data
  PARTITION(event_timestamp_date)
  SELECT
    *
  WHERE 
    event_timestamp_date BETWEEN '2018-09-09' AND '2018-10-09' 
DISTRIBUTE BY event_timestamp_date
;

distribute by partition key helps with OOM issue, but this configuration may cause each reducer writing the whole partition, depending on hive.exec.reducers.bytes.per.reducer configuration, which can be set very high value by default, like 1Gb. distribute by partition key有助于解决 OOM 问题,但此配置可能会导致每个 reducer 写入整个分区,具体取决于hive.exec.reducers.bytes.per.reducer配置,默认情况下可以设置非常高的值,例如 1Gb。 distribute by partition key may cause additional reduce stage, the same does hive.optimize.sort.dynamic.partition . distribute by partition key可能会导致额外的减少阶段, hive.optimize.sort.dynamic.partition也是hive.optimize.sort.dynamic.partition

So, to avoid OOM and achieve maximum performance:因此,为了避免 OOM 并实现最大性能:

  1. add distribute by partition key at the end of your insert query, this will cause the same partition keys to be processed by the same reducer(s).在插入查询的末尾添加distribute by partition key ,这将导致相同的reducer 处理相同的分区键。 Alternatively, or in addition to this setting, you can use hive.optimize.sort.dynamic.partition=true或者,除了此设置之外,您还可以使用hive.optimize.sort.dynamic.partition=true
  2. set hive.exec.reducers.bytes.per.reducer to the value which will trigger more reducers if there are too much data in one partition.hive.exec.reducers.bytes.per.reducer设置为如果一个分区中有太多数据将触发更多减速器的值。 Just check what is current value of hive.exec.reducers.bytes.per.reducer and reduce or increase it accordingly to get proper reducer parallelism.只需检查hive.exec.reducers.bytes.per.reducer当前值并相应地减少或增加它以获得适当的减速器并行度。 This setting will determine how much data single reducer will process and how many files per partition will be created.此设置将决定单个 reducer 将处理多少数据以及每个分区将创建多少文件。

Example:例子:

set hive.exec.reducers.bytes.per.reducer=33554432;

insert overwrite table partition (load_date)
select * from src_table
distribute by load_date;

See also this answer about controlling the number of mappers and reducers: https://stackoverflow.com/a/42842117/2700344另请参阅有关控制映射器和减速器数量的答案: https : //stackoverflow.com/a/42842117/2700344

Finally I found what's wrong.最后我发现了什么问题。

First of all, execution engine was tez.首先,执行引擎是 tez。 mapreduce.reduce.memory.mb option was not help. mapreduce.reduce.memory.mb选项没有帮助。 You should use hive.tez.container.size option.您应该使用hive.tez.container.size选项。 When write dynamic partition, reducer open multiple record writers.写入动态分区时,reducer 打开多个记录写入器。 Reducer need enough memory to write multiple partitions simultaneously. Reducer 需要足够的内存来同时写入多个分区。

If you use hive.optimize.sort.dynamic.partition option, global partition sorting is run but sorting means there are reducers.如果您使用hive.optimize.sort.dynamic.partition选项,则运行全局分区排序,但排序意味着有减速器。 In this case, if there isn't another reducer tasks, each partition is processed by one reducer.在这种情况下,如果没有另一个 reducer 任务,每个分区都由一个 reducer 处理。 Thats why there is only one file in partition.这就是为什么分区中只有一个文件。 DISTRIBUTE BY make more reduce tasks, so it can make more files in each partition, but there is same memory problem. DISTRIBUTE BY 做更多的reduce 任务,所以它可以在每个分区中创建更多的文件,但存在相同的内存问题。

Consequently, containers memory size is really important!因此,容器内存大小非常重要! Don't forgot use hive.tez.container.size option to change tez container memory size!不要忘记使用hive.tez.container.size选项来更改 tez 容器内存大小!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM