Spark3.0新特性:SQL相关

本文介绍了Apache Spark 3.0引入的动态分区修剪和自适应查询执行(AQE)两大优化技术,前者通过实时成本计算减少无效数据读取,后者能动态调整执行计划提升性能。此外,文章还探讨了映射下推和谓词下推在列式存储中的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、动态分区修剪(Dynamic Partition Pruning)

二、自适应查询执行(Adaptive Query Execution)

三、映射下推(Project PushDown)

四、谓词下推(Predicate PushDown)


一、动态分区修剪(Dynamic Partition Pruning)

静态分区裁剪优化

过滤提前,减少无效数据读写,尤其在 join 时,效果很明显

 

 

            

 

 

对比一下 Spark 2.X

 

在 Spark 2.x 里面加了基于代价的优化,但是这个并不表现的很好。主要有以下几个原因:

统计信息的缺失;统计信息过期;很难抽象出一个通用的 cost model。

 

为了解决这些问题,Apache Spark 3.0 引入了基于 Runtime 的查询优化。

 

第一个就是动态分区裁减

 

比如上面的 SQL 查询,假设 t2 表 t2.id < 2 过滤出来的数据比较少,但是由于之前版本的 Spark 无法进行动态计算代价,所以可能会导致 t1 表扫描出大量无效的数据。有了动态分区裁减,可以在运行的时候过滤掉 t1 表无用的数据

经过这个优化,查询扫描的数据大大减少,性能提升了 33 倍

 

 

二、自适应查询执行(Adaptive Query Execution

 

而有了 AQE(自适应查询执行) 之后,Spark 就可以动态统计相关信息,并动态调整执行计划,比如把 SortMergeJoin 变成 BroadcastHashJoin:

 

spark.sql.optimizer.dynamicPartitionPruning.enabled 参数必须设置为 true,

 

三、映射下推(Project PushDown)

说到列式存储的优势,映射下推是最突出的,它意味着在获取表中原始数据时只需要扫描查询中需要的列,由于每一列的所有值都是连续存储的,所以分区取出每一列的所有值就可以实现TableScan算子,而避免扫描整个表文件内容。

在Parquet中原生就支持映射下推,执行查询的时候可以通过Configuration传递需要读取的列的信息,这些列必须是Schema的子集,映射每次会扫描一个Row Group的数据,然后一次性得将该Row Group里所有需要的列的Cloumn Chunk都读取到内存中,每次读取一个Row Group的数据能够大大降低随机读的次数,除此之外,Parquet在读取的时候会考虑列是否连续,如果某些需要的列是存储位置是连续的,那么一次读操作就可以把多个列的数据读取到内存。

 

四、谓词下推(Predicate PushDown)

在数据库之类的查询系统中最常用的优化手段就是谓词下推了,通过将一些过滤条件尽可能的在最底层执行可以减少每一层交互的数据量,从而提升性能,

例如”select count(1) from A Join B on A.id = B.id where A.a > 10 and B.b < 100”SQL查询中,在处理Join操作之前需要首先对A和B执行TableScan操作,然后再进行Join,再执行过滤,最后计算聚合函数返回,但是如果把过滤条件A.a > 10和B.b < 100分别移到A表的TableScan和B表的TableScan的时候执行,可以大大降低Join操作的输入数据。

无论是行式存储还是列式存储,都可以在将过滤条件在读取一条记录之后执行以判断该记录是否需要返回给调用者,在Parquet做了更进一步的优化,优化的方法时对每一个Row Group的每一个Column Chunk在存储的时候都计算对应的统计信息,包括该Column Chunk的最大值、最小值和空值个数。通过这些统计值和该列的过滤条件可以判断该Row Group是否需要扫描。另外Parquet还增加诸如Bloom Filter和Index等优化数据,更加有效的完成谓词下推。

在使用Parquet的时候可以通过如下两种策略提升查询性能:

1、类似于关系数据库的主键,对需要频繁过滤的列设置为有序的,这样在导入数据的时候会根据该列的顺序存储数据,这样可以最大化的利用最大值、最小值实现谓词下推。

2、减小行组大小和页大小,这样增加跳过整个行组的可能性,但是此时需要权衡由于压缩和编码效率下降带来的I/O负载。

 

PartitionFilter分区过滤:创建表的时候为分区表

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值