Spark SQL新特性

想要更全面了解Spark内核和应用实战,可以购买我的新书。

图解Spark 大数据快速分析实战(作者:王磊)

在这里插入图片描述

在Spark 3.0中,Spark SQL拥有如下新特性。

• 动态合并Shuffle分区。
• 动态调整表关联策略。
• 动态优化倾斜的表关联操作。
• 动态分区裁剪。
• 兼容ANSI SQL。
• 支持更丰富的Join Hints。

1. 动态合并Shuffle分区

我们首先来看一下为什么分区这么重要。
(1)如果分区过小,那么不仅I/O低效,而且会产生调度开销和任务启动开销。
(2)如果分区过大,那么GC压力就会很大且容易溢写硬盘。
(3)在实践中,整个查询在执行过程中通常使用统一的分区数,但在查询执行的不同阶段,数据规模会变,因此分区对Spark性能影响很大。
基于以上原因,Spark提供了动态合并Shuffle 分区的功能,目的就是简化甚至避免调整Shuffle分区的数量。在真实场景中,不同分区的数据量不同,数据量大的分区所对应任务的执行时间较长,数据量小的分区所对应任务的执行时间较短,这样在运行过程中某些资源就被浪费了。另外,如果每个分区的数据量都比较小,那么对应任务的数量就会比较多。通过AQE,我们可以将数据量较小的分区组合起来分配给一个任务处理,从而使得每个任务处理的数据量都比较均衡且大小合理。
那么,AQE是如何动态调整分区呢?首先设置较大的初始分区数以满足整个查询在执行过程中所需的最大分区数;然后在每个查询阶段结束后,按需自动合并分区。
如图8-5所示,普通的Shuffle操作并没有自动合并,而是根据指定的分区数进行分区:Reduce过程中包含Reduce1、Reduce2、Reduce3、Reduce4、Reduce5共5个分区,运行时间长;使用AQE自动合并的Shuffle分区则会合并相邻的小分区Reduce2、Reduce3、Reduce4,因而最终只包含3个分区,运行时长和资源利用率都有了提高。
在这里插入图片描述

下面通过一个例子介绍如何动态合并Shuffle 分区。如图8-6所示,假设存在如下非常典型的SQL查询:select t1.id,t2.key from t1 join t2 on t1.key=t2.key and t2.id <2。以上SQL查询涉及两个表t1和t2,其中表t1比较大,表t2虽然较大,但是过滤操作可能会过滤掉其中的绝大部分值,因此在关联操作后实际产生的结果不会很多。
也就是说,关联操作在执行后,将会排除大量的数据,因此在读取表t2时,会浪费很多读的资源。但是在查询执行前,我们并不知道表t2在经过筛选后还剩下多少数据,因此不得不全部读取。

在这里插入图片描述

但是,如果考虑运行期间的统计信息,那么对于表t2来说,筛选后的数据就可以推送到右边的子树,也就是表t1,这极大提高了查询的性能,如图8-7所示。也就是说,Spark根据运行时统计信息对分区数据进行了动态合并,将SQL语句select t1.id,t2.key from t1 join t2 on t1.key=t2.key and t2.id <2优化成了select t1.id,t1.key from t1 where t1.key in(select t2.keyfrom t2 where t2.id<2)。
在这里插入图片描述

2.动态调整表关联策略

动态调整表关联策略在一定程度上避免了由于缺少统计信息或者错误估计数据量大小,而导致执行计划不理想的情况发生。
当表关联的一边可以完全放入内存时,Spark会选择Broadcast Hash Join。但是由于统计信息不够精准、子查询太复杂、“黑盒”的谓词(比如用户自定义函数导致预估可能不准确)等,使得本来可以优化为 Broadcast Hash Join的关联没有得到优化。
AQE可以使用运行时的数据大小重新选择执行计划。在具体运行时,AQE可以根据运行时信息判断来选择具体的表关联策略。例如,将Sort Merge Join转换成Broadcast Hash Join,从而进一步提升性能。
如图8-8所示,右侧的过滤操作完成后,数据量预估为25 MB,但实际为8 MB。当没有AQE时,因为Spark默认的Broadcast阈值(spark.sql.autoBroadcastJoinThreshold)为10MB,因此Spark只能通过提前预估的25 MB数据量大小选择Sort Merge Join;有了AQE之后,Spark在运行时便可以检测到实际的数据量为8 MB,因而对执行计划重新进行优化,将Sort Merge Join转换成 Broadcast Hash Join,从而提高执行效率。
在这里插入图片描述

3.动态优化倾斜的表关联操作

当表关联操作发生数据倾斜时,可对倾斜部分的数据做并行处理,以避免出现由于数据倾斜导致某个任务执行时间过长,从而影响整个任务进度的情况发生。
动态优化倾斜的表关联操作的具体实现逻辑如下:当数据发生Shuffle时,AQE会统计Shuffle后的分区个数和每个分区的数据量等信息。如果发现某个分区上的数据明显多于其他分区上的数据,就说明数据在这个分区上发生了数据倾斜,于是将发生数据倾斜的分区分割为多个小的分区,并将它们与另一侧的相应分区连接起来。这样就很好地解决了数据倾斜问题,同时提高了任务执行的并发度,另外还在整体上提高了程序的运行效率。
如图所示,当不做倾斜优化时,可以明显看出,PART.A0分区上存在数据倾斜问题。

在这里插入图片描述

如图8-10所示,启用动态优化倾斜的表关联功能后,就可以看到,之前的PART.A0分区将被划分为3个小的分区,分别为A0-S0、A0-S1、A0-S2。Spark在读取数据的时候,将使用倾斜分区数据读取器(Skew Shuffle Reader)并行地读取这三个小分区上的数据,从而很好地解决了数据倾斜问题。

如图, 经过倾斜优化后的任务的执行过程在这里插入图片描述

4.动态分区裁剪

在编译阶段,我们有时候无法准确识别数据所在的分区是否可以跳过,此时便可以利用动态分区裁剪功能,根据运行时的统计信息在任务运行过程中对任务做进一步的分区裁剪,以避免扫描不必要的数据。

5.兼容ANSI SQL

Spark 3.0为了与ANSI SQL兼容而做了进一步优化,为开发人员将其他大数据应用迁移到Spark SQL提供了很大的便利。

6.支持更丰富的Join Hints

Spark编译器无法保障在任何情况下都能对SQL做出好的执行计划,这时就需要开发人员使用Join Hints来影响优化器,促使其做出更好的执行计划。Apache Spark 3.0对Join Hints的实现进行了扩展,具体包括BROADCAST、SHUFFLE_MERGE、SHUFFLE_HASH和SHUFFLE_REPLICATE_NL。
(1)Broadcast Join的Join Hints。
如下代码能在Spark SQL中以语法格式/*+ BROADCAST(t1) */将t1表中的数据广播到各个节点上执行,从而提高执行效率。

SELECT /*+ BROADCAST(t1) */ * FROM t1 INNER JOIN t2 ON t1.key = t2.key;

能够进行这种优化的前提是,开发人员都清楚地知道要广播的表数据的大小和分布情况。除了/*+ BROADCAST(t1) /这种Join Hints之外,还有/+ BROADCASTJOIN(t1) /和/+ MAPJOIN(t2) /等Join Hints。/+ BROADCASTJOIN(t1) /用于声明只有在对表数据进行关联时才对数据进行广播,/+ MAPJOIN(t2) */用于声明在映射端对表数据进行关联,示例如下:

SELECT /*+ BROADCASTJOIN (t1) */ * FROM t1 left JOIN t2 ON t1.key = t2.key;
SELECT /*+ MAPJOIN(t2) */ * FROM t1 right JOIN t2 ON t1.key = t2.key;

(2)Shuffle Sort Merge Join的Join Hints。
如下代码分别用于实现SHUFFLE_MERGE、MERGEJOIN和MERGE的功能:
– Join Hints for shuffle sort merge join

SELECT /*+ SHUFFLE_MERGE(t1) */ * FROM t1 INNER JOIN t2 ON t1.key = t2.key;
SELECT /*+ MERGEJOIN(t2) */ * FROM t1 INNER JOIN t2 ON t1.key = t2.key;
SELECT /*+ MERGE(t1) */ * FROM t1 INNER JOIN t2 ON t1.key = t2.key;

(3)Shuffle Hash Join的Join Hints。
如下代码用于实现Shuffle Hash Join的功能:

SELECT /*+ SHUFFLE_HASH(t1) */ * FROM t1 INNER JOIN t2 ON t1.key = t2.key;

(4)Shuffle Replicate NL的Join Hints。
如下代码用于实现Shuffle Replicate NL的功能:

SELECT /*+ SHUFFLE_REPLICATE_NL(t1) */ * FROM t1 INNER JOIN t2 ON t1.key = t2.key;
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值