sparksql到RDD


从SQL到RDD:一个简单的案例

从典型的Spark SQL应用场景中,数据的读取、数据表的创建和分析都是必不可少的过程。
通常来讲,SQL查询所面对的数据模型以关系表为主。
转自《Spark SQL内核剖析》

一个简单的案例

1
2
3
4
5
6
7
8
9
10
11
1、初始化SparkSession
val spark = SparkSession.builder().appName('example').master('local').getOrCreate()
2、创建数据表并读取数据
spark.read.json("student.json").createOrReplaceTempView("student")
student.json
{"id":1,"name":"Kate","age":29}
{"id":2,"name":"Andy","age":30}
{"id":3,"name":"Tony","age":10}
3、通过SQL语句查询数据
spark.sql("select name from student where age > 18").show()

案例中设计到的操作分为3步。
1、创建SparkSession类。从2.0版本开始。SparkSession逐步取代SparkContext成为Spark应用程序的入口。
2、创建数据表并读取数据。这里假设数据存储在本地名为student的json文件中,包含3条记录且每条记录包含3个列(分别对应学生的id、name、和age)。
3、通过SQL进行数据分析。在SparkSession类的sql方法中可以输入任意满足语法的语句。

上述案例中第2步创建数据表时虽然没有显示调用SQL语句(如关系数据库中的”create table”),但是其本质上也是一种(DDL操作),
在内部转化执行时,所涉及的流程和第三步执行SQL查询的流程类似。因此,从一般性考虑,后续内容只对第3步背后的实线进行分析。

这里首先从通用的角度介绍SQL转换的过程。
一般来讲,对于Spark SQL系统,从SQL到Spark中RDD的执行需要经过两个大的阶段,分别是逻辑计划(LogicalPlan)和物理计划(PhysicalPlan)。

逻辑计划

逻辑计划阶段会将用户所写的SQL语句转换成树型数据结构(逻辑算子树),SQL语句中蕴含的逻辑映射到逻辑算子树的不同节点。
逻辑计划阶段生成的逻辑算子树并不会直接提交执行,仅作为中间阶段。

最终逻辑算子树的生成过程经历3个子阶段:
1、分别对应未解析的逻辑算子树(Unresolved LogicalPlan,仅仅数据结构,不包含任何数据信息等);
2、解析后的逻辑算子树(Analyzed LogicalPlan,节点中绑定各种信息);
3、优化后的逻辑算子树(Optimized LogicalPlan,应用各种优化规则对一些低效的逻辑计划进行转换)。

物理计划

物理计划阶段将上一步逻辑计划阶段生成的逻辑算子树进行近一步转换,生成物理算子树。
物理算子树的节点会直接生成RDD或对RDD进行transformation操作(注:每个物理计划节点中都是先了对RDD进行转换的execute方法)。

物理计划阶段也包含3个子阶段:
1、首先根据逻辑算子树,生成物理算子树的列表Iterator[PhysicalPlan](同样的逻辑算子树可能对应多个物理算子树);
2、然后从列表中按照一定的策略选取最优的物理算子树(SparkPlan);
3、最后对选取的物理算子树进行提交前的准备工作,确保分区操作正确、物理算子树节点重用、执行代码生成等,
得到”准备后”的物理算子树(Prepared SparkPlan)。
物理算子树生成的RDD执行action操作(图片中的show),即可提交执行。

SQL提交

从SQL语句的解析一直到提交之前,上述整个转换过程都在Spark集群的Driver端进行,不涉及分布式环境。
SparkSession类的SQL方法调用SessionState中的各种对象,包括上述不同阶段对应的 **SparkSqlParser类、Analyzer类、Optimizer类和SparkPlanner类等,
最后封装成一个QueryExecution对象。因此,在进行SparkSQL开发时,可以很方便地将每一步生成的计划单独剥离出来分析。
SQL语句较为简单(不包含JOIN和Aggregation等操作),因此其转换过程也相对简单。
左上角是SQL语句,生成的逻辑算子树中有Relation、Filter和Project节点,分别对应数据表、过滤逻辑(age > 18)和列剪裁逻辑(只涉及student表中3列的2列)。
下一步的物理算子树丛逻辑算子树一对一映射得到,
1、Relation 逻辑节点转换为FileSourceScanExec执行节点。
2、Filter 逻辑节点转为FilterExec执行节点。
3、Project 逻辑节点转换为ProjectExec执行节点。

生成的物理算子树根节点是ProjectExec,每个物理节点中的execute函数都是执行调用接口,
由根节点开始递归调用,从叶子节点开始执行。
上图展示了物理算子树的执行逻辑,与直接采用RDD进行编程类似。
需要注意的是,FileSourceScanExec叶子执行节点中需要构造数据源对应的RDD,
FilterExec和ProjectExec中的execute函数对RDD执行影响的transformation操作。


文章作者: Callable
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Callable !
评论
  目录