hive 小文件过多解决方案
  TEZNKK3IfmPf 2023年11月12日 25 0

一、小文件产生原因

hive 中的小文件是向 hive 表中导入数据时产生,所以先看下向 hive 中导入数据的几种方式

1.直接向表中插入数据

​​insert into table test1  values (1,'aa',67),(2,'bb',87);

2.通过load方式加载数据

load data local inpath '/root/score.csv' overwrite into table test1  -- 导入文件

load data local inpath '/root/score' overwrite into table test1   -- 导入文件夹

使用 load 方式可以导入文件或文件夹,当导入一个文件时,hive表就有一个文件,当导入文件夹时,hive表的文件数量为文件夹下所有文件的数量

3.通过查询方式加载数据

insert overwrite table test1  select id,name,score from test2;

这种方式是生产环境中常用的,也是最容易产生小文件的方式

insert 导入数据时会启动 MR 任务,MR中 reduce 有多少个就输出多少个文件

  • 文件数量=ReduceTask数量*分区数

也有很多简单任务没有reduce,只有map阶段,则

  • 文件数量=MapTask数量*分区数

每执行一次 insert 时hive中至少产生一个文件,因为 insert 导入时至少会有一个MapTask。


二、小文件过多产生的影响

  1. 首先对底层存储HDFS来说,HDFS本身就不适合存储大量小文件,小文件过多会导致namenode元数据特别大, 占用太多内存,严重影响HDFS的性能

  2. 对 hive 来说,在进行查询时,每个小文件都会当成一个块,启动一个Map任务来完成,而一个Map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的Map数量是受限的。


三、怎么解决小文件过多

1. 使用 hive 自带的 concatenate 命令,自动合并小文件

  • 先执行一次insert ,插入两条数据

0: jdbc:hive2://hdp101:2181,hdp103:2181,hdp10>  insert into table test1  values (1,'aa',67),(2,'bb',87);
  •  打印的日志

hive 小文件过多解决方案

  •  HDFS 文件夹下形成的文件

hive 小文件过多解决方案

  • 执行 insert 三次,test1  表下面会有三个小文件

hive 小文件过多解决方案

  • 使用 concatenate 进行合并
0: jdbc:hive2://hdp101:2181,hdp103:2181,hdp10> alter  table test1 concatenate;

hive 小文件过多解决方案

2. 调整参数减少Map数量

  • 设置map输入合并小文件的相关参数

#执行Map前进行小文件合并
#CombineHiveInputFormat底层是 Hadoop的 CombineFileInputFormat 方法
#此方法是在mapper中将多个文件合成一个split作为输入
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; -- 默认

#每个Map最大输入大小(这个值决定了合并后文件的数量)
set mapred.max.split.size=256000000;   -- 256M

#一个节点上split的至少的大小(这个值决定了多个DataNode上的文件是否需要合并)
set mapred.min.split.size.per.node=100000000;  -- 100M

#一个交换机下split的至少的大小(这个值决定了多个交换机上的文件是否需要合并)
set mapred.min.split.size.per.rack=100000000;  -- 100M
  • 设置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;   -- 256M

# 当输出文件的平均大小小于该值时,启动一个独立的MapReduce任务进行文件merge
set hive.merge.smallfiles.avgsize=16000000;   -- 16M
  • 启用压缩

# hive的查询结果输出是否进行压缩
set hive.exec.compress.output=true;

# MapReduce Job的结果输出是否使用压缩
set mapreduce.output.fileoutputformat.compress=true;

3. 减少Reduce的数量

reduce 的个数决定了输出的文件的个数,所以可以调整 reduce 的个数控制 hive 表的文件数量,hive中的分区函数 distribute by 正好是控制MR中 partition 分区的,然后通过设置 reduce 的数量,结合分区函数让数据均衡的进入每个 reduce 即可。

#设置reduce的数量有两种方式,第一种是直接设置reduce个数
set mapreduce.job.reduces=10;

#第二种是设置每个reduce的大小,Hive会根据数据总大小猜测确定一个reduce个数
set hive.exec.reducers.bytes.per.reducer=5120000000; -- 默认是1G,设置为5G
【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月12日 0

暂无评论

推荐阅读
  TEZNKK3IfmPf   2023年11月14日   22   0   0 Hive
  TEZNKK3IfmPf   2023年11月14日   20   0   0 mysqlHive
  TEZNKK3IfmPf   2023年11月14日   31   0   0 Hive视图
  TEZNKK3IfmPf   2023年11月14日   21   0   0 hadoopHive
  TEZNKK3IfmPf   2024年04月26日   63   0   0 hadoopHive
TEZNKK3IfmPf