小文件的影响:
如果有1千万个小文件,每个文件占用一个block,则NameNode大约需要3GB内存空间,如果存储1亿个小文件,则NameNode需要30GB内存空间。
其次,读写大量小文件的速度要远远小于读写几个大文件的速度,因为要频繁与NameNode交互导致NameNode处理队列过长和GC时间过长而产生延迟。
故随着小文件的增多会严重影响到NameNode性能和制约集群的扩展。
设定参数
set hive.merge.mapfiles = true ##在 map only 的任务结束时合并小文件
set hive.merge.mapredfiles = false ## true 时在 MapReduce 的任务结束时合并小文件
set hive.merge.size.per.task = 256*1000*1000 ##合并文件的大小
set mapred.max.split.size=256000000; ##每个 Map 最大分割大小
set mapred.min.split.size.per.node=1; ##一个节点上 split 的最少值
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; ##执行 Map 前进行小文件合并
小注:
推荐的命令 hdfs dfs <args>,而不是hadoop dfs
hadoop fs <args> 当您处理不同的文件系统(如本地FS,HFTP FS,S3 FS等)时,可以使用它
hdfs dfs <args> 即适用于与HDFS相关的所有操作
-- 合并小文件 方案一----mapreduce--------------------------
第1步:创建一个tmp目录
hadoop fs -mkdir tmp
第2步:在某个时间点将所有小文件移至tmp目录
hadoop fs -mv input/*.txt tmp
第3步-在hadoop-streaming jar的帮助下合并小文件
hadoop jar $HADOOP_HOME/share/hadoop/tools/lib/hadoop-streaming-2.6.0.jar \
-Dmapred.reduce.tasks=1 \
-input "/user/abc/input" \
-output "/user/abc/output" \
-mapper cat \
-reducer cat
第4步,将输出移至输入文件夹 ############直接这一步不行?
hadoop fs -mv output/part-00000 input/large_file.txt
第5步-删除输出
hadoop fs -rm -R output/
第6步-从tmp中删除所有文件
hadoop fs -rm tmp/*.txt
****上面的综合*** 参考来源*https://www.it1352.com/1595924.html*
#!/bin/bash
/home/abc/hadoop-2.6.0/bin/hadoop fs -mv input/*.txt tmp
wait
/home/abc/hadoop-2.6.0/bin/hadoop jar /home/abc/hadoop-2.6.0/share/hadoop/tools/lib/hadoop-streaming-2.6.0.jar \
-Dmapred.reduce.tasks=1 \
-input "/user/abc/input" \
-output "/user/abc/output" \
-mapper cat \
-reducer cat
wait
/home/abc/hadoop-2.6.0/bin/hadoop fs -mv output/part-00000 input/large_file.txt
wait
/home/abc/hadoop-2.6.0/bin/hadoop fs -rm -R output/
wait
/home/abc/hadoop-2.6.0/bin/hadoop fs -rm tmp/*.txt
********
* * * * * /bin/bash /home/abc/mergejob.sh > /dev/null 2>&1
-- 方案二-小批量--转存本地合并
https://zhuanlan.zhihu.com/p/211463589
hdfs dfs -copyFromLocal world.txt /baihe
hdfs dfs -copyFromLocal world2.txt /baihe
hdfs dfs -getmerge /baihe/ local_largefile.txt #存到本地了需要再上传
方案三--小批量操作
-- 合并小文件 方案三 ,数据量非常大的情况下可能不太适合,最好使用MapReduce来合并。
[hadoop@node01 ~]$ hdfs dfs -cat /baihe/* | hdfs dfs -appendToFile - /tmp/hdfs_largefile.txt
方案四-存档
-- 合并小文件 方案四-存档-------存档文件的源文件及目录都不会自动删除,需要手动删除,不压缩(为副本文件),需mr\yarn支持、不可修改、不会减少读取时的map数
主要作用:减少namenode内存使用
[hadoop@node01 ~]$ hadoop archive
archive -archiveName <NAME>.har -p <parent path> [-r <replication factor>]<src>* <dest>
hadoop archive -archiveName 0825.har -p /test/in/ small mapjoin /test/in/har #small mapjoin 为/test/in/ 下的目录
-archiveName .har 指定归档后的文件名
-p 被归档文件所在的父目录
* 归档的目录结构
归档后存在归档文件的目录
可以通过参数 -D har.block.size 指定HAR的大小
创建归档文件,将 hdfs /baihe 目录下的文件归档到 /user/hadoop 目录下的 myhar.har中
-- 合并小文件 ---------------end---------------------------------------------