欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

hive中小文件的产生原因 如何合并小文件 以及控制Map个数,增加/缩小map个数,

程序员文章站 2022-07-14 19:50:07
...

小文件产生原因

  • Hive的后端存储是HDFS,它对大文件的处理是非常高效的,如果合理配置文件系统的块大小,NameNode可以支持很大的数据量。但是在数据仓库中,越是上层的表其汇总程度就越高,数据量也就越小。而且这些表通常会按日期进行分区,随着时间的推移,HDFS的文件数目就会逐渐增加。

小文件带来的问题

  • 简单来说,HDFS的文件元信息,包括位置、大小、分块信息等,都是保存在NameNode的内存中的。每个对象大约占用150个字节,因此一千万个文件及分块就会占用约3G的内存空间,一旦接近这个量级,NameNode的性能就会开始下降了
    此外,HDFS读写小文件时也会更加耗时,因为每次都需要从NameNode获取元信息,并与对应的DataNode建立连接。对于MapReduce程序来说,小文件还会增加Mapper的个数,每个脚本只处理很少的数据,浪费了大量的调度时间。当然,这个问题可以通过使用CombinedInputFile和JVM重用来解决。

Hive小文件产生的原因
前面已经提到,汇总后的数据量通常比源数据要少得多。而为了提升运算速度,我们会增加Reducer的数量,Hive本身也会做类似优化——Reducer数量等于源数据的量除以hive.exec.reducers.bytes.per.reducer所配置的量(默认1G)。Reducer数量的增加也即意味着结果文件的增加,从而产生小文件的问题。
解决小文件的问题可以从两个方向入手:

  1. 输入合并。即在Map前合并小文件
  2. 输出合并。即在输出结果的时候合并小文件

两种方式控制Map数:即减少map数和增加map数

  • 背景:首先同时可执行的map数是有限的。
    •通常情况下,作业会通过input的目录产生一个或者多个map任务
    •主要的决定因素有: input的文件总个数,input的文件大小。
    •举例
    a) 假设input目录下有1个文件a,大小为780M,那么hadoop会将该文件a分隔成7个块(block为128M,6个128m的块和1个12m的块),从而产生7个map数

b) 假设input目录下有3个文件a,b,c,大小分别为10m,20m,130m,那么hadoop会分隔成4个块(10m,20m,128m,2m),从而产生4个map数

减少map数可以通过合并小文件来实现,这点是对文件数据源来讲。

可以通过以下方法来在map执行前合并小文件,减少map数:(查询多文件的时候合并)

set mapred.max.split.size=100000000;              相当于100M  ----每个Map最大输入大小,决定合并后的文件数----

set mapred.min.split.size.per.node=100000000; ----一个节点上split的至少的大小 ,决定了多个data node上的文件是否需要合并----

set mapred.min.split.size.per.rack=100000000; ----一个交换机下split的至少的大小,决定了多个交换机上的文件是否需要合并---

set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; 

     ----执行Map前进行小文件合并----

set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;这个参数表示执行前进行小文件合并,前面三个参数确定合并文件块的大小,大于文件块大小128m的,按照128m来分隔,小于128m,大于100m的,按照100m来分隔,把那些小于100m的(包括小文件和分隔大文件剩下的)

增加map数的可以通过控制上一个job的reduer数来控制

合并MapReduce操作
•Multi-group by:当从同一个源表进行多次查询时用。
•Multi-group by是Hive的一个非常好的特性,它使得Hive中利用中间结果变得非常方便
•FROM log
• insert overwrite table test1 select log.id group by log.id
• insert overwrite table test2 select log.name group by log.name
• 上述查询语句使用了Multi-group by特性连续group by了2次数据,使用不同的group by key。这一特性可以减少一次MapReduce操作。

最后我们可以通过一些配置项来使Hive在执行结束后对结果文件进行合并:

hive.merge.mapfiles 在map-only job后合并文件,默认true
hive.merge.mapredfiles 在map-reduce job后合并文件,默认false
hive.merge.size.per.task 合并后每个文件的大小,默认256000000
hive.merge.smallfiles.avgsize 平均文件大小,是决定是否执行合并操作的阈值,默认16000000

set hive.merge.mapredfiles=true;
set hive.merge.smallfiles.avgsize=100000000;