Spark作为批处理事实上的标准,框架本身在不断演进过程中内置了好多调优能力,但是除了通用的调优之外,一些性能优化和业务本身的数据特征有关,因此要深入了解常用的调优原理,才能结合实际项目选择合适的调优策略。以下策略强调实用,简单、直接,不会深入太多细节。
调优策略
1. 内存/CPU设置
内存:
避免 OOM;合理分配计算、存储所使用的内存
Spark Application是由Driver端和Executor组成,Executor是计算节点,这里只介绍Executor端(Driver端功能简单暂不涉及)
该图来源网络
重点关注以下两部分:
Storage :广播变量 + (cache缓存数据【使用序列化存储数据可减少内存】 / executor数量)
Excetion: shuffle、join等算子使用该内存,一般计算规则:executor核数(task任务数) * (数据集大小/并行度)
主要涉及的参数有两个:
spark.memory.fraction:(storage内存+execution内存) / executor总内存。 容易发生OOM的地方
spark.memory.storageFraction: storage内存 / (storage内存+execution内存),用来缓存数据的内测
官方参考文档:https://spark.apache.org/docs/3.5.1/tuning.html#memory-management-overview
CPU/并行度:
低效的原因是:任务太少未充分使用【cpu挂起】 + 任务太多竞争充分【cpu来回切换开销大】
CPU调优 实际上是调整并行度以此来合理使用CPU
CPU浪费的识别:
查看Spark Web UI界面上同一时期CPU的占用情况,以下视图就是代表CPU重复使用
设置策略:(executor内存数/core核数) / 2 ~ (executor内存数/core核数)。 实际过程中使用 core数的2~3倍。
特别注意是注意按照设置后的并行度对应的数据分片大小,如果并行度调少导致数据分片太大,此时需要相应调整内存大小。
2. 语法优化
Spark SQL 使用Catalyst框架做了RBO,CBO的优化,如下图所示:RBO发生在Logical Plan 和 Optimized Logical Plan之间,CBO等同于图中的 Cost Model
图片来源网络
RBO
基于规则的优化Catalyst已经自动做好了,这个是按照经验提前配置好的规则,总结下来就是2点:1.提前过滤-减少数据量(常见的过滤逻辑下推-谓词下推) 2. 提前计算-减少计算量(常量替换)
CBO
CBO的核心是一个代价模型,它基于统计信息用于估计不同查询计划的执行成本,该过程是框架实现的,但是需要手动开启。
3. Spark SQL 常见的JOIN
广播Join:适合较小表【可以同步广播到内存,减少IO读写】和大表JOIN的场景
Shuffle Hash Join:适合小表和大表JOIN的场景
Sort Merge Join:适合两张大表JOIN,例如 TB级别的两张表JOIN
广播Join和shuffle hash join 都是基于 hash key进行join,区别在于小表是否需要放到广播到内存中。
所以根据数据特征不同选择对应合适的JOIN策略
三者的详细原理和区别参考网络文章:https://developer.jdcloud.com/article/3580
4. 数据倾斜
数据倾斜的识别:在Spark-Web-UI查看 某个task运行时间很长;task出现OOM
适用情况&解决方案:
情况:单表聚合倾斜
解决方法:key加盐局部聚合 -> 减小数据量 --> 去盐全局聚合
情况:大表join,大表的key有热点
解决方法:大表的key加随机数打散 --> 小表扩容 ---> 两表按照新key join
5. Map端优化
map提前做聚合;读取小文件优化成大文件读取
6. Reduce优化
设置合理的任务数;输出时尽量减少生成小文件;减少分区数