1.执行计划
2.资源规划
3.缓存调优
4.CPU调优
5.语法优化
6.数据倾斜
6.1 数据倾斜现象
1、现象
绝大多数task运行速度很快,但是就是有那么几个task任务运行极其缓慢,慢慢的可能就会报内存溢出异常。
2、原因
数据倾斜一般发生在shuffle类的算子,比如distinct、groupByKey、reduceByKey、aggregateByKey、join、cogroup等,涉及到数据重分区,如果其中某一个key 数量特别大,就发生了数据倾斜。
6.2 数据倾斜大Key定位
已经存在数据倾斜的现象,那么我们怎么定位是哪个Key导致了数据倾斜呢?
可以用scala写一个采样key的demo,统计出现次数最高的top10的key
6.3 单表数据倾斜优化
为了减少shuffle数据量以及reduce端的压力,通常Spark SQL在map端会做一个partial aggregate(就是预聚合的操作),即在shuffle前将同一分区内所属的相同key的记录进行预聚合,再将结果进行shuffle,发送到reduce端再做汇总,有点类似MR中的combiner操作,所以执行计划中的HashAggregate通常是成对出现的。
但是预聚合有个缺陷,有一种场景:大key分布在大量不同的map端,就算提前在map端预聚合,下游reduce端还是会聚合大量数据。如果出现这种场景,我们可以自己实现两次MR,对大key先加一个随机数打散到多个reduce task中进行聚合,然后去掉前面的随机数,再第二个reduce中再进行聚合。
6.4 Join数据倾斜优化
6.4.1 广播Join
1、适用场景
适用于小表join大表。小表足够小,可以被加载进Driver驱动程序所在节点内存并通过BroadCast方法广播到各个Executor的内存中。
2、解决逻辑
在小表join大表时如果产生数据倾斜,那么广播join可以直接规避掉此shuffle阶段。直接优化掉stage。并且广播join也是Spark SQL中最常用的优化方案。
6.4.2 拆分key,打散大表 扩容小表
1、适用场景
适用于join时出现数据倾斜
2、解决逻辑
1)将存在数据倾斜的表,根据抽样结果,拆分成倾斜key(skew表)和没有倾斜key(common)的两个数据集
2)将skew表的key全部加上随机前缀,然后对另一个不存在严重倾斜的数据集(old表)整体与随机前缀数据集作笛卡尔积(即将数据量扩大N倍,得到new表)
3)打散的skew表 join 扩容的new表
4)没有倾斜的表直接和B表进行join得到一张表
5)最后union两张表