一、SQL解析过程
### --- sql解析过程
~~~ Spark SQL 可以说是 Spark 中的精华部分。
~~~ 原来基于 RDD 构建大数据计算任务,重心在向 DataSet 转移,原来基于 RDD 写的代码也在迁移。
~~~ 使用 Spark SQL 编码好处是非常大的,尤其是在性能方面,有很大提升。
~~~ Spark SQL 中各种内嵌的性能优化比写 RDD 遵守各种最佳实践更靠谱的,尤其对新手来说。
~~~ 如先 filter 操作再 map 操作,Spark SQL 中会自动进行谓词下推;
~~~ Spark SQL中会自动使用 broadcast join 来广播小表,把 shuffle join 转化为 map join 等等。
~~~ Spark SQL对SQL语句的处理和关系型数据库类似,即词法/语法解析、绑定、优化、执行。
~~~ Spark SQL会先将SQL语句解析成一棵树,然后使用规则(Rule)对Tree进行绑定、优化等处理过程。
### --- Spark SQL由Core、Catalyst、Hive、Hive-ThriftServer四部分构成:
~~~ Core: 负责处理数据的输入和输出,如获取数据,查询结果输出成DataFrame等
~~~ Catalyst: 负责处理整个查询过程,包括解析、绑定、优化等
~~~ Hive: 负责对Hive数据进行处理
~~~ Hive-ThriftServer: 主要用于对Hive的访问
![](https://i-blog.csdnimg.cn/blog_migrate/6a25a9fd7e7e9534c86d77619390f2e5.png)
![](https://i-blog.csdnimg.cn/blog_migrate/278f9a470dc58bba8efd1a8b31f4984b.png)
~~~ # Spark SQL的代码复杂度是问题的本质复杂度带来的,
~~~ Spark SQL中的 Catalyst 框架大部分逻辑是在一个 Tree 类型的数据结构上做各种折腾,
~~~ 基于 Scala 来实现还是很优雅的,Scala 的偏函数和强大的 Case 正则匹配,
~~~ 让整个代码看起来非常优雅。
~~~ SparkSession 是编写 Spark 应用代码的入口,
~~~ 启动一个 spark-shell 会提供给你一个创建 SparkSession,
~~~ 这个对象是整个 Spark 应用的起始点。以下是SparkSession 的一些重要的变量和方法:
二、sparksql类
类 | 功能 |
catalog | 通过对这个类可以操作元数据,对数据库、表、 函数进行增删改查,内部使用SessionCatalog完成具体操作 |
table | 把一个table或view包装为一个DataFrame进行后续操作 |
emptyDataset/emptyDataFrame | 创建空的Dataset 或 DataFrame |
sql | 执行sql,返回一个DataFrame |
read或readStream | 获取数据读取器,读取各种格式的数据 |
sessionState | 维护了当前session使用的所有状态数据; 还包括SQL解析器、分析器、优化器等 |
### --- 源码提取说明
~~~ # 源码提取说明:sessionstate.scala
~~~ 59行
private[sql] class SessionState(
sharedState: SharedState,
val conf: SQLConf,
val experimentalMethods: ExperimentalMethods,
val functionRegistry: FunctionRegistry,
val udfRegistration: UDFRegistration,
catalogBuilder: () => SessionCatalog,
val sqlParser: ParserInterface,
analyzerBuilder: () => Analyzer,
optimizerBuilder: () => Optimizer,
val planner: SparkPlanner,
val streamingQueryManager: StreamingQueryManager,
val listenerManager: ExecutionListenerManager,
resourceLoaderBuilder: () => SessionResourceLoader,
createQueryExecution: LogicalPlan => QueryExecution,
createClone: (SparkSession, SessionState) => SessionState) {
三、编程代码实现
### --- 编程代码实现
package cn.yanqi.sparksql
import org.apache.spark.sql.{DataFrame, SparkSession}
object Plan {
def main(args: Array[String]): Unit = {
val spark = SparkSession
.builder()
.appName("Demo1")
.master("local[*]")
.getOrCreate()
spark.sparkContext.setLogLevel("warn")
import spark.implicits._
Seq((0, "zhansan", 10),
(1, "lisi", 11),
(2, "wangwu", 12)).toDF("id", "name", "age").createOrReplaceTempView("stu")
Seq((0, "chinese", 80), (0, "math", 100), (0, "english", 98),
(1, "chinese", 86), (1, "math", 97), (1, "english", 90),
(2, "chinese", 90), (2, "math", 94), (2, "english", 88)
).toDF("id", "subject", "score").createOrReplaceTempView("score")
val df: DataFrame = spark.sql(
"""
|select sum(v), name
| from (select stu.id, 100 + 10 + score.score as v, name
| from stu join score
| where stu.id = score.id and stu.age >= 11) tmp
|group by name
|""".stripMargin)
println(df.queryExecution)
// df.show()
val df1: DataFrame = spark.sql(
"""
|select sum(v), name
| from (select stu.id, 100 + 10 + score.score as v, name
| from stu join score on stu.id = score.id where stu.age >= 11) tmp
|group by name
|""".stripMargin)
println(df1.queryExecution)
val df2: DataFrame = spark.sql(
"""
|select sum(v), name
| from (select stu.id, 100 + 10 + score.score as v, name
| from stu join score on stu.id = score.id where stu.age >= 11) tmp
|group by name
|""".stripMargin)
println(df2.queryExecution)
// df1.show()
// 打印执行计划
// println(df.queryExecution)
spark.close()
}
}
### --- 编译打印
D:\JAVA\jdk1.8.0_231\bin\java.exe "-javaagent:D:\IntelliJIDEA\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=61251:D:\IntelliJIDEA\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath D:\JAVA\jdk1.8.0_231\jre\lib\charsets.jar;D:\JAVA\jdk1.8.0_231\jre\lib\deploy.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\access-bridge-64.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\cldrdata.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\dnsns.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\jaccess.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\jfxrt.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\localedata.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\nashorn.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunec.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunjce_provider.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunmscapi.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\sunpkcs11.jar;D:\JAVA\jdk1.8.0_231\jre\lib\ext\zipfs.jar;D:\JAVA\jdk1.8.0_231\jre\lib\javaws.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jce.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jfr.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jfxswt.jar;D:\JAVA\jdk1.8.0_231\jre\lib\jsse.jar;D:\JAVA\jdk1.8.0_231\jre\lib\management-agent.jar;D:\JAVA\jdk1.8.0_231\jre\lib\plugin.jar;D:\JAVA\jdk1.8.0_231\jre\lib\resources.jar;D:\JAVA\jdk1.8.0_231\jre\lib\rt.jar;E:\NO.Z.80000.Hadoop.spark\SparkBigData\target\classes;C:\Users\Administrator\.m2\repository\org\scala-lang\scala-library\2.12.10\scala-library-2.12.10.jar;C:\Users\Administrator\.m2\repository\org\apache\spark\spark-core_2.12\2.4.5\spark-core_2.12-2.4.5.jar;C:\Users\Administrator\.m2\repository\com\thoughtworks\paranamer\paranamer\2.8\paranamer-2.8.jar;C:\Users\Administrator\.m2\repository\org\apache\avro\avro\1.8.2\avro-1.8.2.jar;C:\Users\Administrator\.m2\repository\org\codehaus\jackson\jackson-core-asl\1.9.13\ja