本文首发于公众号:五分钟学大数据

小文件产生原因

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

  1. 直接向表中插入数据
insert into table A values (1,'zhangsan',88),(2,'lisi',61);

这种方式每次插入时都会产生一个文件,多次插入少量数据就会出现多个小文件,但是这种方式生产环境很少使用,可以说基本没有使用的

  1. 通过load方式加载数据
load data local inpath '/export/score.csv' overwrite into table A  -- 导入文件

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

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

  1. 通过查询方式加载数据
insert overwrite table A  select s_id,c_name,s_score from B;

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

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

所以, 文件数量=ReduceTask数量*分区数

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

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

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

像有的业务需要每10分钟就要把数据同步到 hive 中,这样产生的文件就会很多。

小文件过多产生的影响

  1. 首先对底层存储HDFS来说,HDFS本身就不适合存储大量小文件,小文件过多会导致namenode元数据特别大, 占用太多内存,严重影响HDFS的性能
  2. 对 hive 来说,在进行查询时,每个小文件都会当成一个块,启动一个Map任务来完成,而一个Map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的Map数量是受限的。

怎么解决小文件过多

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

使用方法:

#对于非分区表
alter table A concatenate; #对于分区表
alter table B partition(day=20201224) concatenate;

举例:

#向 A 表中插入数据
hive (default)> insert into table A values (1,'aa',67),(2,'bb',87);
hive (default)> insert into table A values (3,'cc',67),(4,'dd',87);
hive (default)> insert into table A values (5,'ee',67),(6,'ff',87); #执行以上三条语句,则A表下就会有三个小文件,在hive命令行执行如下语句
#查看A表下文件数量
hive (default)> dfs -ls /user/hive/warehouse/A;
Found 3 items
-rwxr-xr-x 3 root supergroup 378 2020-12-24 14:46 /user/hive/warehouse/A/000000_0
-rwxr-xr-x 3 root supergroup 378 2020-12-24 14:47 /user/hive/warehouse/A/000000_0_copy_1
-rwxr-xr-x 3 root supergroup 378 2020-12-24 14:48 /user/hive/warehouse/A/000000_0_copy_2 #可以看到有三个小文件,然后使用 concatenate 进行合并
hive (default)> alter table A concatenate; #再次查看A表下文件数量
hive (default)> dfs -ls /user/hive/warehouse/A;
Found 1 items
-rwxr-xr-x 3 root supergroup 778 2020-12-24 14:59 /user/hive/warehouse/A/000000_0 #已合并成一个文件

注意:

1、concatenate 命令只支持 RCFILE 和 ORC 文件类型。

2、使用concatenate命令合并小文件时不能指定合并后的文件数量,但可以多次执行该命令。

3、当多次使用concatenate后文件数量不在变化,这个跟参数 mapreduce.input.fileinputformat.split.minsize=256mb 的设置有关,可设定每个文件的最小size。

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 #执行以下语句,将数据均衡的分配到reduce中
set mapreduce.job.reduces=10;
insert overwrite table A partition(dt)
select * from B
distribute by rand(); 解释:如设置reduce数量为10,则使用 rand(), 随机生成一个数 x % 10 ,
这样数据就会随机进入 reduce 中,防止出现有的文件过大或过小

4. 使用hadoop的archive将小文件归档

Hadoop Archive简称HAR,是一个高效地将小文件放入HDFS块中的文件存档工具,它能够将多个小文件打包成一个HAR文件,这样在减少namenode内存使用的同时,仍然允许对文件进行透明的访问

#用来控制归档是否可用
set hive.archive.enabled=true;
#通知Hive在创建归档时是否可以设置父目录
set hive.archive.har.parentdir.settable=true;
#控制需要归档文件的大小
set har.partfile.size=1099511627776; #使用以下命令进行归档
ALTER TABLE A ARCHIVE PARTITION(dt='2020-12-24', hr='12'); #对已归档的分区恢复为原文件
ALTER TABLE A UNARCHIVE PARTITION(dt='2020-12-24', hr='12');

注意:

归档的分区可以查看不能 insert overwrite,必须先 unarchive

最后

如果是新集群,没有历史遗留问题的话,建议hive使用 orc 文件格式,以及启用 lzo 压缩。

这样小文件过多可以使用hive自带命令 concatenate 快速合并。

如果你想获取更多大数据相关技术文章,可关注公众号:五分钟学大数据,专注于大数据技术研究,分享高质量的原创技术文章

