PySpark非分区Hive表到分区Hive表数据加载的性能调优
PySpark分区导入作业调优方案
核心问题根因
- 当前作业总数据规模仅15GB,远未达到计算瓶颈,3小时的超长耗时来自两个可明确定位的问题:
- 动态分区写入逻辑失当导致小文件爆炸:默认配置下Spark写入分区表时,每个执行task会扫到所有load_date分区值,为每个命中的分区单独创建文件,最终单分区平均生成217个小文件,全表累计60万+个过小文件,90%以上的耗时花在HDFS文件创建、RPC调用、句柄维护的IO开销上,而非实际数据计算。
- 集群资源闲置严重:当前仅占用YARN队列10%的可用算力,处理15GB数据的并行度严重不足。
一、 写入层参数调优(优先落地,见效最快)
- 开启Spark自适应执行(AQE),自动处理shuffle倾斜、小文件合并问题,核心配置项:
spark.sql.adaptive.enabled=truespark.sql.adaptive.coalescePartitions.enabled=truespark.sql.adaptive.skewJoin.enabled=true
- 调整shuffle并行度:将默认的
spark.sql.shuffle.partitions=200调整为120180,匹配15GB源数据的规模,保证每个shuffle分区的处理数据量在128256MB的最优区间,避免并行度过高带来的小文件问题。 - 从根源控制写入文件大小:配置
spark.sql.sources.writeMaxPartitionBytes=134217728(即单个写入文件最大128MB):- 对于仅4MB的小load_date分区,直接生成1个不超过128MB的文件即可,避免单分区生成上百个小文件
- 对于4GB的大分区,自动切分为30个左右的128MB标准文件,全表总文件数可从60万+降到3000个左右
- 开启Parquet向量化写入:配置
spark.sql.parquet.enableVectorizedWriter=true,Snappy压缩Parquet的写入速度可提升2~3倍。
二、 资源配置优化(把闲置集群算力用满)
- 当前队列总资源为5120GB内存、1000核,现有配置(单executor5核10GB)是Spark写入任务的最优配比(每核对应2GB内存,预留2GB给HDFS客户端和PySpark进程),可直接将executor数量从50提升到180~200:
- 调整后总占用资源为9001000核、18002000GB内存,仅占队列总容量的35%~40%,不会触发可抢占调度的资源回收
- 无需调整executor-cores和executor-memory参数,现有配比无内存溢出风险。
三、 源表读取优化
- 针对源表对应的15GB单dat格式文件,配置
spark.sql.files.maxPartitionBytes=134217728(128MB),将单文件切分为120个左右的输入分片并行读取,避免单task串行处理整个15GB文件的性能瓶颈,让输入层并行度和shuffle层并行度匹配。
效果预期
- 调整后,整体作业运行时长可压缩到1015分钟,远低于Beeline执行的2530分钟水平;同时目标表的小文件问题会被彻底解决,后续对目标表的查询性能也会同步提升。
内容的提问来源于stack exchange,提问作者Ajay
相关产品推荐
相关产品推荐

