当前位置:   article > 正文

Hive表小文件治理方案_表的小文件

表的小文件
@Author  : Spinach | GHB
@Link    : http://blog.csdn.net/bocai8058
  • 1
  • 2

小文件是如何产生的?

  1. Reduce个数越多,产生的小文件越多;
  2. 写入hive表时,以动态分区(set hive.exec.dynamic.partition=true)形式写入时,会产生大量的小文件;
  3. 数据源本身就包含众多小文件;

为什么要治理小文件?

  1. 从Hive的角度看,小文件会开很多map,一个map开一个JVM去执行,所以这些任务的初始化,启动,执行会浪费大量的资源,严重影响性能。
  2. 从HDFS的角度看,小文件太多,会导致namenode元数据对象多,占用更多的内存,从而制约了集群的扩展。

Hive的小文件治理方案

HDFS中文件的存储是以文件块(block)的形式存储在DataNode中的,block块位置信息等元数据信息是存储在namenode中的,在实际生产中,一般block块的大小设置为256MB。具体关于block块疑问,可参考《HDFS Block块大小限定依据及原则》

  1. 设置以下参数:
## 设置map输入合并小文件的相关参数
set mapred.max.split.size=256000000;
set mapred.min.split.size.per.node=100000000;
set mapred.min.split.size.per.rack=100000000;
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

## 设置map输出和reduce输出进行合并的相关参数
set hive.merge.mapfiles=true;
set hive.merge.mapredfiles=true;
set hive.merge.size.per.task=256000000;
set hive.merge.smallfiles.avgsize=256000000;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  1. 少用动态分区,用时记得按distribute by rand() 将数据随机分配给Reduce,这样可以使得每个Reduce处理的数据大体一致,例如:
insert overwrite table tableName partition(date) select * from person DISTRIBUTE BY (rand()*3);
  • 1
  1. 针对于ORC格式存储的表,可使用concatenate命令对指定分区进行小文件合并,例如:
alter table tableName_orc partition (date="20200101") concatenate;
  • 1
  • 仅仅适用于ORC格式存储的表;
  • 使用concatenate命令合并小文件时不能指定合并后的文件数量,虽然可以多次执行该命令,但显然不够优雅。当多次使用concatenate后文件数量不在变化,这个跟参数mapreduce.input.fileinputformat.split.minsize=256mb的设定有有有关,可设定每个文件的最小size,具体见链接
  • 只能针对分区使用concatenate命令。

Spark的小文件治理方案

  1. 添加参数 .config("spark.sql.adaptive.enabled", "true")
  2. 添加repartition操作或coalesce操作;
  3. 添加sql hint暗示(/*+ REPARTITION(分区数) */),例如:
create table tableName as select /*+ REPARTITION(10) */ age,name from person where date='20200101'
insert into table tableName select /*+ REPARTITION(10) */ age,name from person where date='20200101'
insert overwrite table tableName select /*+ REPARTITION(10) */ age,name from person where date='20200101'
注意:分区数的设置根据落地数据量而定
  • 1
  • 2
  • 3
  • 4
  1. 少用动态分区,用时记得按distribute by rand() 将数据随机分配给Reduce,这样可以使得每个Reduce处理的数据大体一致,例如:
insert overwrite table tableName partition(date) select * from person DISTRIBUTE BY rand()
  • 1

对已存在的小文件治理方案

  1. 设置与【Hive的小文件治理方案】中1相同的参数;
  2. 使用hadoop archive命令把小文件进行归档;
  3. 重建表,建表时减少reduce数量;
  4. 重新读取表中数据,重新控制写入文件数,如:spark.table(dwdTableName).where(s"""statis_date='$statis_date'""").coalesce(5).distinct().write.mode(SaveMode.Overwrite).insertInto(dwdTableName)

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号