Spark3.0新特性AQE DPP

新特性

  • 动态分区剪裁(Dynamic Partition Pruning)
  • ⾃适应查询执⾏(Adaptive Query Execution)
  • 加速器感知调度(Accelerator-aware Scheduling)
  • ⽀持 Catalog 的数据源API(Data Source API with Catalog Supports)
  • SparkR 中的向量化(Vectorization in SparkR)
  • ⽀持Hadoop 3/JDK 11/Scala 2.12 等等。

AQE(Adaptive Query Execution,⾃适应查询执⾏)

AQE是Spark SQL的⼀种动态优化机制,是对查询执⾏计划的优化。
我们可以设置参数 spark.sql.adaptive.enabled 为true来开启AQE,在Spark 3.0中默认是
false。
在运⾏时,AQE会结合Shuffle Map阶段执⾏完毕后的统计信息,基于既定的规则动态地调
整、修正尚未执⾏的逻辑计划和物理计划,来完成对原始查询语句的运⾏时优化。
在介绍AQE之前我们先讲解两个优化策略:

  • RBO(Rule Based Optimization,基于规则的优化)。它往往基于⼀些规则和策略实现,如
    谓词下推、列剪枝,这些规则和策略来源于数据库领域已有的应⽤经验。也就是说,启
    发式的优化实际上算是⼀种「经验主义」。
  • CBO(Cost Based Optimization,基于成本的优化)。CBO是⼀种基于数据统计信息例如数
    据量、数据分布来选择代价最⼩的优化策略的⽅式。
    RBO相对于CBO⽽⾔要成熟得多,常⽤的规则都基于经验制定,可以覆盖⼤部分查询场景,
    并且⽅便扩展。其缺点则是不够灵活,对待相似的问题和场景都使⽤同⼀类解决⽅案,忽略
    了数据本身的信息。

Spark在2.2版本中推出了CBO,主要就是为了解决RBO 「经验主义」 的弊端。
AQE的三⼤特性包括: Join策略调整 、 分区⾃动合并 、 ⾃动倾斜处理 。

Join策略调整

在这里插入图片描述

Spark ⽀持的许多 Join 策略中,Broadcast Hash Join通常是性能最好的,前提是参加 join 的
⼀张表的数据能够装⼊内存。由于这个原因,当 Spark 估计参加 join 的表数据量⼩于⼴播⼤
⼩的阈值时,其会将 Join 策略调整为 Broadcast Hash Join。但是,很多情况都可能导致这种
⼤⼩估计出错——例如存在⼀个⾮常有选择性的过滤器。

由于AQE可以精确的统计上游数据,因此可以解决该问题。⽐如下⾯这个例⼦,右表的实际
⼤⼩为15M,⽽在该场景下,经过filter过滤后,实际参与join的数据⼤⼩为8M,⼩于了默认
broadcast阈值10M,应该被⼴播。

在我们执⾏过程中转化为Broadcast Hash Join的同时,我们甚⾄可以将传统shuffle优化为本地shuffle(例如shuffle读在mapper⽽不是基于reducer)来减⼩⽹络开销。

分区⾃动合并

在我们处理的数据量级⾮常⼤时,shuffle通常来说是最影响性能的。因为shuffle是⼀个⾮常
耗时的算⼦,它需要通过⽹络移动数据,分发给下游算⼦。

在shuffle中,partition的数量⼗分关键。partition的最佳数量取决于数据,⽽数据⼤⼩在不同
的query不同stage都会有很⼤的差异,所以很难去确定⼀个具体的数⽬。

在这部分,有两个⾮常重要的参数⽤来控制⽬标分区的⼤⼩:

  • spark.sql.adaptive.advisoryPartitionSizeInBytes ,分区合并后的推荐尺⼨
  • spark.sql.adaptive.coalescePartitions.minPartitionNum ,分区合并后最⼩分区

为了解决该问题,我们在最开始设置相对较⼤的shuffle partition个数,通过执⾏过程中
shuffle⽂件的数据来合并相邻的⼩partitions。 例如,假设我们执⾏ SELECT max(i) FROM t
able GROUP BY j ,表table只有2个partition并且数据量⾮常⼩。我们将初始shuffle partition
设为5,因此在分组后会出现5个partitions。若不进⾏AQE优化,会产⽣5个tasks来做聚合结
果,事实上有3个partitions数据量是⾮常⼩的
在这里插入图片描述
这种情况下,AQE⽣效后只会⽣成3个reduce task。
在这里插入图片描述

⾃动倾斜处理

Spark Join操作如果出现某个key的数据倾斜问题,那么基本上就是这个任务的性能杀⼿了。
在AQE之前,⽤户没法⾃动处理Join中遇到的这个棘⼿问题,需要借助外部⼿动收集数据统
计信息,并做额外的加盐,分批处理数据等相对繁琐的⽅法来应对数据倾斜问题。

AQE根据shuffle⽂件统计数据⾃动检测倾斜数据,将那些倾斜的分区打散成⼩的⼦分区,然
后各⾃进⾏join。

我们可以看下这个场景,Table A join Table B,其中Table A的partition A0数据远⼤于其他分
区。
在这里插入图片描述

AQE会将partition A0切分成2个⼦分区,并且让他们独⾃和Table B的partition B0进⾏join。
在这里插入图片描述
如果不做这个优化,SMJ将会产⽣4个tasks并且其中⼀个执⾏时间远⼤于其他。经优化,这个
join将会有5个tasks,但每个task执⾏耗时差不多相同,因此个整个查询带来了更好的性能。
关于如何定位这些倾斜的分区,主要靠下⾯三个参数:

  • spark.sql.adaptive.skewJoin.skewedPartitionFactor ,判定倾斜的倾斜因⼦
  • spark.sql.adaptive.skewJoin.skewedPartitionThresholdInBytes ,判定倾斜的最
    低阈值
  • spark.sql.adaptive.advisoryPartitionSizeInBytes ,倾斜数据分区拆分,⼩数据分
    区合并优化时,建议的分区⼤⼩(以字节为单位)

DPP(Dynamic Partition Pruning,动态分区剪裁)

所谓的动态分区裁剪就是基于运⾏时(run time)推断出来的信息来进⼀步进⾏分区裁剪,
从⽽减少事实表中数据的扫描量、降低 I/O 开销,提升执⾏性能。

我们在进⾏事实表和维度表的Join过程中,把事实表中的⽆效数据进⾏过滤,例如:
SELECT * FROM dim
JOIN fact
ON (dim.col = fact.col)
WHERE dim.col = ‘dummy’

当SQL满⾜DPP的要求后,会根据关联关系 dim.col = fact.col ,通过维度表的列传导到事
实表的col字段,只扫描事实表中满⾜条件的部分数据,就可以做到减少数据扫描量,提升
I/O效率。

但是使⽤DPP的前提条件⽐较苛刻,需要满⾜以下条件:

  1. 事实表必须是分区表
  2. 只⽀持等值Join
  3. 维度表过滤之后的数据必须⼩于⼴播阈值: spark.sql.autoBroadcastJoinThreshold

以上就是Spark3.0中最重要的两个特性 AQE 和 DPP 了。

  • 16
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值