HIVE 生成过多小文件的问题

今天运维人员突然发来了告警,有一张表生成的小文件太多,很疑惑,然后排查记录了下

HIVE的版本 2.x,使用的引擎是 MR

注意:HIVE ON SPARK 或 SPARK-SQL 生成的小文件的方式不同,该篇文章针对 MR 引擎的 HIVE

小文件的危害

① 增加 TASK 的数量

当我们执行表查询时,每个文件都会生成一个 MapTask,在文件内容比较小的时候,过多的 Task 数量反而会降低查询的性能(因为 MapTask 的启动时间可能大于逻辑执行时间);同时每个JOB 生成的 MAP TASK 的数量是有限制的,可能会影响到其他JOB

② 增加 NameNode 的负担

我们知道,在 HADOOP 启动的时候,会通过 fsImage文件和edits文件 加载出所有文件的元数据信息,然后保存在 NameNode 节点的内存中,每个HDFS文件元信息(位置,大小,分块等)对象约占150字节,如果小文件过多,会占用大量内存,直接影响NameNode的性能。因此大量的小文件会严重占用 NameNode 的内存,有可能影响整个 Hadoop 集群的性能,因此,减少小文件的数量很有必要

为什么会生成多个小文件

HIVE 生成的小文件过多,指的是该表在 HDFS 目录下,有多个文件,且文件的磁盘占用比较小;

表的文件一般是向表插入数据的时候生成的,所以我们应该分析下插入数据的方式

不同的数据加载方式生成文件的区别

① 通过文件向表中加载数据

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

-- 导入文件
load data local inpath '/opt/data/cust_info.txt' overwrite into table cust_info
-- 导入文件夹
load data local inpath '/opt/data/cust_info' overwrite into table cust_ifno

在这里插入图片描述
在这里插入图片描述

② 直接向表中插入数据

每次插入时都会产生一个文件,多次插入少量数据就会出现多个小文件

-- 执行两次看下结果
insert into table stu_info partition(ds = '20220405') values ('001','kyle', '22', 'beijing'),('002', 'lisa', '23', 'shanghai');

<think>好的,我现在需要回答用户关于如何在使用SparkSQL时避免生成过多小文件问题,特别是关于调整参数配置和shuffle partition的最佳实践。首先,我需要回忆一下SparkSQL处理小文件问题的常见方法,并结合用户提供的引用内容来组织回答。 用户提到了三个引用,分别涉及小文件问题的影响、通过repartition解决的方法,以及shuffle分区数的默认设置。我需要将这些内容整合到回答中,确保符合系统级指令的要求,比如正确使用LaTeX格式,生成相关问题,并添加引用标识。 首先,调整shuffle partition的参数spark.sql.shuffle.partitions,默认是200,这可能导致很多小文件。需要说明如何根据数据量调整这个值,比如减少到合理范围。然后,用户可能使用动态分区插入数据,这时候需要设置spark.sql.files.maxRecordsPerFile来控制每个文件的最大记录数,或者调整spark.sql.adaptive.enabled来启用自适应优化。 另外,用户提供的引用2提到通过repartition的hint来合并小文件,这可以手动控制分区数,比如coalesce或repartition方法。需要解释这两种方法的区别,coalesce适合减少分区,而repartition可以增减,但会引入shuffle。 还要提到写入后的合并策略,比如使用Hive的合并工具,或者触发合并的机制,如OPTIMIZE命令。最后,总结参数调整、手动重分区和写入后合并的综合方法,并强调根据数据量和集群资源灵活调整。 接下来需要生成相关问题,这些问题应该覆盖参数优化、手动重分区、自适应执行引擎、动态分区影响以及合并工具等方面,确保问题与主题相关且具有延伸性。 在回答过程中,确保所有数学表达式用$...$,如$N$,独立公式用$$...$$,但可能在这个问题中用到的数学内容不多,但如果有的话要注意格式。同时检查LaTeX语法是否正确,使用中文回答,结构清晰,分步骤说明。引用标识要自然地添加到引用内容的末尾,如[^1]、[^2]、[^3]。 现在需要将上述思路整理成一个结构化的回答,分步骤说明最佳实践,每个步骤结合引用内容,并在末尾添加相关问题。</think>在使用SparkSQL时,避免生成过多小文件的核心在于**控制分区数量**和**优化写入策略**。以下是具体的最佳实践: --- ### 1. 调整Shuffle分区数 SparkSQL的Shuffle操作默认分区数为$N=200$(由参数`spark.sql.shuffle.partitions`控制)。若数据量较小,此值过大会直接导致小文件问题。 **优化方法**: - 根据数据规模动态调整分区数: ```sql SET spark.sql.shuffle.partitions=64; -- 根据数据量减少到合理值(如集群核心数的2-3倍) ``` - 结合`spark.sql.adaptive.enabled=true`(自适应执行引擎),Spark会自动合并小分区。 --- ### 2. 控制写入文件大小 通过参数限制单个文件大小或记录数: - **静态控制**: ```sql SET spark.sql.files.maxRecordsPerFile=1000000; -- 每个文件最多100万条记录 ``` - **动态分区优化**: 对动态分区插入场景,设置`spark.sql.hive.convertMetastoreParquet.mergeSchema=false`以避免元数据合并开销。 --- ### 3. 手动重分区写入 在最终写入数据前,显式指定分区数: - **使用`COALESCE`**(适合减少分区,无Shuffle): ```sql INSERT INTO table SELECT /*+ COALESCE(10) */ * FROM src; ``` - **使用`REPARTITION`**(可增减分区,触发Shuffle但分布均匀): ```sql INSERT INTO table SELECT /*+ REPARTITION(20) */ * FROM src; -- 强制调整为20个分区 ``` --- ### 4. 写入后合并小文件 对已存在的小文件,可通过以下方式合并: - **Hive合并工具**: ```sql ALTER TABLE table CONCATENATE; -- 仅适用于Hive表 ``` - **触发合并机制**: 写入后执行`OPTIMIZE table`(需Delta Lake等支持事务的格式)。 --- ### 总结配置参数 | 参数 | 作用 | 示例值 | |------|------|--------| | `spark.sql.shuffle.partitions` | 控制Shuffle后分区数 | 64 | | `spark.sql.files.maxRecordsPerFile` | 限制单个文件记录数 | 1,000,000 | | `spark.sql.adaptive.enabled` | 启用自适应优化 | true | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值