一、概述

Spark SQL 逻辑计划在实现层面被定义为 LogicalPlan 类。LogicalPlan 作为数据结构记录了对应逻辑算子树节点的基本信息和基本操作,包括输入输出和各种处理逻辑等。

二、实现

LogicalPlan 属于 TreeNode 体系,继承自 QueryPlan 父类。

2.1. 结构

LogicalPlan 继承自 QueryPlan,包含了两个成员变量和多个方法。

2.1.1. 成员变量

  1. resolved,用来标记该 LogicalPlan 是否为经过了解析
  2. canonicalized,重载了 QueryPlan 中的对应赋值,默认实现消除了子查询别名之后的 LogicalPlan。

三、继承体系

LogicalPlan 仍然是抽象类,根据子节点数目,绝大部分的 LogicalPlan 可以分为 3 类,即叶子节点 LeafNode 类型(不存在子节点)、一元节点 UnaryNode 类型(仅包含一个子节点)和二元节点 BinaryNode 类型(包含两个子节点)。此外,还有几个子类直接继承自 LogicalPlan,不属于这 3 种类型。

3.1. Command 接口

3.1. LeafNode 接口

LeafNode 类型的 LogicalPlan 节点对应数据表和命令(Command)相关的逻辑,因此这些 LeafNode 子类中有大部分都属于 datasources 包和 command 包。

RunnableCommand 是直接运行的命令,包括 Database 相关命令、Table 相关命令、View 相关命令、DDL相关命令、Function 相关命令和 Resource 相关命令等。例如,Database 相关命令有两个,分别是 ShowDatabasesCommand 和 SetDatabaseCommand,用于显示当前数据库名称和切换当前数据库到相应的数据库。

以 SetDatabaseCommand 命令为例,该 Command 对应 SQL 中的 use database 语句。该命令直接调用的是 Catalog 中的 set 方法。

3.2. UnaryNode 接口

一元节点 UnaryNode 类型(仅包含一个子节点),UnaryNode 类型的节点常见于对数据的逻辑转换操作,包括过滤等。

根据节点所起的不同作用,节点可以分为 4 个类别:

  1. 用来定义重分区(repartitioning)操作的 UnaryNode

  2. 转换操作 ScriptTransformation,用特定的脚本对输入数据进行转换。

  3. Object 相关操作

  4. 基本操作算子 basicLogicalOperators,如: Project、 Filter、Sort 等各种常见的关系算子。

3.3. BinaryNode 接口

BinaryNode 类型的逻辑算子树节点包括连接(Join)、集合操作(SetOperation) 和 CoGroup 3 种,其中 SetOperation 包括 Except 和 Intersect 两种算子。

3.4. ObjectProducer 接口

ObjectProducer 用于产生只包含 Object 列的行数据

3.5. Union

Union 算子其子节点数目不限,是一系列 LogicalPlan 的列表。

3.6. EventTimeWatermark

EventTimeWatermark 主要针对 Spark Streaming 中的 watermark 机制