目录
一:DataFrame lazy特性
二:HiveContext.sql() SQL起始
三:SQLContext.executeSql() 正式执行
四:Spark SQL 具体转换解析分析
//在用户拿到了封装的 Unresolved LogicalPlan的DataFrame之后
//执行一些 show(),select(),show(),groupBy(),show() 等操作
//在一系列的transformation操作后,在执行一个action操作
//在触发后续优化 SQL 的步骤
入口:=======================================================================
HiveContext.sql()
org.apache.spark.sql.SQLContext.scala.
sql()调用
DataFrame(this, parseSql(sqlText))
parseSql()
ddlParser(sql, false).getOrElse(sqlParser(sql))
1.sqlParser
val fallback = new catalyst.SqlParser
最后返回一个DataFrame对象
=============================================
org.apache.spark.sql.catalyst.SparkSQLParser.scala
org.apache.spark.sql.catalyst.AbstractSparkSQLParser.apply()
new lexical.Scanner(input) ==》
用 lexical.Scanner,进行语法检查,分析。
如果满足,则使用SQL解析器针对SQL进行解析:包括词法解析(将SQL语句解析成一个个的短语,token)、语法解析
最后生成一个Unreasolved LogicalPlan
图:
1.SQLContext.executeSql() 方法
SQLContext.scala.QueryExecution()
2.lazy val analyzed: LogicalPlan = analyzer(logical)
3.useCachedData()
执行缓存的操作:如果之前缓存过这个执行计划,那么就使用缓存中的数据
4.optimizer(withCacheData)
org.apache.spark.sql.catalyst.optimizer.Optimizer.scala
直接使用建议的方式来编写SQL语句,这样避免了 Spark SQL 内部的优化,某种程度上提升了性能
5.. lazy val sparkPlan: SparkPlan = {
SparkPlan.currentContext.set(self)
planner(optimizedPlan).next()
}
optimized logical plan –> spark plan
逻辑计划 —— 》 物理计划
6.
lazy val executedPlan: SparkPlan = prepareForExecution(sparkPlan)
spark plan -> executed Plan 在SparkPlan中插入Shuffle的操作
7. executed Plan -> RDD[Row] 物理计划的执行,最终转变为 RDD返回 (详情参见之前Spark Core 的核心源码)
/** Internal version of the RDD. Avoids copies and has no schema */
lazy val toRdd: RDD[Row] = executedPlan.execute()
================================================ Analyzer.scala
=> org.apache.spark.sql.catalyst.analysis.Analyzer.scala
RuleExecutor.scala .apply()
将LogicalPlan 将它要查询的数据源绑定起来
通过遍历取出Analyzer中定义的batches里存储的每一个Batch,每一个Batch中会封装同属某一个类别的Rule及其相应的执行策略
lazy val batches: Seq[Batch] = Seq()
图:
Spark SQL 的SQL处理引擎分析
https://blog.csdn.net/weixin_39966065/article/details/93745012
图: