HDFS中小文件产生的原因以及解决

小文件产生的原因:

1、实时处理:比如我们使用 Spark Streaming 从外部数据源接收数据,然后经过 ETL 处理之后存储到 HDFS 中,这种情况下在每个 Job 中会产生大量的小文件。
2、hive中对表执行insert into 操作,每次插入数据都在表目录下形成一个小文件,这个小文件就是MR任务reduce端的输出文件。
解决:insert overwrite into table t_new as select * from t_old;
如下面所有的文件都是某个表中的数据,但是却有多个小文件:
在这里插入图片描述
3、hive中执行简单过滤操作,符合过滤条件的数据存在很多block块中,只走map,map输出有很多小文件。
开启map端的聚合。
4、mapreduce正常执行产生小文件。
将mapreduce输出不直接写hdfs,而是写入到hbase中。
设置map端文件合并及reduce端文件合并。
5、输入数据文件为小文件。
小文件合并后再计算。
CombineFileInputFormat: 它是一种新的inputformat,用于将多个文件合并成一个单独的 split切片,另外,它会考虑数据的存储位置。
或者 :CombineHiveInputFormat

设置map输入合并小文件的相关参数:

//每个Map最大输入大小(这个值决定了合并后文件的数量)
set mapred.max.split.size=256000000;  
//一个节点上split的至少的大小(这个值决定了多个DataNode上的文件是否需要合并)
set mapred.min.split.size.per.node=100000000;
//一个交换机下split的至少的大小(这个值决定了多个交换机上的文件是否需要合并)  
set mapred.min.split.size.per.rack=100000000;
//执行Map前进行小文件合并
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; 

设置map输出和reduce输出进行合并的相关参数:

//设置map端输出进行合并,默认为true
set hive.merge.mapfiles = true
//设置reduce端输出进行合并,默认为false
set hive.merge.mapredfiles = true
//设置合并文件的大小
set hive.merge.size.per.task = 256*1000*1000
//当输出文件的平均大小小于该值时,启动一个独立的MapReduce任务进行文件merge。
set hive.merge.smallfiles.avgsize=16000000

小文件的影响:

影响:
1、文件的元数据存储在namenode中,每个文件的元数据都差不多大,小文件过多会极大的占用namonode
的内存,制约集群的扩展。(主要影响)
2、在对小文件进行处理的时候,一个小文件对应一个maptask,一个maptask会开启一个JVM进程,JVM处理一个maptask后会关闭,这样JVM开关的时间会比处理maptask的时间更长,严重浪费了资源,因为进程的开启销毁会严重性能。(可以开启JVM重用)
3.HDFS读写小文件时也会更加耗时,因为每次都需要从NameNode获取元信息,并且对应的DataNode建立连接

解决方案:

1.采用har 归档的方式:
Hadoop Archive或者HAR,是一个高效地将小文件放入HDFS块中的文件存档工具,它能够将多个小文件打包成一个HAR文件,这样在减少namenode内存使用的同时,仍然允许对文件进行透明的访问。
2.Sequence file
sequence file由一系列的二进制key/value组成,如果为key小文件名,value为文件内容,则可以将大批小文件合并成一个大文件。
3.开启JVM重用:前提条件task必需属于同一个job

  • 表示属于同一job的排队按顺序执行的task可以共享一个JVM,也就是说第二轮的map可以重用前一轮的JVM,而不是第一轮结束后关闭JVM,第二轮再启动新的JVM。

  • 如果设置成-1,那么只要是同一个job的task(无所谓多少个),都可以按顺序在一个JVM上连续执行。

  • 如果task属于不同的job,那么JVM重用机制无效,不同job的task需要不同的JVM来运行。

#默认是1,表示一个JVM上最多可以顺序执行的task数目(属于同一个Job)是1。也就是说一个task启一个JVM。
 hive> set  mapred.job.reuse.jvm.num.tasks=20;  
 hive> set hive.exec.parallel=true; # 开启同步执行hive的多个阶段,hive在执行过程,将一个查询转化成一个或者多个阶段。

设置reducer 个数
设置 hive.exec.reducers.bytes.per.reducer(默认为1GB)(总输入数据量),
受hive.exec.reducers.max(默认为999)(参数1)影响:

 hive>mapred.reduce.tasks = min ( 参数2,总输入数据量/参数1 )
  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值