文章目录
- 小文件产生的原因
- 1.查询建表或者插入
- 2.装载数据
- 3.动态分区
- 小文件影响
- 解决方法
- 针对已经存在的小文件进行优化
- 1.小文件归档
- 2.getmerge
- 3.concatenate
- 4.重写
- 针对写入数据时的优化
- 1.调参优化
- 2.动态分区优化
- 3.使用 Spark 算子控制小文件数量
查看 HDFS 上的文件时,无意间点进了 Hive 表的存储目录下,打开发现其中有许多的小文件,如下所示:
每个文件都是几个 KB,都占用了一个块,这种就是典型的小文件。那么通过这篇博客,一起来学习如何解决 Hive 中出现的小文件问题。
注意,博主使用的 Hive 版本为 3.1.3
,不同版本之间可能存在微差,但整体影响不大。
小文件产生的原因
产生小文件绝大多数都是和 Reduce 相关的,因为它决定了我们最终的输出文件数量,主要有以下几个场景:
1.查询建表或者插入
当我们通过查询建表或者通过查询的方式将数据插入的时候,就有可能会产生小文件,如下所示:
create table test_a select * from tmp;insert into test_a select * from tmp;
2.装载数据
使用 load
语句装载或者 insert
语句直接将数据装载到表中,也可能会产生小文件。
当使用 load
时,导入多少个文件,在 Hive 表中就会生成多少个文件:
load data local inpath 'xxx' overwrite into table test_a;
当使用 insert
直接插入数据时,它会启动 MR 任务,有多少个 Reduce,就会输出多少个文件:
insert into test_a values (1,'a'),(2,'b'),(3,'c');
3.动态分区
在 Hive 中使用动态分区时,容易产生大量的小文件。
这主要是由于动态分区插入数据的方式导致的,在每次插入数据时,Hive 可能会为每个分区创建一个新的文件。如果插入的数据量较小或者插入操作频繁,就会导致产生大量的小文件。
小文件过多会对Hive和底层存储HDFS产生负面影响。此外,小文件过多也会使得NameNode的元数据变得庞大,占用过多内存,1。
小文件影响
我们都知道在 HDFS 中,所有文件的元数据信息都存储在 NameNode,也就是命名空间中,它运行在有限的内存里。
HDFS 上每个文件的元数据信息占用 150B
左右的空间,一旦小文件过多,就会影响 HDFS 的性能,还可能撑爆 NameNode 的内存,造成集群宕机,无法提供服务,这就是为什么要处理小文件的根本原因。
同时,对于 Hive 来说,每个小文件在查询时都会被当作一个块,并启动一个 Map 任务来完成,但这种情况下 Map 任务的启动和初始化时间通常远大于逻辑处理时间,这样就会导致大量的资源浪费,降低程序性能。
解决方法
针对已经存在的小文件进行优化
1.小文件归档
在 Hadoop 中,提供了一种小文件归档技术,它可以将一个目录下的所有小文件都打包成一个 HAR
文件,也就是说,它只对分区表有效。
-- 是否开启归档操作,默认 false
set hive.archive.enabled=true;
-- 是否允许Hive在创建归档时可以设置父目录(该参数有些Hive版本中已经弃用,无需设置)
set hive.archive.har.parentdir.settable=true;
-- 控制需要归档文件的大小
set har.partfile.size=1099511627776;-- 使用语法
ALTER TABLE table_name ARCHIVE PARTITION (partition