在生产中,无论是通过SQL语句或者Scala/Java等代码的方式使用Spark SQL处理数据,在Spark SQL写数据时,往往会遇到生成的小文件过多的问题,而管理这些大量的小文件,是一件非常头疼的事情。

大量的小文件会影响Hadoop集群管理或者Spark在处理数据时的稳定性:

1. Spark SQL写Hive或者直接写入HDFS,过多的小文件会对NameNode内存管理等产生巨大的压力,会影响整个集群的稳定运行

2. 容易导致task数过多,如果超过参数spark.driver.maxResultSize的配置(默认1g),会抛出类似如下的异常,影响任务的处理

Caused by: org.apache.spark.SparkException: Job aborted due to stage failure: Total size of serialized results of 478 tasks (2026.0 MB) is bigger than spark.driver.maxResultSize (1024.0 MB)

当然可以通过调大spark.driver.maxResultSize的默认配置来解决问题,但如果不能从源头上解决小文件问题,以后还可能遇到类似的问题。

此外,Spark在处理任务时,一个分区分配一个task进行处理,多个分区并行处理,虽然并行处理能够提高处理效率,但不是意味着task数越多越好。如果数据量不大,过多的task运行反而会影响效率。

下面通过一个例子,Spark SQL写数据时,导致产生分区数"剧增"的典型场景,通过分区数"剧增",以及Spark中task数和分区数的关系等,来倒推小文件过多的可能原因(这里的分区数是指生成的DataSet/RDD的分区数,不是Hive分区表的分区概念):

1. 现象

1) 对表test_tab进行写入操作
2) t1的分区数是100,t2的分区数是200,union all后生成的tmp分区数是300
3) test_tab产生的小文件数基本也在300左右
select * from t1 union all select * from t2 as tmp;insert overwrite table test_tab select * from tmp;

2. 分析

1)执行上述insert操作时的分区并行度,主要受tmp的分区数(对应一个DataSet)影响,

2)tmp的分区数主要受t1、t2以及union all的影响

3)暂且不考虑t1或t2是物理表还是经过其他处理生成的临时表,它们的分区数是确定的,这里主要看经过union all处理后,生成的tmp的分区数和t1、t2的分区数有何关系?

4)Spark SQL语句中的union all对应到DataSet中即为unionAll算子,底层调用union算子

在之前的文章《重要|Spark分区并行度决定机制》中已经对Spark RDD中的union算子对union产生的新的RDD的分区数是如何受被union的多个RDD的影响的,做过详细介绍,这里直接给出结论:

同样的这种机制也可以套用到Spark SQL中的DataSet上,那么就很好解释了tmp的分区数为什么等于t1和t2的分区数的和。

最后,Spark中一个task处理一个分区从而也会影响最终生成的文件数。

当然上述只是以Spark SQL中的一个场景阐述了小文件产生过多的原因之一(分区数过多)。在数仓建设中,产生小文件过多的原因有很多种,比如:

1. 流式处理中,每个批次的处理执行保存操作也会产生很多小文件

2. 为了解决数据更新问题,同一份数据保存了不同的几个状态,也容易导致文件数过多

那么如何解决这种小文件的问题呢?

1. 通过repartition或coalesce算子控制最后的DataSet的分区数

注意repartition和coalesce的区别,具体可以参考文章《重要|Spark分区并行度决定机制》

2. 将Hive风格的Coalesce and Repartition Hint 应用到Spark SQL需要注意这种方式对Spark的版本有要求,建议在Spark2.4.X及以上版本使用,示例:

INSERT ... SELECT /*+ COALESCE(numPartitions) */ ...
INSERT ... SELECT /*+ REPARTITION(numPartitions) */ ...

3. 小文件定期合并

可以定时通过异步的方式针对Hive分区表的每一个分区中的小文件进行合并操作

上述只是给出3种常见的解决办法,并且要结合实际用到的技术和场景去具体处理,比如对于HDFS小文件过多,也可以通过生成HAR 文件或者Sequence File来解决。

推荐文章:

Spark SQL | 目前Spark社区最活跃的组件之一

Spark存储Parquet数据到Hive,对map、array、struct字段类型的处理Spark SQL解析查询parquet格式Hive表获取分区字段和查询条件

关于HDFS应知应会的几个问题Spark RDD详解

Spark和Spring整合处理离线数据Spark流式状态管理


关注微信公众号:大数据学习与分享,获取更对技术干货

