利用开窗函数+spark.sql.shuffle.partitions避免小文件合并

遇到一个常见sql使用场景

insert overwrite table xxx(date='${hiveconf:date}')

select 

    *

from table1

union all 

select

     *

from table2

 观察发现任务耗时慢,大概30多分钟,其中主要耗时花在合并小文件——每次执行完spark etl任务还会执行hive合并小文件合并,解决小文件过多的问题。

ALTER TABLE xxx PARTITION (date='${date}')  concatenate

合并小文件前查看分区下的小文件数量,大概有4000-5000多个,看来是小文件太多,执行hive合并小文件命令的时候耗时了;合并完成后小文件数量40-50个。

解决方案:开窗函数+设置spark.sql.shuffle.partitions参数

1. 优化后的sql

insert overwrite table xxx(date='${hiveconf:date}')

select 

……

,max(id) over(partition by id) as id

from

(

select 

    *

from table1

union all 

select

     *

from table2

)

2. 启动时设置参数

--conf spark.sql.shuffle.partitions,其默认大小为200。

--conf spark.sql.shuffle.partitions=50

3. 外层对表的主键进行分组开窗,其实就是最后一步进行shuffle。由于是主键,所以不存在数据倾斜问题,性能影响不大,数据重新均匀打散,再spark.sql.shuffle.partitions参数生成指定分区数量。

优化后,开窗会带来一定的性能消耗,但避免了再直一个任务做小文件合并,耗时从30多分钟缩小到五六分钟,实际中遇到类似问题,可以尝试此方法。

你可能感兴趣的:(spark)