文章目录
- 前言
- 一、Spark SQL概述
- 1.1 Spark是什么
- 1.2 Spark SQL优势
- 1.3Spark SQL数据抽象
- 1.4RDD,DataFame,Dataset区别和共性
- 二,Spark SQL原理
- 2.1SparkSession
- 2.3三者的转换
- 2.4SparkSQL中的join
- 2.5 SQL解析过程
前言
Spark SQL自从面世以来不仅接过了shark的接力棒,为spark用户提供高性能的SQL on hadoop的解决方案,还为spark带来了通用的高效的,多元一体的结构化的数据处理能力。
提示:以下是本篇文章正文内容,下面案例可供参考
一、Spark SQL概述
1.1 Spark是什么
Spark SQL是Spark用来处理结构化数据的一个模块。
1.2 Spark SQL优势
(1)读更少的数据(SparkSQL的表数据在内存中存储不使用原生态的JVM对象存储方式,而是采用内存列存储)
(2)提供更好的性能(字节码生成技术、SQL优化)
1.3Spark SQL数据抽象
1.DataFrame
DataFrame的前身是SchemaRDD。Spark1.3更名为DataFrame。不继承RDD,自己实现了RDD的大部分功能,与RDD类似。
DataFrame也是一个分布式数据集:
DataFrame可以看做分布式 Row 对象的集合,提供了由列组成的详细模式信息,使其可以得到优化。
DataFrame 不仅有比RDD更多的算子,还可以进行执行计划的优化DataFrame更像传统数据库的二维表格,除了数据以外,还记录数据的结构信息,即schema
DataFrame也支持嵌套数据类型(struct、array和map)
DataFrame API提供的是一套高层的关系操作,比函数式的RDD API要更加友好,门槛更低Dataframe的劣势在于在编译期缺少类型安全检查,导致运行时出错。
2.DataSet
DataSet是在Spark1.6中添加的新的接口;与RDD相比,保存了更多的描述信息,概念上等同于关系型数据库中的二维表;与DataFrame相比,保存了类型信息,是强类型的,提供了编译时类型检查。DataSet包含了DataFrame的功能,在Spark2.0中两者得到了统一:DataFrame表示为DataSet[Row],即DataSet的子集。
3.Row & Schema
DataFrame = RDD[Row] + Schema;DataFrame 的前身是 SchemaRDD
Row是一个泛化的无类型 JVM object
schema是DataFame中的数据结构信息,包含哪些列,每列的名称和类型各
1.4RDD,DataFame,Dataset区别和共性
1.区别
DataFrame(DataFrame = RDD[Row] + Schema):
与RDD和Dataset不同,DataFrame每一行的类型固定为Row,只有通过解析才能获取各个字段的值
Dataset(Dataset = RDD[case class].toDS):
Dataset和DataFrame拥有完全相同的成员函数,区别只是每一行的数据类型不同,Dataset每一行的类型都是一个case class,在自定义了case class之后可以很自由的获得每一行的信息。
对DataFrame和Dataset进行操作许多操作都需要这个包进行支持,import spark.implicits._
2.共性
1、RDD、DataFrame、Dataset都是 Spark 平台下的分布式弹性数据集,为处理海量数据提供便利
2、三者都有许多相同的概念,如分区、持久化、容错等;有许多共同的函数,如map、filter,sortBy等
3、三者都有惰性机制,只有在遇到 Action 算子时,才会开始真正的计算
二,Spark SQL原理
2.1SparkSession
在 Spark 2.0 之前:
SQLContext 是创建 DataFrame 和执行 SQL 的入口HiveContext通过Hive sql语句操作Hive数据,兼Hhive操作,HiveContext继承自SQLContext。
在 Spark 2.0 之后:将这些入口点统一到了SparkSession,SparkSession 封装了 SqlContext 及 HiveContext;实现了 SQLContext 及 HiveContext 所有功能。
2.3三者的转换
2.4SparkSQL中的join
数据分析中将两个数据集进行 Join 操作是很常见的场景,在 Spark 的物理计划阶段,Spark 的 Join Selection 类会根据 Join hints 策略、Join 表的大小、 Join 是等值 Join 还是不等值以及参与 Join 的 key 是否可以排序等条件来选择最终的 Join 策略,最后 Spark 会利用选择好的 Join 策略执行最终的计算。
当前 Spark 一共支持五种 Join 策略:
1.Broadcast hash join (BHJ)
Broadcast Hash Join 的实现是将小表的数据广播到 Spark 所有的 Executor 端,这个广播过程和我们自己去广播数据没什么区别:
(1)利用 collect 算子将小表的数据从 Executor 端拉到 Driver 端
(2)在 Driver 端调用 sparkContext.broadcast 广播到所有 Executor 端
(3)在 Executor 端使用广播的数据与大表进行 Join 操作(实际上是执行map操作)
总结:这种 Join 策略避免了 Shuffle 操作。一般而言,Broadcast Hash Join 会比其他 Join 策略执行的要快,只能用于等值 Join,不要求参与 Join 的 keys 可排序.
2.Shuffle hash join(SHJ)
当表中的数据比较大,又不适合使用广播,这个时候就可以考虑使用 Shuffle Hash Join。Shuffle Hash Join 同样是在大表和小表进行 Join 的时候选择的一种策略。它的计算思想是:把大表和小表按照相同的分区算法和分区数进行分区(根据参与 Join 的 keys 进行分区),这样就保证了 hash 值一样的数据都分发到同一个分区中,然后在同一个 Executor 中两张表 hash 值一样的分区就可以在本地进行 hash Join 了
总结:仅支持等值 Join,不要求参与 Join 的 Keys 可排序,对表的大小有限制。
3.Shuffle sort merge join (SMJ)
前面两种 Join 策略对表的大小都有条件的,如果参与 Join 的表都很大,这时候就得考虑用 Shuffle Sort Merge Join了。
Shuffle Sort Merge Join 的实现思想:
将两张表按照 join key 进行shuffle,保证join key值相同的记录会被分在相应的分区对每个分区内的数据进行排序排序后再对相应的分区内的记录进行连接。
总结:无论分区有多大,Sort Merge Join都不用把一侧的数据全部加载到内存中,而是即用即丢.仅支持等值 Join,并且要求参与 Join 的 Keys 可排序
4.Cartesian product join
如果 Spark 中两张参与 Join 的表没指定连接条件,那么会产生 Cartesian product join,这个 Join 得到的结果就是两张表行数的乘积。
5.Broadcast nested loop join (BNLJ)
在某些情况会对某张表重复扫描多次,效率非常低下,这种join 会根据相关条件对小表进行广播,以减少表的扫描次数。
**总结:**支持等值和不等值 Join,支持所有的 Join 类型。
2.5 SQL解析过程
Spark SQL对SQL语句的处理和关系型数据库类似,即词法/语法解析、绑定、优化、执行。Spark SQL会先将SQL语句解析成一棵树,然后使用规则(Rule)对Tree进行绑定、优化等处理过程。
1.Spark SQL由Core、Catalyst、Hive、Hive-ThriftServer四部分构成:
Core: 负责处理数据的输入和输出,如获取数据,查询结果输出成DataFrame等
Catalyst: 负责处理整个查询过程,包括解析、绑定、优化等
Hive: 负责对Hive数据进行处理
Hive-ThriftServer: 主要用于对Hive的访问.
Spark SQL的代码复杂度是问题的本质复杂度带来的,Spark SQL中的 Catalyst 框架大部分逻辑是在一个 Tree 类型的数据结构上做各种折腾.
2.执行过程
queryExecution 就是整个执行计划的执行引擎,里面有执行过程中各个中间过程变量,整个执行流程如下:
(1).SQL 语句经过 Parser 解析后就会变成一个抽象语法树(AST).operator 组成的抽象语法树是整个 Catatyst 优化的基础,Catatyst 优化器会在这个树上面进行各种折腾,把树上面的节点挪来挪去来进行优化.
(2).经过 Parser 有了抽象语法树,但是并不知道 score,sum 这些东西是啥,所以就需要 analyer 来定位。analyzer 会把 AST 上所有 Unresolved 的东西都转变为 resolved 状态,SparkSQL 有很多resolve 规则:ResolverRelations:解析表(列)的基本类型等信息
ResolveFuncions:解析出来函数的基本信息
ResolveReferences:解析引用,通常是解析列名
(3)接下来要进行逻辑优化,主要的优化有:谓词下推(Push Down Predicate)、常量折叠(Constant Folding)、字段裁剪(ColumningPruning)。()(4).做完逻辑优化,还需要先转换为物理执行计划,将逻辑上可行的执行计划变为 Spark 可以真正执行的计划,数据在一个一个的 plan 中流转,然后每个 plan 里面表达式都会对数据进行处理,就相当于经过了一个个小函数的调用处理,这里面有大量的函数调用开销。