Spark SQL catalyst概述和SQL Parser的具体实现
之前已经对spark core做了较为深入的解读,在如今SQL大行其道的背景下,spark中的SQL不仅在离线batch处理中使用广泛,structured streamming的实现也严重依赖spark SQL。因此,接下来,会对spark SQL做一个较为深入的了解。
本文首先介绍一下spark sql的整体流程,然后对这个流程之中涉及到的第一个步骤:SQL语法解析部分做一下较为深入的分析。
1,spark sql概述
首先截取一张任何介绍spark sql实现都会出现的图(如下)。
总体执行流程如下:从提供的输入API(SQL,Dataset, dataframe)开始,依次经过unresolved逻辑计划,解析的逻辑计划,优化的逻辑计划,物理计划,然后根据cost based优化,选取一条物理计划进行执行。从unresolved logical plan开始, sql的查询是通过抽象语法树(AST)来表示的,所以以后各个操作都是对AST进行的等价转换操作。 针对以上过程作如下几点说明:
1,编程接口:通过像df.groupBy("age")这样的Dataset接口构造查询过程,抽象语法树(AST)会自动建立。而通过“SELECT name, count(age) FROM people where age > 21 group by name” 这样的sql语句进行查询时,需要增加一个步骤是,需要将SQL解析成AST(spark 2.2中目前是借助于antlr4来做的,具体见后面分析)。
2,经过步骤1后,我们可以得到unresolved logical plan,此时像以上sql中的name,count(age),people都是unresolved attribute,relation等,他们是AST树TreeNode的一中类型,但是他们是不能被计算的(实现了Unevaluable接口)。
3,unresolved logical plan通过Analyzer模块定义的一系列规则,将步骤2中的unresolved的attribute,relation借助catalog去解析,如将之前提到的unresolved attribute转换成resolved attribute。此时,如果sql中某个表不存在或者列和表不对应,在此阶段便可以发现。Analyzer定义一系列部分规则如下:
4,解析成resolved logical plan以后,通过一系列优化规则会将resolved logical plan的AST转化成optimized logical plan的AST。这些优化包括基于规则和代价的优化,比如谓词下推,列值裁剪等。
5,AST到了optimized logical plan以后,利用如下的策略将逻辑计划转化成物理计划,物理计划是可以执行的计划。当有相关的action操作时,物理计划便可以执行。
2,SQL Parser的具体实现
在上节步骤1中提到,如果使用选择使用SQL进行查询,首先需要将SQL解析成spark中的抽象语法树(AST)。在spark中是借助开源的antlr4库来解析的。Spark SQL的语法规则文件是:SqlBase.g4。该文件以及生成的相关文件截图如下。
在生成的文件中SqlBaseBaseListener和SqlBaseBaseVistor分别代表两种遍历AST的方法,在spark中主要用了visitor模式。
接下来,将看一下spark中,当使用spark.sql("select *** from ...")时,sql怎么解析成spark内部的AST的?
1,用户调用的spark.sql的入口是sparkSession中sql函数,该函数最终返回DataFrame(DataSet[Row]),sql的解析的过程主要是在
sessionState.sqlParser.parsePlan(sqlText)中发生的。
def sql(sqlText: String): DataFrame = {
Dataset.ofRows(self, sessionState.sqlParser.parsePlan(sqlText))
}
2,调用到parsePlan,将调用parse函数,传入的两个参数分为:sql语句,sqlBaseParse到LogicalPlan的一个函数。
override def parsePlan(sqlText: String): LogicalPlan = parse(sqlText) { parser =>
astBuilder.visitSingleStatement(parser.singleStatement()) match {
case plan: LogicalPlan => plan
case _ =>
val position = Origin(None, None)
throw new ParseException(Option(sqlText), "Unsupported SQL statement", position, position)
}
}
3,在parse函数中,首先构造SqlBaseLexer词法分析器,接着构造Token流,最终SqlBaseParser对象,然后一次尝试用不同的模式去进行解析。最终将执行parsePlan中传入的函数。
4,在步骤2中,astBuilder是SparkSqlAstBuilder的实例,在将Antlr中的匹配树转换成unresolved logical plan中,它起着桥梁作用。
astBuilder.visitSingleStatement使用visitor模式,开始匹配SqlBase.g4中sql的入口匹配规则:
singleStatement
: statement EOF
;
递归的遍历statement,以及其后的各个节点。在匹配过程中,碰到叶子节点,就将构造Logical Plan中对应的TreeNode。如当匹配到
singleTableIdentifier
: tableIdentifier EOF
;
规则时(单表的标识符)。即调用的函数如下:
override def visitSingleTableIdentifier(
ctx: SingleTableIdentifierContext): TableIdentifier = withOrigin(ctx) {
visitTableIdentifier(ctx.tableIdentifier)
}
可以看到将递归遍历对应的tableIdentifier,tableIdentifier的定义和遍历规则如下:
tableIdentifier
: (db=identifier '.')? table=identifier
;
override def visitTableIdentifier(
ctx: TableIdentifierContext): TableIdentifier = withOrigin(ctx) {
TableIdentifier(ctx.table.getText, Option(ctx.db).map(_.getText))
}
可以看到当匹配到tableIdentifier,将直接生成TableIdentifier对象,而该对象是TreeNode的一种。经过类似以上的过程,匹配结束后整个spark内部的抽象语法树也就建立起来了。
3,小结
本文主要介绍spark catalyst的总体执行情况,以及sql parse的具体实现细节。接下来,计划还将对Analyzer,Optimization,以及执行的过程做更深入的分析。
Spark SQL catalyst概述和SQL Parser的具体实现的更多相关文章
- Oracle-05-SQL语句概述、分类&SQL*PLUS概述(初识insert,desc,list,r,del,a,c,n等命令)
一.SQL语句概述 (1)SQL全程是"结构化查询语言(Structured Query Language)". SQL是大多数主流数据库系统採用的标准查询语言. (2)SQL语句 ...
- 第八篇:Spark SQL Catalyst源码分析之UDF
/** Spark SQL源码分析系列文章*/ 在SQL的世界里,除了官方提供的常用的处理函数之外,一般都会提供可扩展的对外自定义函数接口,这已经成为一种事实的标准. 在前面Spark SQL源码分析 ...
- 第三篇:Spark SQL Catalyst源码分析之Analyzer
/** Spark SQL源码分析系列文章*/ 前面几篇文章讲解了Spark SQL的核心执行流程和Spark SQL的Catalyst框架的Sql Parser是怎样接受用户输入sql,经过解析生成 ...
- 第二篇:Spark SQL Catalyst源码分析之SqlParser
/** Spark SQL源码分析系列文章*/ Spark SQL的核心执行流程我们已经分析完毕,可以参见Spark SQL核心执行流程,下面我们来分析执行流程中各个核心组件的工作职责. 本文先从入口 ...
- Spark SQL Catalyst源代码分析之UDF
/** Spark SQL源代码分析系列文章*/ 在SQL的世界里,除了官方提供的经常使用的处理函数之外.一般都会提供可扩展的对外自己定义函数接口,这已经成为一种事实的标准. 在前面Spark SQL ...
- Spark SQL Catalyst源代码分析之Analyzer
/** Spark SQL源代码分析系列文章*/ 前面几篇文章解说了Spark SQL的核心运行流程和Spark SQL的Catalyst框架的Sql Parser是如何接受用户输入sql,经过解析生 ...
- Spark SQL Catalyst源代码分析之TreeNode Library
/** Spark SQL源代码分析系列文章*/ 前几篇文章介绍了Spark SQL的Catalyst的核心执行流程.SqlParser,和Analyzer,本来打算直接写Optimizer的,可是发 ...
- Spark SQL Catalyst源代码分析Optimizer
/** Spark SQL源代码分析系列*/ 前几篇文章介绍了Spark SQL的Catalyst的核心运行流程.SqlParser,和Analyzer 以及核心类库TreeNode,本文将具体解说S ...
- Spark SQL / Catalyst 内部原理 与 RBO
原创文章,转载请务必将下面这段话置于文章开头处. 本文转发自技术世界,原文链接 http://www.jasongj.com/spark/rbo/ 本文所述内容均基于 2018年9月10日 Spark ...
随机推荐
- 合肥 专业做APP(安卓,ios) 微信公共平台
合肥 专业做APP(安卓,ios) 微信公共平台 电话:15715696592
- EasyUI+Python-flask实现CRUD应用
1.需求分析 需求:应用easyui制作前端表格数据显示,flask制作后端路由 环境搭建略 2.easyui前端实现 2.1 easyui是前端实用的一个框架,这里我们要实现的是easyui的CRU ...
- TTL以及LVDS接口传输【转】
本文转载自:http://blog.csdn.net/jscese/article/details/16860833 TTL接口:属于并行方式传输数据的接口,采用这种接口时,不必在液晶显示器的驱动板端 ...
- 一步一步学Silverlight 2系列(23):Silverlight与HTML混合之无窗口模式
概述 Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, ...
- Android隐藏Activity和图标
今天发现4.0以后如果不写Activity只写BroadcastReceiver的话,这个广播接收器是不能运行的.经过查询,好像是HoneyComb之后添加了安全机制,规定必须运行一次Activity ...
- I.MX6 Parallel RGB LCD Datasheet描述
/******************************************************************** * I.MX6 Parallel RGB LCD Datas ...
- Android gif 录屏
/********************************************************************************** * Android gif 录屏 ...
- BZOJ_4278_[ONTAK2015]Tasowanie_后缀数组
BZOJ_4278_[ONTAK2015]Tasowanie_后缀数组 Description 给定两个数字串A和B,通过将A和B进行二路归并得到一个新的数字串T,请找到字典序最小的T. Input ...
- bzoj3302
树形dp 很明显我们可以枚举一条边,然后求两边的重心,这样是暴力,我们用一些奇怪的方法来优化这个找重心的过程,我们先预处理出来每个点最大和第二的儿子,然后每次把断掉的子树的贡献减掉,每次找重心就是向最 ...
- vs2008控制台程序运行一闪而过,不显示按任意键继续
调试运行(F5)而且没插断点.且程序没有暂停的点,就会一闪而过 直接执行(Ctrl+F5),在程序结束前会有“按任意键继续” 当你不想进入调试状态,只想看一看程序执行结果时用ctrl+f5F5会进入调 ...