小文件产生的原因
当文件的大小远远小于HDFS block块的大小(hadoop2:128m)就可以当作是一个小文件;具体产生的原因包括一下:
1)实时计算时,如果窗口开的小,在hdfs上会产生很多小文件
2)离线计算,批处理时,在spark或者mr时,没有设置好partition或者reduce的个数,会产生小文件
3)Flume采集数据时,没有配置好具体的滚动策略,会产生小文件
4)数据源本身存在很多小文件
小文件的影响
1)元数据影响:namenode将文件系统的元数据存放在内存中,因此存储的文件数目受限于 namenode的内存大小。HDFS中每个文件、目录、数据块 占用150Bytes。如果存放的文件数目过多的话会占用很大的内存甚至撑爆内存。而HDFS是适合存储大文件的,很小的文件如果很多的话,Name Node的压力会非常大,因为每个文件都会有一条元数据信息存储在Name Node上,小文件非常多也就意味着在Name Node上存储的元数据信息非常多。Hadoop是适合存储大数据的,所以可以通过Sequence File将小文件合并,从而获得更高效率的存储和计算。Sequence File中的Key和Value可以是任意类型的Writable或者自定义Writable类型。
2)mr任务影响:在mapreduce中,对每个文件都会启动一个map task,如果小文件太多,影响性能;
3)在hdfs的读流程里,如果小文件越多,寻址花费的时间越多
解决方法
Hive参数调优
当文件数目过多时,会给HDFS带来压力,可以通过合并Map和Reduce的输出文件来减少文件数。相关配置如下。
- hive.merge.mapfiles = true。是否合并Map阶段的输出文件,默认为true。
- hive.merge.mapredfiles = true。是否合并Reduce阶段的输出文件,默认为false
- hive.merge.size.per.task= 256000000。合并的文件的大小,默认为256000000。
- 设置hive.merge.size.per.task参数,默认256MB,是每个任务合并后文件的大小。一般设置为和HDFS集群的文件块大小一致。
使用Hadoop任务合并小文件
- 在临时目录下建立一个当前日期的任务临时目录
- 对于每个递归后的路径合并,启动一个只有map的MR任务,输出到临时目录
- 完成后把原有路径下文件move到临时目录
- 把临时目录下合并后的文件move回原路径,最后删除临时目录