本文参考了《Spark SQL内核剖析》(朱峰、张韶全、黄明等著)的目录结构和内容,这本书主要集中在对SQL内核实现的剖析上,从源码实现上学习分布式计算和数据库领域的相关技术,非常值得有相关需求的专业人士学习和购买。我写这篇文章的目的也是基于此学习Spark SQL以及分享一些自己的理解。

什么是Spark SQL?

Spark SQL是近年来SQL-on-Hadoop解决方案(包括Hive、Presto和Impala等)中的佼佼者,结合了数据库SQL处理和Spark分布式计算模型两个方面的技术,目标是取代传统的数据仓库。

上一部分 Spark SQL内核剖析—学习(二)介绍了Spark SQL 编译器 Parser的实现方式以及Spark SQL逻辑算子树生成、分析和优化流程的技术原理和实现方式。本部分将介绍Spark SQL 物理计划的处理流程。

5. Spark SQL 物理计划(PhysicalPlan)

物理计划阶段是Spark SQL整个查询处理流程的最后一步,在此阶段Spark SQL会对生成的逻辑算子树进行进一步处理,得到物理算子树,并将LogicalPlan节点及其包含的各种信息映射成Spark Core计算模型的元素,如RDD、Transformation和Action等,以支持其提交执行。

5.1. 物理计划概述

物理计划可分为三个阶段,这三个阶段分别产生Iterator[PhysicalPlan]、SparkPlan和Prepared SparkPlan,其中Prepared SparkPlan可以直接提交并执行(这里的SparkPlan和PhysicalPlan均表示物理计划)。具体来讲,这三个阶段的工作分别如下:

  1. 有SparkPlanner将各种物理计划策略(Strategy)作用于对应的LogicalPlan节点上,生成SparkPlan列表(一个LogicalPlan可能生成多种SparkPlan)。
  2. 选取最佳的SparkPlan,在Spark2.10版本直接用next()获取第一个。
  3. 提交前准备工作,进行分区排序处理,确保SparkPlan各节点能够正确执行,这一步通过PrepareForExecution()方法调用若干规则(Rule)进行转换。

5.2. SparkPlan

在物理算子树中,叶子类型的SparkPlan节点负责创建RDD,每个非叶子类型的SparkPlan节点等价于在RDD上进行一次Transformation,即通过调用execute()函数转换新的RDD,最终执行collect()操作触发计算操作,返回结果给用户。此外,SparkPlan还有可能对RDD的分区做调整,直接调用executeBroadcast方法,将数据广播到集群上。