一、Spark SQL架构分析

Spark SQL架构与传统的查询优化器+执行器类似,只不过Spark SQL基于分布式环境来实现,并采用Spark作为执行引擎。在Spark SQL中catalyst会将SQL翻译成最终的执行计划,并在这个过程中进行查询计划。最终会在Spark内部将执行计划转换为DAG来执行。

因此Catalyst是Spark SQL的调度核心,其执行流程如下:

Sparksql 优化案例 spark sql 优化器_列式存储


SqlParser将SQL首先转换为逻辑查询计划,Analyzer对逻辑查询计划进行属性和关系关联的检验,之后Optimizer通过逻辑查询优化将逻辑查询计划转换为优化的逻辑查询计划,QueryPlanner将优化的逻辑查询计划转换为物理计划,prepareExecution调整数据分布,最后将物理查询计划转换为执行计划进行Spark执行计划。

二、Spark SQL优化策略

(1)内存列式存储与内存缓存表
Spark SQL可以通过cacheTable将数据存储转换为列式存储,同时将数据加载到内存缓存,cacheTable相当于分布式集群的内存视图(物化),将数据进行缓存,这样会避免从磁盘读取数据,减少了I/O开销。使用列式存储的优点在于查询时只需读出相应的列即可,而不需要将所有的列都读取出来,占用内存数据缓存,同时减少网络传输和I/O开销,数据按照列式存储,由于数据类型都相同,因此能够利用序列化和压缩减少内存空间的占用。

(2)列式存储压缩
为了减内存和硬盘的空间占用,Spark SQL采用了一些压缩策略对内存列存储数据进行压缩,比如它支持PassThrough、RunLengthEncoding、DictionaryEncoding、BooleanBitSet等多种压缩方式。

(3)逻辑查询优化
Spark SQL在逻辑查询优化时会支持列剪枝,谓词下压,属性合并等逻辑查询优化方法。列剪枝为了减少读取不必要的属性列,减少数据传输和计算开销,在查询优化器进行转换过程的过程中优化列剪枝。
下面看 一下简单的例子:

SELECT class FROM(SELECT ID,Name,Class FROM STUDENT) S WHERE S.ID=1

Sparksql 优化案例 spark sql 优化器_查询优化_02


catalyst将原有的查询通过谓词下压,将选择操作ID=1优先执行,这样过滤掉大部分数据,通过属性合并将最后的投影只做一次,保存Class属性列。

(4)Join优化
Spark SQL中对join进行了优化,支持多种连接算法,如BroadcastHashJoin、BroadcastNestedLoopJoin、HashJoin、LeftSemiJoin等。
以BroadcastHashJoin为例,它会将小表转换为广播变量进行广播,这样避免Shuffle开销,最后在分区内做Hash连接。这里的思想和Hive中的Map Side Join的思想类似,当然 也可以利用该思想解决部分数据倾斜。