-- 参考链接: https://blog.csdn.net/yycdaizi/article/details/43341239
Hive在对结果文件进行合并时会执行一个额外的map-only脚本,mapper的数量是文件总大小除以size.per.task参数所得的值,触发合并的条件是:
根据查询类型不同,相应的mapfiles/mapredfiles参数需要打开;
结果文件的平均大小需要大于avgsize参数的值。
示例:
-- map-red job,5个reducer,产生5个60K的文件。
create table dw_stage.zj_small as
select paid, count (*)
from dw_db.dw_soj_imp_dtl
where log_dt = '2014-04-14'
group by paid;
-- 执行额外的map-only job,一个mapper,产生一个300K的文件。
set hive.merge.mapredfiles= true;
create table dw_stage.zj_small as
select paid, count (*)
from dw_db.dw_soj_imp_dtl
where log_dt = '2014-04-14'
group by paid;
-- map-only job,45个mapper,产生45个25M左右的文件。
create table dw_stage.zj_small as
select *
from dw_db.dw_soj_imp_dtl
where log_dt = '2014-04-14'
and paid like '%baidu%' ;
-- 执行额外的map-only job,4个mapper,产生4个250M左右的文件。
set hive.merge.smallfiles.avgsize=100000000;
create table dw_stage.zj_small as
select *
from dw_db.dw_soj_imp_dtl
where log_dt = '2014-04-14'
and paid like '%baidu%' ;
hive对于小文件合并, 是有开关的, 分别是
hive.merge.mapredfiles
hive.merge.tezfiles
hive.merge.sparkfiles
分别用于合并mapreduce, tez或spark产生的小文件。这三个开关默认都是关的,需要手动打开
其原理是,在作业最后物理执行计划追加一个ConditionalTask.
如果作业输出的平均文件大小小于16M,即hive.merge.smallfiles.avgsize,那么就另起一道作业,做合并。自动化的。但有时候,平均是一个很坑爹的事,比如几百个空文件,加一个巨大的倾斜文件……
小文件带来的问题:
1. HDFS的文件元信息, 都是存在于NameNode内存中的, 每个对象大约占用150字节
2. 读取大量小文件会增加Mapper的个数.
=======================
在Hive查询执行时, 合并文件的时机主要有三个:
1. map输入合并
2. map输出合并
3. reduce输出合并
设置map输入合并小文件:
//每个Map最大输入大小(这个值决定了合并后文件的数量)
set mapred.max.split.size=256000000;
//一个节点上split的至少的大小(这个值决定了多个DataNode上的文件是否需要合并)
set mapred.min.split.size.per.node=100000000;
//一个交换机下split的至少的大小(这个值决定了多个交换机上的文件是否需要合并)
set mapred.min.split.size.per.rack=100000000;
//执行Map前进行小文件合并
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
设置map输出和reduce输出进行合并的相关参数:
//设置map端输出进行合并,默认为true
set hive.merge.mapfiles = true
//设置reduce端输出进行合并,默认为false
set hive.merge.mapredfiles = true
//设置合并文件的大小
set hive.merge.size.per.task = 256*1000*1000
//当输出文件的平均大小小于该值时,启动一个独立的MapReduce任务进行文件merge。
set hive.merge.smallfiles.avgsize=16000000