小文件如何产生
- hive的底层存储是HDFS,默认的块大小是128M,通常小于默认块大小,HDFS默认也算一个block, 所以产生小文件主要有以下几种:
- 1、
数据源本身
就包含有大量的小文件。 - 2、使用spark/flink实时写hive时,根据业务的时间窗口(10s,20s)落地hive表,产生很多小文件。
- 3、采用
动态分区
也会产生很多小文件。 - 4、
reduce的个数输出
。默认reduce个数和落地hive文件个数一样。
小文件带来的影响
- 1、从Hive的角度看,
小文件会开很多map
,一个map开一个JVM去执行,所以这些任务的初始化,启动,执行会浪费大量的资源,严重影响性能。 - 2、HDFS存储太多小文件, 会导致
namenode元数据特别大
, 占用太多内存, 查询效率降低。
- HDFS的文件元信息,包括位置、大小、分块信息等,都是保存在NameNode的内存中的。每个对象大约占用150个字节,因此一千万个文件及分块就会占用约3G的内存空间,一旦接近这个量级,NameNode的性能就会开始下降了。
解决方案
已有的小文件
- 1.使用hadoop archive命令把小文件进行归档。
set hive.archive.enabled=true;
set hive.archive.har.parentdir.settable=true;
set har.partfile.size=1099511627776;
ALTER TABLE srcpart ARCHIVE PARTITION(ds='2021-09-08', hr='12');
ALTER TABLE srcpart UNARCHIVE PARTITION(ds='2021-09-08', hr='12');
set mapred.reduce.tasks=100;
小文件的产生途径
set mapred.max.split.size=256000000;
set mapred.min.split.size.per.node=100000000;
set mapred.min.split.size.per.rack=100000000;
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
set hive.merge.mapfiles = true;
set hive.merge.mapredfiles = true;
set hive.merge.size.per.task = 134217728;
set hive.merge.smallfiles.avgsize=16000000;
set mapred.job.priority = NORMAL;
set hive.exec.compress.intermediate = true;
set hive.merge.mapfiles=true;
set hive.merge.mapredfiles = true;
set hive.merge.size.per.task = 134217728;
set hive.merge.smallfiles.avgsize=134217728;
set hive.exec.orc.default.block.size=134217728;
set hive.merge.orcfile.stripe.level=false;
set hive.support.concurrency=false;
set hive.support.quoted.identifiers=none;
insert overwrite table ${hivevar:item_table} partition (dt='${hivevar:item_date}')
select `(dt)?+.+`
from ${hivevar:item_table}
where dt='${hivevar:item_date}'
distribute by rand();
- 使用sequencefile作为表存储形式,不要使用textfile,在一定程度上可以减少小文件
参考