一、小文件形成的原因:
(1)动态分区插入数据,产生大量的小文件,从而导致 map 数量剧增;
(2)reduce 数量越多,小文件也越多,reduce 的个数和输出文件个数一致;
(3)数据源本身就是大量小文件;
二、小文件的危害:
(1)在 HDFS 中,每个文件均按块存储,每个文件在 NameNode 中存储大约占 150 个字节,与块大小无关,如果小文件过多,则会耗尽 NameNode 中的大多数内存。
(2)从 Hive 角度看,小文件过多也会影响 MR 的执行任务的数量,一个小文件会开启一个 MapTask,同时一个 map 会开一个 JVM 去执行, 任务过多则会导致频繁的开启关闭,浪费大量的资源,严重影响性能。
三、解决小文件问题常见方法:
解决小文件问题的本质就是将小文件进行合并,可以通过以下几种方式解决小文件问题:
1. 使用 hive 自带的 concatenate 命令,自动合并小文件
2. 调整参数减少 Map 数量、Reduce 数量
(1)减少 map 数量:执行 Map 前可以对小 文件进行合并,使用 CombineHiveInputFormat,它底层是 haddoop 的 CombineFileInputFormat 方法,此方法可以在 mapper 中将多个文件合成一个 split 作为输入
(2)减少 Reduce 数量:Reduce 的个数决定输出的文件的个数,所以可以调整 Reduce 的个数来控制 hive 表的文件数量。hive 中的分区函数 distribute by 正好是控制 MR 中 partition 分区的,所以通过设置 reduce 数量,再结合分区函数让数据均衡的进入每个 reduce 即可。
3. 使用 Hadoop Archive(HAR)将小文件进行归档:使用 Hadoop 自带的 HAR 将小文件进行归档,将多个小文件打包成一个 HAR 文件,这样 NameNode 中的元数据也就存储一份。在减少 namenode 内存使用的同时,仍然可以对文件进行透明的访问。