原创

小文件危害及处理


小文件危害及处理

1.HDFS小文件处理

影响:

1)存储层面

​ 1个文件块,大约占namenode 150个字节,128G大概能存储9亿个文件块(小文件会大量占用)

2)计算层面

每个小文件都会生成一个MapTask,占用了大量的计算支援

解决:

1)采用har归档方式,将小文件归档;

2)采用CombineTextInputFormat;

3)有小文件场景开启JVM重用;如果没有小文件,不要开启JVM重用,因为会一直占用使用到的task卡槽,直到任务完成才释放。

JVM重用可以使得JVM实例在同一个job中重新使用N次,N的值可以在Hadoop的mapred-site.xml文件中进行配置。通常在10-20之间

<property>

  <name>mapreduce.job.jvm.numtasks</name>

  <value>10</value>

  <description>
  How many tasks to run per jvm,if set to -1 ,there is  no limit
  </description>

</property>  

2.Hive上的小文件问题

​ 现象1:

输入文件过多,而Hive对文件创建的总数是有限制的,这个限制取决于参数:hive.exec.max.created.files,默认值是10000。如果现在你的表有60个分区,然后你总共有2000个map,在运行的时候,每一个mapper都会创建60个文件,对应着每一个分区,所以60*2000> 120000,就会报错:exceeds 100000.Killing the job 。最简单的解决办法就是调大hive.exec.max.created.files参数。但是如果说数据文件只有400G,那么你调整这个参数比如说40000。平均下来也就差不多每一个文件10.24MB,这样的话就有40000多个小文件,不是一件很好的事情。

方案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:

hive执行中间过程生成的文件过多

方案2:

设置中间过程合并参数 

-- 在Map-only的任务结束时合并小文件

hive.merge.mapfiles = true

-- 在Map-Reduce的任务结束时合并小文件

hive.merge.mapredfiles = true

-- 合并文件的大小

hive.merge.size.per.task = 25610001000

-- 当输出文件的平均大小小于该值时,启动一个独立的map-reduce任务进行文件merge

hive.merge.smallfiles.avgsize=16000000

现象3:

hive结果文件过多

方案3:
 
 设置 reducer 参数 (一种是调整reducer个数,另一种是调整reducer大小)
 -- 设置reduce的个数

set mapreduce.job.reduces=500;
insert into table xxx
select
  *
from
 xxx
distribute by rand();

-- 设置reduce的大小
set hive.exec.reducers.bytes.per.reducer=5120000000;
insert into table xxx
select
  *
from
 xxx
distribute by rand();

-- distribute by rand()保证了reduce中的数据随机分配,大小大致相同
hadoop
Hive
  • 作者:刘智豪(联系作者)
  • 发表时间:2020-03-24
  • 版权声明:自由转载-非商用-保持署名(创意共享3.0许可证)
  • 公众号转载:请在文末添加作者公众号二维码
  • 评论