整体上的优化点目录如下:
0. Overview
1. 开发调优
- 避免创建重复的RDD
- 尽可能复用同一个RDD
- 对多次使用的RDD进行持久化
- 尽量避免使用shuffle类算子
- 使用map-side预聚合的shuffle操作
- 使用高性能的算子
- 广播大变量
- 使用Kryo优化序列化性能
- 优化数据结构
2. 资源参数调优
- 运行时架构
- 运行流程
- 调优
- executor配置
- driver配置
- 并行度
- 网络超时
- 数据本地化
- JVM/gc配置
3. 数据倾斜调优
- 使用Hive ETL预处理数据
- 过滤少数导致倾斜的key
- 提高shuffle操作的并行度
- 两阶段聚合
- 将reduce join转为map join
- 使用随机前缀和扩容RDD进行join
4. Shuffle调优
- shuffle原理
- shuffle演进
- 调优
- join类型
5. 其他优化项
- 使用DataFrame/DataSet
Spark的瓶颈一般来自于集群(standalone, yarn, mesos, k8s)的资源紧张,CPU,网络带宽,内存。通过都会将数据序列化,降低其内存memory和网络带宽shuffle的消耗。
Spark的性能,想要它快,就得充分利用好系统资源,尤其是内存和CPU:核心思想就是能用内存cache就别spill落磁盘,CPU 能并行就别串行,数据能local就别shuffle。
字符串
替代对象
,使用原始类型
(比如Int、Long)替代字符串
,使用数组
替代集合类型
,这样尽可能地减少内存占用,从而降低GC频率,提升性能spark runtime architecture From Spark in Action
数据倾斜,key=hello过多
单个task分到的key少了
两阶段聚合
shuffle From iteblog_hadoop
M*R
E*R
M
shuffle是一个涉及到CPU(序列化反序列化)、网络IO(跨节点数据传输)以及磁盘IO(shuffle中间结果落盘)的操作。所以用户在编写Spark应用程序的过程中应当尽可能避免shuffle算子和考虑shuffle相关的优化,提升spark应用程序的性能。
要减少shuffle的开销,主要有两个思路,
A.union(B).distinct()
vs. A.distinct().union(B.distinct()).distinct()
Shuffled Hash Join Sort Merge Join Broadcast Join
sql joins From JAMES CONNER
spark api演进
Type | RDD | DataFrame | DataSet |
---|---|---|---|
definition | RDD是分布式的Java对象的集合 | DataFrame是分布式的Row对象的集合 | DataSet是分布式的Java对象的集合ds = df.as[ElementType]df = Dataset[Row] |
pros | * 编译时类型安全* 面向对象的编程风格 | * 引入schema结构信息* 减少数据读取,优化执行计划,如filter下推,剪裁* off-heap堆外存储 | * Encoder序列化* 支持结构与非结构化数据* 和rdd一样,支持自定义对象存储* 和dataframe一样,支持结构化数据的sql查询* 采用堆外内存存储,gc友好* 类型转化安全,代码有好 |
cons | * 对于结构化数据不友好* 默认采用的是java序列化方式,序列化结果比较大,而且数据存储在java堆内存中,导致gc比较频繁 | * rdd内部数据直接以java对象存储,dataframe内存存储的是Row对象而不能是自定义对象* 编译时不能类型转化安全检查,运行时才能确定是否有问题 | * 可能需要额外定义Encoder |