Spark SQL 小文件问题处理的更多相关文章

  1. hadoop spark合并小文件

      一.输入文件类型设置为 CombineTextInputFormat hadoop job.setInputFormatClass(CombineTextInputFormat.class) sp ...

  2. Spark SQL如何选择join策略

    前言 众所周知,Catalyst Optimizer是Spark SQL的核心,它主要负责将SQL语句转换成最终的物理执行计划,在一定程度上决定了SQL执行的性能. Catalyst在由Optimiz ...

  3. spark SQL (四)数据源 Data Source----Parquet 文件的读取与加载

    spark SQL Parquet 文件的读取与加载 是由许多其他数据处理系统支持的柱状格式.Spark SQL支持阅读和编写自动保留原始数据模式的Parquet文件.在编写Parquet文件时,出于 ...

  4. Spark SQL之External DataSource外部数据源(二)源代码分析

    上周Spark1.2刚公布,周末在家没事,把这个特性给了解一下,顺便分析下源代码,看一看这个特性是怎样设计及实现的. /** Spark SQL源代码分析系列文章*/ (Ps: External Da ...

  5. spark sql/hive小文件问题

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

  6. Spark:spark df插入hive表后小文件数量多,如何合并?

    在做spark开发过程中,时不时的就有可能遇到租户的hive库目录下的文件个数超出了最大限制问题. 一般情况下通过hive的参数设置: val conf = new SparkConf().setAp ...

  7. 针对小文件的spark wholeTextFiles()

    场景:推送过来的数据文件数量很多,并且每个只有10-30M的大小 spark读取hdfs一般都是用textfile(),但是对于这种情况,如果使用textFile默认产生的分区数将与文件数目一致,产生 ...

  8. 通过Spark SQL关联查询两个HDFS上的文件操作

    order_created.txt   订单编号  订单创建时间 -- :: -- :: -- :: -- :: -- :: order_picked.txt   订单编号  订单提取时间 -- :: ...

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

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

随机推荐

  1. 使用Camtasia制作游戏直播高能短视频

    随着电竞行业的兴起,很多主播都开始做起游戏直播.对于喜欢打游戏的朋友来说,观看游戏直播既可以提高游戏的技术,也能作为下班后的休闲娱乐.对于喜欢钻研游戏技术的朋友,制作一个游戏高能合集能也是一件很燃的事 ...

  2. Boom 3D带你聆听《我们的乐队》音乐盛宴

    说到前段时间大热的音乐类综艺节目,<我们的乐队>肯定值得一提.<我们的乐队>是由谢霆锋.萧敬腾.王俊凯担任导师,以团队的形式组成各种风格的乐队,并通过同场比拼,最终选出获胜的乐 ...

  3. 安装Ubuntu时到底该如何分区

    安装系统:Ubuntu16.04(单系统) /(根分区),主分区,   Ext4文件系统,100G-200G /boot分区,   逻辑分区,Ext4文件系统,~200MB /home分区, 逻辑分区 ...

  4. Unity减少构建安装包的体积(210MB减小到7MB)

    概述 项目简介 由于是公司内做的项目,不方便开源,就只分享优化过程吧. 项目信息 逐日是一个移动端单机小游戏,使用Unity开发,目前已将项目使用的Unity升级到2019.4.14f1c1 (3e5 ...

  5. 【电子取证:抓包篇】Fiddler 抓包配置与数据分析(简)

    Fiddler 抓包配置与分析(简) 简单介绍了Fiddler抓包常用到的基础知识,看完可以大概明白怎么分析抓包数据 ---[suy999]   Fiddler 抓包工具,可以将网络传输发送与接受的数 ...

  6. Nginx添加fastdfs-nginx-module模块

    系统:Ubuntu 20.04 Nginx版本:1.18.0 要添加的模块:fastdfs-nginx-module 思路:configure参数下包括Nginx已安装的模块信息,通过编辑config ...

  7. 牛客练习赛66 C公因子 题解(区间gcd)

    题目链接 题目大意 给你一个长为n的数组,给所有数组元素加上一个非负整数x,使得这个数组的所有元素的gcd最大 题目思路 这主要是设计到一个多个数gcd的性质 gcd(a,b,c,d.....)=gc ...

  8. try...catch的前世今生

    1975年, John Goodenough发表论文,提出异常处理的建议: 一是明确声明命令可能抛出何种异常: 二是需要有将可能出错的操作括起来的语句结构. Communications of the ...

  9. Java基础教程——二维数组

    二维数组 Java里的二维数组其实是数组的数组,即每个数组元素都是一个数组. 每个数组的长度不要求一致,但最好一致. // 同样有两种风格的定义方法 int[][] _arr21_推荐 = { { 1 ...

  10. LeetCode 033 Search in Rotated Sorted Array

    题目要求:Search in Rotated Sorted Array Suppose a sorted array is rotated at some pivot unknown to you b ...