接了一个业务方面的Spark Sql需求,2个大表join.
20e 和90e数据join,无其他复杂逻辑,按固定字段join。
由于发生了叉乘。中间结果达到上万亿,12T数据量。
Task很容易失败,查看具体LOG,报一些经典shuffle异常,比如timeout, shuffle lost location。
调优思路:让每个task处理更少的数据量(提高并发),减少GC时间,提高程序稳定性(retry和timeout参数配置),shuffle系列参数
1.先查看Spark Web Ui ,看内存使用是否频繁GC,若频繁提高Executor内存
2.调整shuffle系列参数
--conf spark.shuffle.spill.numElementsForceSpillThreshold=5000000 \ --conf spark.shuffle.file.buffer=1024k \ --conf spark.reducer.maxSizeInFlight=100m \ --conf spark.shuffle.io.maxRetries=20 \ --conf spark.shuffle.io.retryWait=60s \
3.GC情况良好,可提高core数,我从1提高到了4,内存可不变或适当提高,我从8G提高到了14G,结合num-executors的个数,调整spark.sql.shuffle.partitions = num-executors * executor-cores * 3。
--conf spark.sql.shuffle.partitions=3600 --conf spark.network.timeout=300 \ --executor-memory 14G \ --driver-memory 1G \ --num-executors 300 \ --executor-cores 4 \
4.增加整体稳定性
--conf spark.network.timeout=300 \
5.调整内存模型参数
我没使用到缓存rdd一类的,所以
--conf spark.memory.storageFraction=0.1 \
6.其他
若为了提高程序稳定性,针对这种单次二次开发需求,可以将sql拆分成N个子sql,每个sql都落盘保存为parquet文件,方便重启,减少试错成本。
经测试:在晚上10点左右,集群不忙的时候,效果最好,此时集群整体IO和网络通信压力较小,很少会出现executor lost以及timeout。
最终程序在2个小时跑完了。 业务方面的hive on mr 那边已经跑了24个小时。