大数据平台小文件统计及合并
一、小文件统计
1. 统计方法
将namenode 的镜像文件导入hive表,通过sql查询即可统计小文件数量情况。
查看镜像文件: oiv
hdfs oiv -p 文件类型 -i 镜像文件 -o 转换后文件输出路径
1.导出镜像文件:
hdfs dfsadmin -fetchImage /home/bigdata/fsimage/fsimage_$date
2.解析镜像文件为 "," 逗号分割的csv文件
hdfs oiv -p Delimited -delimiter , -t temporaryDir -i /home/bigdata/fsimage/fsimage_$date -o /home/bigdata/fsimage/fsimage_$date.csv
3.删除csv文件第一行表头信息: Path,Replication,ModificationTime,AccessTime,PreferredBlockSize,BlocksCount,FileSize,NSQUOTA,DSQUOTA,Permission,UserName,GroupName
sed -i '1d' /home/bigdata/fsimage/fsimage_$date.csv
4.导入hive表
4-1. 创建hive分区表(按时间分区):按照导出的表头创建hive表 CREATE TABLE default.fsimage_info_csv( path string , replication int, modificationtime string, accesstime string, preferredblocksize bigint, blockscount int, filesize bigint, nsquota string, dsquota string, permission string, username string, groupname string) partitioned by (createdate string) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe' WITH SERDEPROPERTIES ( 'field.delim'=',' , 'serialization.format'=',' ) STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'; 4-2. 将镜像文件数据导入hive表: sql="load data local inpath '/home/bigdata/fsimage/fsimage_$date.csv' into table default.fsimage_info_csv partition(createdate='$date')" hive -e $sql
2. 统计
1.统计hdfs镜像记录中小于60M的文件
通过统计小文件,发现主要是hive表落盘数据小文件较多;有的表达到每日增量4000多小文件;
2.测试目录数据删除( /tmp目录和特殊目录 )
/tmp 目录下 48000个文件,占用空间4211220.19 M(4T)
FSIMG_FILE_STATIC.LEVEL | FSIMG_FILE_STATIC.PATH | FSIMG_FILE_STATIC.SMALL_FILE_NUM | FSIMG_FILE_STATIC.FILE_NUM | FSIMG_FILE_STATIC.SUM_SMALL_FILE_SIZE | FSIMG_FILE_STATIC.SUM_FILE_SIZE | FSIMG_FILE_STATIC.CREATEDATE |
---|---|---|---|---|---|---|
3 | /apps/hive/warehouse | 11076979 | 11479387 | 14698785.20 | 102354870.38 | 20220818 |
3 | /app-logs/root/logs-ifile | 304869 | 304984 | 153710.04 | 281023.66 | 20220818 |
3 | /data/monitor/source | 103105 | 365064 | 2111568.50 | 90465815.04 | 20220818 |
3 | /data/monitor/checkpoint | 49155 | 49155 | 598.46 | 598.46 | 20220818 |
二、小文件合并策略调研
小文件影响:
在HDFS中,任何一个文件,目录或者block在NameNode节点的内存中均以一个对象表示(元数据),而这受到NameNode物理内存容量的限制。每个元数据对象约占150byte,所以如果有1千万个小文件,每个文件占用一个block,则NameNode大约需要15G空间。如果存储1亿个文件,则NameNode需要150G空间,这毫无疑问1亿个小文件是不可取的.
小文件合并方案:
hdfs文件系统中的文件分为下面几类:
-
数据中心落盘文件
-
hive 数据文件
-
系统应用文件
经过技术调研发现均可以用har对hdfs上的文件进行归档。 以下是对小文件合并做的一些实验操作。
实验1. 文件追加合并小文件
1.将hdfs /tmp/test/目录下的part-0-7.gz追加到 part-1-8.gz 文件:(appendToFile)
执行命令:
hdfs dfs -cat /tmp/test/part-0-7.gz | hdfs dfs -appendToFile - /tmp/test/part-1-8.gz
2.追加命令执行成功,part-1-8.gz文件大小为28.1M(16.7M+11.3M两个文件之和 )
3.下载该part-1-8.gz文件并解压到本地,查看内容:
hdfs dfs -cat /tmp/test/part-1-8.gz | zcat > append_m3_xian.txt
追击后的文件行数与两个文件行数之和一致。
适用范围:
-
适合hdfs 普通文件或压缩文件;
-
hive orc格式的不支持(追加后hive查询会报错)
-
操作不够简单
实验2. har 归档方式
在HDFS之上构建一个分层文件系统。通过执行hadoop archive 命令可以创建一个HAR文件。hadoop Archive是一个高效地将小文件放入HDFS块中的文件存档文件格式,它通过将多个小文件打包成一个后缀为.har文件来减少HDFS中的文件数量。
上图为HAR文件的文件结构,访问一个指定的小文件需要访问两层索引文件才能获取小文件在HAR文件中的存储位置,因此,访问一个HAR文件的效率可能会比直接访问HDFS文件要低。
对于一个mapreduce任务来说,如果使用HAR文件作为其输入,仍旧是其中每个小文件对应一个map task,效率低下。所以,HAR files最好是用于文件归档。
上图为Hadoop存档目录,其中包含元数据(以index和masterindex的形式)和数据(part- *)文件。 _index文件包含作为归档文件一部分的文件名以及这些文件内的位置。
归档命令会转换成一个mapreduce 任务;
1)归档特点:
1、存档文件的源文件目录以及源文件都不会自动删除需要手动删除 2、存档的过程实际是一个mapreduce过程,所以需要需要hadoop的mapreduce的支持 3、存档文件本身不支持压缩 4、存档文件一旦创建便不可修改,要想从中删除或者增加文件,必须重新建立存档文件 5、创建存档文件会创建原始文件的副本,所以至少需要有与存档文件容量相同的磁盘空间 6、要归档的文件名中不能有空格,否则会抛出异常,可以将空格用其他符号替换(使用-Dhar.space.replacement.enable=true 和-Dhar.space.replacement参数)。 7、对于一个mapreduce任务来说,如果使用HAR文件作为其输入,仍旧是其中每个小文件对应一个map task,效率低下。所以,HAR files最好是用于文件归档。
2)归档操作说明:
1.归档命令:
归档文件: hadoop archive -archiveName m3_monitor.har -p /tmp/test/archive_test/m3_monitor/20220809 /tmp/test/archive 删除数据源目录: hdfs dfs -rm -r /tmp/test/archive_test/m3_monitor/20220809 查看归档文件: hdfs dfs -ls -R har:///tmp/test/archive/m3_monitor.har 解归档:将归档文件内容拷贝到另一个目录: hdfs dfs -cp har:///tmp/test/archive/m3_monitor.har/part-1-7.gz /tmp/test/
参考链接:
实验3. hive 表使用 hive har 进行小文件合并
1)使用appendToFile合并hive orc文件(不支持合并操作)--不可用
hdfs dfs -cat /tmp/test/hive/000203_0 | hdfs dfs -appendToFile - /tmp/test/hive/000204_0
加载进入hive后: 执行查询操作报错;
hive> select * from ods.tb_bu_dc_monitor_day_bak1; OK Failed with exception java.io.IOException:java.lang.IllegalArgumentException: Buffer size too small. size = 262144 needed = 1206453 Time taken: 0.166 seconds
2)使用hive concatenate (外部表不可用,内部表可用,orc可用)
使用方式:
#1.设置文件最小大小(需要设置,否则合并操作可能会不理想): SET mapreduce.input.fileinputformat.split.maxsize=256 #对于非分区表 alter table A concatenate; #2.对于分区表 alter table B partition(day=20201224) concatenate;
使用限制:
-
不支持外部表,只支持内部表;
-
concatenate 命令只支持 RCFILE 和 ORC 文件类型。
-
使用concatenate命令合并小文件时不能指定合并后的文件数量,但可以多次执行该命令参考链接。
-
当多次使用concatenate后文件数量不再变化,这个跟参数
mapreduce.input.fileinputformat.split.minsize=256mb
的设置有关,可设定每个文件的最小size。
3)使用hive har 归档命令
#用来控制归档是否可用 set hive.archive.enabled=true; #通知Hive在创建归档时是否可以设置父目录 set hive.archive.har.parentdir.settable=true; #控制需要归档文件的大小 set har.partfile.size=1099511627776; #使用以下命令进行归档 ALTER TABLE A ARCHIVE PARTITION(dt='2022-02-24', hr='12'); #对已归档的分区恢复为原文件 ALTER TABLE A UNARCHIVE PARTITION(dt='2022-02-24', hr='12');
ALTER TABLE default.tb_bu_dc_monitor_day_bak_manage ARCHIVE partition(dc_code='wgq_monitor',data_date='20220820');
ALTER TABLE default.tb_bu_dc_monitor_day_bak_manage UNARCHIVE PARTITION(dc_code='wgq_monitor',data_date='20220820');
归档后文件: 分区数据目录下只有一个dat.har文件,原来的数据文件都被删除。
解归档后:分区目录下的dat.har文件删除,新增了原来的数据文件。
4.网上的脚本做小文件合并的:
hdfs小文件使用fsimage分析实例_Direction_Wind的博客-CSDN博客_hdfs小文件分析
filecrush/bin at master · asdaraujo/filecrush · GitHub 开源代码;
三、小文件合并方案总结
目前大数据平台hdfs数据存储情况:
数据仓库中的表: 1.stg层是把flink应用程序写入的数据load进入的; 2.ods层表名称中包含ai的表是从mysql导入的; /_SCRATCH0 这些目录是sqoop 把mysql数据导入hive时生成的临时目录,可以删除。 3.stg 和 ods 的 tb_bu_dc_monitor_day 是外部表,其他层的表都是内部表; 4.stg层是原始数据,没有经过压缩处理,ods及以后其他各层都是orc格式 flink程序落盘数据路径: /data/monitor/source 是各个数据中心指标的落盘数据;
1.hive表使用hive归档命令来进行压缩;
2.flink落盘数据 使用har归档;
四、小文件优化:
hive表数据mapreduce操作落盘做参数优化,对落盘文件大小进行限制。
目前hive使用的是默认的16M
SET hive.exec.dynamic.partition=true; #使用动态分区 SET hive.exec.dynamic.partition.mode=nonstrict; #默认值为srticat,nonstrict模式表示允许所有分区字段都可以使用动态分区 SET hive.exec.max.dynamic.partitions=3000; #在所有执行MR的节点上,共可以创建多少个动态分区 SET hive.exec.max.dynamic.partitions.pernode=500; #在执行MR的单节点上,最大可以创建多少个分区 SET hive.merge.tezfiles=true; #tez任务结束时合并小文件 SET hive.merge.smallfiles.avgsize=1280000000; #当输出文件平均大小小于该值时。启用独立的TEZ任务进行文件合并 SET hive.merge.size.per.task=1280000000; #合并文件大小128M ———————————————— 版权声明:本文为CSDN博主「Impl_Sunny」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/u011487470/article/details/120970962