什么是小文件
Spark官方的推荐文档中,parquet格式的文件的推荐大小是128M,小于该值的文件均可以称为小文件。但在实际工作中,小文件的定义不是这么绝对,可能存在文件大小是几百MB,但是文件数量会有几万个,此时,对于这些几百M的文件,对于我们来讲也是小文件。
小文件带来的问题
- 任务执行时间长
- 占用NameNode内存资源,影响NameNode性能
- 占用计算资源,无论是Hive还是Spark,每一个小文件都需要对应一个Map程序
小文件产生的原因
- 启用了动态分区,往动态分区表插入数据时,会插入大量小文件
- reduce的数量设置过大,从而产生大量小文件
3.源数据就有大量的小文件
什么是小文件合并
小文件合并的字面意思就是通过某种操作,将一系列小文件合并成大文件。目前通用的大数据系统,都习惯用KV键值对来处理文件,最后文件落盘时,也是一个reduce对应一个输出文件。
MapReduce的中间会有一个shuffle的过程,合并小文件就是通过一个shuffle过程,将小文件合并成一个大文件。基于这个思路,合并的方式可以有两种:
- 计算中已存在shuffle过程,那么我们可以人为控制输出文件的个数
- 强制触发shuffle,合并小文件
小文件合并的方法
1.设置参数
- 每个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最大输入大小(这个值决定了合并后文件的数量)
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端输出进行合并,默认为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
-- spark 设置
-- 设置合并文件的大小
set spark.sql.hive.merge.size.per.task = 1073741824
-- 当输出文件的平均大小小于该值时,启动一个独立的MapReduce任务进行文件merge。
set spark.sql.hive.merge.smallfile.size =134217728
--设置reduce端输出进行合并,默认为false
set spark.sql.hive.mergeFiles.enable = true
- group by
如果SQL中有group by 算子,我们只需要设置如下参数:
set spark.sql.shuffle.partition=10
- repartition()/coalesce()
select /*+ repartition(10) */ * from tbl;
select /*+ coalesce(10) */ * from tbl;
网友评论