解决HDFS小文件带来的计算问题

hive优化

### 一.小文件简述 #### 1.1. HDFS上什么是小文件? HDFS存储文件时的最小单元叫做Block,Hadoop1.x时期Block大小为64MB,Hadoop2.x时期Block大小为128MB。(在hadoop部署下可以通过dfs.block.size进行设置) 小文件就是指,在HDFS上落地的文件大小远远小于一个Block块大小的文件。 #### 1.2. 小文件形成的原因 #### 1.3. 小文件的危害 * **内存占用** 小文件存储在HDFS上,对应的每个文件都会在namenode中存有相应的元数据信息(在namenode的内存中均被表示为一个对象(object)).如果每一个文件的元数据信息占用内存100byte,那么有10万个文件, 就占用了namenode10G的内存空间 * **数据查询** HDFS对小文件的读取, 涉及到磁盘读取, 同时涉及到从跨datanode的文件查询(Reading through small files normally causes lots of seeks and lots of hopping from datanode to datanode to retrieve each small file) * **任务启动** 在hadoop上进行数据计算时,每一个小文件都要对应一个task,每一个task也要对应的申请slot。task启动阶段会耗费大量的时间在任务资源申请和释放上。

二. 小文件的处理方式

2.1. HDFS上现存的小文件

问题 : HDFS集群上目前存在的大量小文件
解决 : 不定期调用HDFS和sync()方法 和 append()方法, 整理小文件生成大文件

2.2. MapReduce上的小文件

上面已经描述过,一个文件对应启动一个mapTask,则小文件太多,会带来相应的很多问题。处理方式如下:

2.2.1. Hadoop Archive(略)
2.2.2. Sequence File(略)
2.2.3. CombineFileInputFormat方法

思路主要是, 将几个小文件合并在一起, "打包"提供给Task进行计算, 避免一个文件启动一个Task。
具体说来就是: Hadoop内置了CombineFileInputFormat类专门用于处理小文件, 将HDFS上多个小文件合并成一个InputSplit, 然后启用一个map来处理这个InputSplit。
这个环节主要包含如下的几个参数的使用:

mapreduce.input.fileinputformat.split.minsize.per.node
mapreduce.input.fileinputformat.split.minsize.per.rack
mapreduce.input.fileinputfornat.split.maxsize

mapreduce.input.fileinputfornat.split.maxsize参数说明

  • 如果未进行设置, 默认就会将同一个机架上的所有小文件组成一个InputSplit, 交由一个MapTask处理。
  • 如果进行了设置, 同一个节点(node)上的文件会组成一个InputSplit

2.3. Hive上的小文件

2.3.1. 输入文件多的解决方案

设置mapper输入文件合并的参数如下:

## Mapper执行前进行小文件合并
hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
## 每一个mapper最大的输入大小
mapred.max.split.size = 256000000
## 一个节点上split的至少的大小(这个值决定了多个DataNode上的文件是否需要合并)
mapred.min.split.size.per.node = 100000000
## 一个机架下split的至少的大小(这个值决定了该机架下的文件是否需要合并)
mapred.min.split.size.per.rack = 100000000
2.3.2. 输出文件过多(包括中间过程和输出结果)
## Map-only的任务结束时合并小文件(map-only应该就是只有map阶段没有reduce阶段吧)
hive.merge.mapfiles = true
## 在Map-reduce的任务结束时合并小文件
hive.merge.mapredfiles = true (默认是false)
## 控制合并文件的大小
hive.merge.size.per.task = 25610001000
## 当输出文件的平均大小小于该值时,启动一个独立的map-reduce任务进行文件merge
hive.merge.smallfiles.avgsize = 16000000
2.3.3. 生成的结果文件多的另一种折中处理

对reducer进行调整 a.调整reducer个数 b.调整reducer大小

## 设定reducer个数
set mapred.reduce.tasks = 50;
## 设定reduce的大小
set hive.exec.reducers.bytes.per.reducer = 512000000

ps:Hive对创建的文件总数是有限制的, 通过hive.exec.max.created.files参数进行控制(默认是10000).如果hive表有100个分区, 1000个mapper, 则总共创建的文件数就会是100*1000 = 100000, 任务执行阶段就会触发exceeds 100000.Killing the job的错误, 进行 hive.exec.max.created.files参数的放大可解决这个错误, 但同时会导致小文件。

posted @ 2019-10-13 10:53  NirvanaInFire  阅读(574)  评论(0编辑  收藏  举报