对于hdfs来说,系统的压力主要集中在namenode
如果在整个hadoop集群中存在大量的小文件,会消耗namenode的大量内存(大概146B一个元数据)
另一方面,如果小文件过多,有没有开启combine inputformat,在进行split分片的时候,会产生大量的map,严重影响到mapred的利用率。
定期对小文件进行清理就会变得很必要,比如我会每天有报表来获取hive中表的信息,比如文件量最多的,文件最小的,占空间最大的,
然后根据需要选择需要合并的表。
合并时考虑以下几个方法:
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