spark sql合并小文件_sparksql合并小文件

本文探讨了Spark SQL在2.4.x及以上版本中合并小文件的方法,包括INSERT...SELECT语句配合COALESCE或REPARTITION操作。在Spark 3.0中,启用自适应执行(spark.sql.adaptive.enabled=true)可以自动合并小文件,但还需要考虑其他相关参数如spark.sql.adaptive.coalescePartitions.enabled。文章指出,合理设置这些参数,特别是初始化分区数和阈值,能避免过多小文件并提高作业效率。作者提出了一种新的策略,以找到最佳的task启动数量平衡点。

查看sparksql支持的参数:spark-sql set -v

需要注意这种方式对Spark的版本有要求,建议在Spark2.4.X及以上版本使用,示例: INSERT ... SELECT /*+ COALESCE(numPartitions) */ ... INSERT ... SELECT /*+ REPARTITION(numPartitions) */

spark3.0支持自适应合并小文件,通过把参数spark.sql.adptive.enabled设置为true打开自适应。但是仅仅设置这个参数是不够,合并小文件还受其他参数影响。下面是我们生产的一个作业SQL,这个SQL执行完后这个表的每个分区都有800个文件,每个文件都是几M。当时就挺纳闷的,为什么都是800。于是去看生产spark的配置文件,发现如下关键参数

3de76de742da58fc51dab325777c5556.png

我们看看这个参数的描述:它和三个参数有关,这三个参数分别sparksql的默认分区数(spark.sql.shuffle.partitions,该值默认是200)、打开sparksql自适应参数spark.sql.adptive.enabled和分区合并小文件参数spark.sql.adptive.coalescePatitions.enabled有关。需要自适应和分区合并小文件都打开才生效。如果没有设置这个合并分区初始化分区数,那么合并小文件就按照sparksql的shuffle默认分区数启动。

0ef45bffcfc077ce750402ccdc41cc11.png

测试SQL如下:

insert overwrite table dws_m.dws_dtfs_mbl_dpi_tag_hour_msk_d_test_20201022 partition  (prov_id, day_id, biz_day_id, tag_flag)  select a.mdn,         a.meid,         a.imsi,         a.tag_id,         substr(a.start_time, 9, 2) hour_range,         count(*) all_cnt,         sum(a.link_dur) link_dur,         count(distinct a.start_time) m_cnt,         sum(a.up_flow) up_flow,         sum(a.down_flow) down_flow,         a.type_id,         b.is_holiday,         a.refer,         a.prov_id,         a.day_id,         a.biz_day_id,         a.tag_flag    from (select *            from dwi_m.dwi_evt_blog_mbl_dpi_tag_msk_d           where day_id = '20201020'             and prov_id = '853'             and tag_flag in ('url', 'app', 'site')) a    left join dim.dim_date b      on a.biz_day_id = b.day_id   group by a.mdn,            a.meid,            a.imsi,            a.tag_id,            substr(a.start_time, 9, 2),            a.type_id,            a.prov_id,            a.day_id,            a.biz_day_id,            a.tag_flag,            b.is_holiday,            a.refer;

测试结果如下:

d7ded9b29984e0cd86da54ed4205b507.png

有shuffle时虽然合并达到了合并小文件的目的,但是个人认为这个还有待改进。我们看到合并小文件的阈值参数spark.sql.adaptive.advisoryPartitionSizeInBytes设置为200M了(和参数spark.sql.adaptive.shuffle.targetPostShuffleInputSize一样,这个默认值64M)。有合并小文件的最小分区数spark.sql.adptive.coalescePatitions.minPartitionNum。那么我们是否把spark.sql.adptive.coalescePatitions.initialPartitionNum改成spark.sql.adptive.coalescePatitions.maxPartitionNum参数,然后根据合并小文件的阈值spark.sql.adaptive.advisoryPartitionSizeInBytes和最大合并小文件分区数spark.sql.adptive.coalescePatitions.maxPartitionNum两者的最小值确定启动task数更合理呢?这样即不会导致初始化合并分区数太多导致小文件,又不会设置初始化分区数太少(会生成很大的文件数)而导致spark作业太慢

下面就是测试的一个极端情况

17ecf4e26dc738bd04f4239f01cbc26c.png
在处理Spark SQL中的小文件问题时,可以通过配置特定的参数来优化文件的合并过程。这些参数不仅有助于减少HDFS上的元数据负载,还能提升计算性能。以下是几个关键参数及其作用[^1]: ### Spark SQL小文件合并参数 #### `spark.compact.smallfile.size` 此参数定义了被认为是小文件的最大大小。在commit阶段,系统会查找所有小于这个值的文件,并将其标记为需要合并的对象。 #### `spark.compact.size` 此参数指定了合并后的目标文件大小。系统会尝试将多个小文件组合成接近这个大小的新文件,以减少文件数量并优化存储效率。 ### Hive小文件合并参数(适用于Hive与Spark集成场景) #### `hive.merge.mapfiles` 控制在map阶段结束后是否合并输出的小文件,默认值为`true`。启用此选项可以在早期阶段就减少小文件的数量。 #### `hive.merge.mapredfiles` 控制在reduce阶段结束后是否合并输出小文件,默认值为`false`。开启此选项可以进一步减少最终写入存储系统的文件数量。 #### `hive.merge.size.per.task` 设定每个任务的目标文件大小,默认为256MB。这个值是硬性设置,确保合并后的每个文件大小不会超过它。 #### `hive.merge.smallfiles.avgsize` 只有当输入文件的平均大小小于该值时,才会触发合并操作,默认为1GB。这个参数用于判断是否需要启动合并流程。 ### 示例配置 以下是一个典型的配置示例,展示如何在Spark SQL中设置这些参数: ```sql SET spark.compact.smallfile.size=134217728; -- 128MB SET spark.compact.size=268435456; -- 256MB SET hive.merge.mapfiles=true; SET hive.merge.mapredfiles=true; SET hive.merge.size.per.task=268435456; -- 256MB SET hive.merge.smallfiles.avgsize=1073741824; -- 1GB ``` 通过上述配置,可以在Spark SQL作业执行过程中有效地管理和合并小文件,从而优化整体性能和资源利用率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值