hive压缩之小文件合并,


Hive压缩之二 小文件合并

 

调研背景

当Hive输入由很多个小文件组成,由于每个小文件都会启动一个map任务,如果文件过小,以至于map任务启动和初始化的时间大于逻辑处理的时间,会造成资源浪费,甚至OOM。为此,当我们启动一个任务,发现输入数据量小但任务数量多时,需要注意在Map前端进行输入合并。当然,在我们向一个表写数据时,也需要注意输出文件大小。

输入合并

合并输入小文件,减少map数?

主要的决定因素有: input的文件总个数,input的文件大小,集群设置的文件块大小。

举例:
a)    假设input目录下有1个文件a,大小为780M,那么hadoop会将该文件a分隔成7个块(6个128m的块和1个12m的块),从而产生7个map数

b)   假设input目录下有3个文件a,b,c,大小分别为10m,20m,130m,那么hadoop会分隔成4个块(10m,20m,128m,2m),从而产生4个map数即,如果文件大于块大小(128m),那么会拆分,如果小于块大小,则把该文件当成一个块。

 

假设一个SQL任务:

        Select count(1) from mb_test where date = ‘2015-01-19’  and hour = 0;

该任务的/user/hive/warehouse/naga.db/mb_test/date=2015-01-19/hour=0共有10个文件,每个文件大小为3.15M,远小于128M的小文件,总大小31.5M,正常执行会用10个map任务。

        而实际上只生成了一个map任务

set mapred.max.split.size=100000000;
        set mapred.min.split.size.per.node=100000000;
        setmapred.min.split.size.per.rack=100000000;
        sethive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

结论是此处的的合并是逻辑上的合并,而Hive默认已经做了输入合并,我们不需要作过多的设置。

 

输出合并

合并输出小文件。输出时,若是太多小文件,每个小文件会与一个block进行对应,而block存在的意义是为了方便在namenode中存储,那么过多的block将会充斥namenode的表中,待集群规模增大和运行次数增大,那么维护block的表将会过大,严重降低namenode性能。


set hive.merge.mapfiles = true #在Map-only的任务结束时合并小文件
set hive.merge.mapredfiles = true #在Map-Reduce的任务结束时合并小文件
set hive.merge.size.per.task = 256*1000*1000 #合并文件的大小
set hive.merge.smallfiles.avgsize=16000000 #当输出文件的平均大小小于该值时,启动一个独立的map-reduce任务进行文件merge

 

我们执行以下语句:

insert overwrite table naga.mb_time selectticks string,starttime bigint, endtime bigint from naga.mb_pageinfo where  starttime%10 = 7;

 

该语句将大表通过设定条件starttime%10 = 7选择三个字段存入小表中,观察执行的map数量和目标文件个数:

如下图,在整个运算job中会开启两个map

而只产生了一个目标文件/user/hive/warehouse/naga.db/mb_time/000000_0,

从上图中看出我们的设置生效,不会产生两个更小的文件

几个参数指标

hive.merge.mapfiles

是否在Map-only的任务结束时合并小文件

true

true

Hive无

hive.merge.mapredfiles

是否在Map-Reduce的任务结束时合并小文件

false

true

Hive无

hive.merge.size.per.task

合并目标文件的大小

256000000

256000000

Hive无

hive.merge.smallfiles.avgsize

当输出文件的平均大小小于该值时,启动一个独立的map-reduce任务进行文件merge

16000000

5000000

Hive无

 

我们要做的就是设置hive.merge.smallfiles.avgsize , 这里建议设置为5000000 = 5M , 即当输出文件的平均大小小于该值时,启动一个独立的map-reduce任务进行文件merge

相关内容

    暂无相关文章