对于hdfs来说,系统的压力主要集中在namenode

  如果在整个hadoop集群中存在大量的小文件,会消耗namenode的大量内存(大概146B一个元数据)

另一方面,如果小文件过多,有没有开启combine inputformat,在进行split分片的时候,会产生大量的map,严重影响到mapred的利用率。

定期对小文件进行清理就会变得很必要,比如我会每天有报表来获取hive中表的信息,比如文件量最多的,文件最小的,占空间最大的,

然后根据需要选择需要合并的表。

hive小文件合并思路_第1张图片

合并时考虑以下几个方法:

1.har

hdfs自带的打包工具,类似于tar,不过用起来不是特别方便,适用于归档(不太常用的历史数据)。

2.insert overwrite table xxx  select xxxx

这是一个maponly的job,通过设置combine相关的参数,可以实现对小文件的压缩和合并

这里我是使用了自己开发的python程序来实现的,具体的思路:

1)从元数据中获取需要合并的分区的名称和location,表结构等信息

2)创建备份表(表结构和源表一致,location自定义),通过设置hive的参数,并调用insert overwrite table xxx select xxx来把对应分区写到备份表中

具体的参数如下:

        set mapred.max.split.size=25000000;
        set mapred.min.split.size.per.node=10000000;
        set hive.hadoop.supports.splittable.combineinputformat=true;
        set mapred.min.split.size.per.rack=10000000;
        set hive.exec.compress.output=true;
        set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec;
        set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

3)清洗完成后,对比前后表的count,如果一致则进行hdfs层面的文件delete和mv操作

3.自定义mapred 

用java代码实现mapred,来进行文件的合并。

网上有个例子可以借鉴下:

https://github.com/edwardcapriolo/filecrush