Hadoop小文件问题
小文件是指比HDFS默认块大小明显小得多的文件。
小文件导致了什么问题
对于存储层来说,大量小文件会产生大量的元数据信息;当NN重启时,必须将元数据信息加载到内存中,大量元数据信息会导致NN重启速度非常慢;并且,太多小文件也会导致NN在DN耗尽磁盘空间之前就先耗尽内存的元数据空间。同时,更多文件意味着更多的读写请求,这可能最终堵塞NN的容量,增加RPC队列和处理延迟,意味着性能下降。以及,在进行文件读写的时候,寻址速度高于读写速度,效率低下。
对于应用层来说,MR或Spark在计算这些小文件的时候性能低下。对于MR来说,一个文件需要启动一个Map Task去处理,浪费资源;对于Spark来说也是类似,在Spark中,每个map相当于Spark任务在执行器中每次读取和处理一个分区,每个分区默认是一个block。小文件会导致大量的分区以至于大量的任务开销。
产生小文件可能的原因
- 大量的map/reduce任务:如果有大量的map/reduce任务,在HDFS上生成的文件基本与map的数量(对于map only而言),或reduce的数量成正比。
- 过度分区表:是指每个分区的数据量很小的Hive表。
- Spark过度并行化:在Spark作业中,Spark分区越多,写入的文件就越多。
Hadoop小文件的解决方案
-
从数据源头解决,在数据采集的时候,就将小文件或小批数据合并成大文件后再上传到HDFS。
-
从存储角度解决,使用Hadoop Archive,这是一个高效将小文件放入HDFS块的文件存档工具,可以将小文件打包成一个har文件,从而减少NN内存使用。
-
从计算角度解决,采用CombineTextInputFormat的切片方式,将多个小文件在切片过程中生成一个单独的切片或少量的切片。
或者开启uber模式,实现jvm的重用。也就是让同一个job的多个task运行在一个jvm中。
Hive小文件问题
Hive中也存在小文件问题,本质上也是Hadoop的小文件问题。
产生的原因
hive中的小文件大概率是导入数据时产生的,通常在生产环境中,一般会使用insert select的方式导入数据,这样会启动MR任务,那么reduce有多少个就会有多少个文件输出。也就是insert每执行一次至少有一个文件,就很容易出现小文件问题。
解决的方案
- 使用hive自带的concatenate命令,自动合并小文件;不过需要注意的是这个命令只支持rcFile和ORC。
- 在MR过程中合并小文件,在inputformat的时候设置为combinehiveinputfor,这个底层就是combinefileinputformat方法。在map后reduce前,设置合并小文件hive.merge.mapfiles;在reduce后合并小文件hive.merge.mapredfiles;
- 或者直接设置少一定的reduce数量
- 最后也可以参考hadoop处理小文件,用hadoop archive归档。