概述:
Spark的调优有很多方面。要想Spark的性能提高,就得充分利用好系统资源,尤其是内存和CPU。核心思想就是减少数据落盘、提高并行度、减少shuffle、减少网络传输。
1. 开发调优
- 避免创建重复的RDD
- 尽可能复用同一个RDD
- 对多次使用的RDD进行持久化
- 尽量避免使用shuffle类算子。
shuffle算子如distinct(实际调用reduceByKey)、reduceByKey、aggregateByKey、sortByKey、groupByKey、join、cogroup、repartition等,入参中会有一个并行度参数numPartitions
- 使用map-side预聚合的shuffle操作
- 使用高性能的算子
使用reduceByKey/aggregateByKey替代groupByKey
使用mapPartitions替代普通map:特别是在写DB的时候,避免每条写记录都new一个connection;推荐是每个partition new一个connection;更好的是new connection池,每个partition从中取即可,减少partitionNum个new的消耗
使用foreachPartitions替代foreach
使用filter之后进行coalesce操作减少小文件数量
使用repartitionAndSortWithinPartitions替代repartition与sort类操作
- 广播大变量
- 使用Kryo优化序列化性能
- 优化数据结构
2. 资源参数调优
- executor配置
spark.executor.memory
spark.executor.instances
spark.executor.cores
- driver配置
spark.driver.memory(如果没有collect操作,一般不需要很大,1~4g即可)
spark.driver.cores
- 并行度
spark.default.parallelism (used for RDD API)
spark.sql.shuffle.partitions (usef for DataFrame/DataSet API)
- 网络超时
spark.network.timeout (所有网络交互的默认超时)
- 数据本地化
spark.locality.wait
- JVM/gc配置
spark.executor.extraJavaOptions
spark.driver.extraJavaOptions
3. 数据倾斜调优
- 使用Hive ETL预处理数据
- 过滤少数导致倾斜的key
- 提高shuffle操作的并行度
- 两阶段聚合
- 将reduce join转为map join
- 使用随机前缀和扩容RDD进行join
4. Shuffle调优
要减少shuffle的开销,主要有两个思路
1、减少shuffle次数,尽量不改变key,把数据处理在local完成
2、减少shuffle的数据规模
1、先去重,再合并:A.union(B).distinct() vs. A.distinct().union(B.distinct()).distinct()
2、用broadcast + filter来代替join
3、spark.shuffle.file.buffer设置shuffle write task的buffer大小
4、spark.reducer.maxSizeInFlight设置shuffle read task的buffer大小,决定了每次能够拉取pull多少数据。
5、spark.shuffle.sort.bypassMergeThreshol: SortShuffleManager 中,shuffle read task的数量小于这个阈值(默认是200),则map-side/shuffle write过程中不会进行排序操作