数仓面试高频考点--解决hive小文件过多问题的更多相关文章

  1. 彻底解决Hive小文件问题

    最近发现离线任务对一个增量Hive表的查询越来越慢,这引起了我的注意,我在cmd窗口手动执行count操作查询发现,速度确实很慢,才不到五千万的数据,居然需要300s,这显然是有问题的,我推测可能是有 ...

  2. HTML&CSS面试高频考点(二)

    HTML&CSS面试高频考点(一)    ♥ 6. W3C盒模型与怪异盒模型 标准盒模型(W3C标准) 怪异盒模型(IE标准) 怪异盒模型下盒子的大小=width(content + bord ...

  3. hive小文件合并设置参数

    Hive的后端存储是HDFS,它对大文件的处理是非常高效的,如果合理配置文件系统的块大小,NameNode可以支持很大的数据量.但是在数据仓库中,越是上层的表其汇总程度就越高,数据量也就越小.而且这些 ...

  4. spark sql/hive小文件问题

    针对hive on mapreduce 1:我们可以通过一些配置项来使Hive在执行结束后对结果文件进行合并: 参数详细内容可参考官网:https://cwiki.apache.org/conflue ...

  5. Hive小文件处理

    小文件是如何产生的: 动态分区插入数据的时候,会产生大量的小文件,从而导致map数量的暴增 数据源本身就包含有大量的小文件 reduce个数越多,生成的小文件也越多 小文件的危害: 从HIVE角度来看 ...

  6. 解决HDFS小文件带来的计算问题

    hive优化 一.小文件简述 1.1. HDFS上什么是小文件? HDFS存储文件时的最小单元叫做Block,Hadoop1.x时期Block大小为64MB,Hadoop2.x时期Block大小为12 ...

  7. Spark使用CombineTextInputFormat缓解小文件过多导致Task数目过多的问题

    目前平台使用Kafka + Flume的方式进行实时数据接入,Kafka中的数据由业务方负责写入,这些数据一部分由Spark Streaming进行流式计算:另一部分数据则经由Flume存储至HDFS ...

  8. HTML&CSS面试高频考点(一)

    1. 行内元素/块级元素 非替换元素/替换元素 行内元素(内联元素):a, abbr(缩写), acronym(只取首字母缩写), b, bdo(文本方向), big, br, cite(引用), c ...

  9. HTML&CSS面试高频考点(三)

    11. CSS隐藏元素的方式 /*占据空间,无法点击*/ visibility: hidden; position: relative; top: -999em; /* 不占据空间,无法点击 */ p ...

随机推荐

  1. [MRCTF2020]Ezpop

    题目: Welcome to index.php <?php //flag is in flag.php //WTF IS THIS? //Learn From https://ctf.ieki ...

  2. Scrum冲刺_Day07

    一.团队展示: 1.项目:light_note备忘录 2.队名:删库跑路队 3.团队成员 队员(不分先后) 项目角色 黄敦鸿 后端工程师.测试 黄华 后端工程师.测试 黄骏鹏 后端工程师.测试 黄源钦 ...

  3. WordCounter项目(基于javase)

    1.  Github项目地址: https://github.com/Flyingwater101/WordCount 1.  PSP表格 PSP2.1 Personal Software Proce ...

  4. CentOS 用户请关注,你期待的 CentOS Linux 9 再也不会来了

    2020年12月晚上红帽官网发布了一条公告,宣布了几件事情: 将不会发行 CentOS Linux 9 CentOS Linux 8 的更新支持持续到2021年12月31日 CentOS Linux ...

  5. Algorithm homework 1

    一.已知下列递推式: \[C(n)= \begin{cases} 1 & , & n = 1 \\ 2C(n/2) + n - 1& , & n \geq 2 \end ...

  6. STL——容器(Set & multiset)的概念和特点

    1. Set 和 multiset 的概念 set 和 multiset 是一个集合容器,其中 set 所包含的元素是唯一的,集合中的元素按一定的顺序排列.set 采用红黑树变体的数据结构实现,红黑树 ...

  7. Docker的容器使用与连接-Window

    启动容器 启动容器之前需要先拉取镜像,然后通过 run 命令启动容器,同一个镜像可以启动多个容器,只要执行多次 run 命令就行了.我们这边启动 centos 的镜像. PS D:\> dock ...

  8. 基数排序(Radix Sort)

    基数排序(Radix Sort) 第一趟:个位 收集: 第二趟:十位 第三趟:百位 3元组 基数排序--不是基于"比较"的排序算法 递增就是把收集的过程返过来 算法效率分析 需要r ...

  9. 恕我直言,你可能连 GitHub 搜索都不会用 - 如何精准搜索的神仙技巧

    大家好,我是你们的 前端章鱼猫,一个不喜欢喵.又不喜欢吃鱼的超级猫 ~ 今天给大家带来的是 在 GitHub 上如何精准搜索的神仙技巧. [前端GitHub:https://github.com/bi ...

  10. js下 Day13、面向对象

    一.对象 什么是对象: 一组无序的属性集合 创建对象两种方式: 对象字面量: var obj = {} 实例化: var obj = new Object() 对象取值: **[] ( ** 中括号) ...