Spark系列文章目录

第一章 初识Spark
第二章 Spark-Core核心模型(一)
第二章 Spark-Core核心模型(二)
第三章 Spark-Core编程进阶(一)
第三章 Spark-Core编程进阶(二)
第四章 Spark-SQL基础(一)
第四章 Spark-SQL基础(二)
第五章 Spark-SQL进阶(一)
第五章 Spark-SQL进阶(二)
第五章 Spark-SQL进阶(三)



文章目录

  • Spark系列文章目录
  • 第四章 Spark-SQL基础(一)
  • 1.认识Spark-SQL
  • 2.Spark-SQL历程
  • 2.1Hive
  • 2.2 Shark
  • 3.Spark-SQL优点
  • 4.Spark-SQL架构
  • 4.1基础架构
  • 4.2执行流程
  • 4.3Catalyst 执行优化器
  • 4.4优化策略
  • 5.分布式SQL引擎
  • 5.1运行Spark SQL CLI
  • 5.2运行Thrift JDBC/ODBC Server
  • 6.编程流程
  • 7.Spark-SQL案例



第四章 Spark-SQL基础(一)

1.认识Spark-SQL

Spark SQL是Spark中处理结构化数据的模块。提供了一种新的编程抽象DataFrame/Dataset,并且可以充当分布式SQL查询引擎。

  • 集成:无缝地将SQL查询集成到Spark程序中。
  • 统一数据访问:使用统一的方式连接到常见数据源。
  • Hive兼容:通过配置可以直接兼容Hive,运行查询Hive数据。
  • 标准的连接:通过JDBC、ODBC连接。Spark SQL包括具有行业标准JDBC和ODBC连接的服务器模式。

spark的缺陷 spark优点_大数据

2.Spark-SQL历程

2.1Hive

Hive是基于Hadoop的一个数据仓库工具

  • 可以将结构化的数据文件映射为一张数据库表;
  • 可以提供简单的SQL查询功能;
  • 可以将SQL语句转换为MapReduce任务并行运算;

Hive计算引擎依赖于MapReduce框架

  • 随着时代的发展,对数据提取转化加载(ETL)需求越来越大;
  • 因此开发一个更加高效的SQL-on-Hadoop工具更加的迫切;

2.2 Shark

Shark便是其中之一

  • 修改了Hive中内存管理、物理计划、执行这三个模块,运行在Spark引擎上,使得SQL查询的速度得到10-100倍的提升。

随着Spark的发展

  • Shark对于Hive的太多依赖
  • 制约了Spark各个组件的相互集成
  • 所以提出了SparkSQL项目
  • 2014年宣布:停止开发Shark,至此Shark的发展画上了句号
  • SparkSQL作为Spark生态的一员继续发展
  • 不再受限于Hive
  • 只是兼容Hive

Hive on Spark是Hive的发展计划

  • 该计划将Spark作为Hive的底层引擎之一
  • 也就是说,Hive将不再受限于一个引擎
  • 可以采用Map-Reduce、Spark等引擎

Shark的出现,使得SQL-on-Hadoop的性能比Hive有了10-100倍的提高。

spark的缺陷 spark优点_spark_02

摆脱了Hive的限制,SparkSQL的性与Shark对比,也有很大的提升。

spark的缺陷 spark优点_spark的缺陷_03

为什么SparkSQL的性能会得到怎么大的提升呢?

3.Spark-SQL优点

SparkSQL主要是在以下三点做了优化(主要是与Spark核心对比):

  • 内存列存储(In-Memory Columnar Storage)
  • 采用了内存列存储之后,减少了对内存的消耗,减少JVM的GC性能开销。
  • 字节码生成技术(bytecode generation,即CG)
  • Spark SQL在其catalyst模块的expressions中增加了codegen模块
  • 对于SQL语句中的计算表达式
  • 比如select num + num from t这种的sql,就可以使用动态字节码生成技术来优化其性能。
  • Scala代码优化
  • 使用Scala编写的代码,对可能造成较大性能开销的代码,Spark SQL底层会使用更加复杂的方式进行重写,来获取更好的性能。
  • 比如Option样例类、for循环、map/filter/foreach等高阶函数,以及不可变对象,都改成了用null、while循环等来实现,并且重用可变的对象。

SparkSQL的表数据在内存中存储不是采用原生态的JVM对象存储方式,而是采用内存列存储,如下图所示。

spark的缺陷 spark优点_spark的缺陷_04

4.Spark-SQL架构

4.1基础架构

SparkSQL语句由三部分组成

  • Projection(a1,a2,a3)
  • Data Source(tableA)
  • Filter(condition)

分别对应SQL查询过程中的Result、Data Source、Operation。

  • SQL语句按Result–>Data Source–>Operation的次序描述。

4.2执行流程

当执行SQL语句的顺序为:

  1. 对读入的SQL语句进行解析(Parse)
  1. 分辨出SQL语句中哪些词是关键词(如SELECT、FROM、WHERE);
  2. 哪些是表达式;
  3. 哪些是Projection;
  4. 哪些是Data Source等;
  5. 从而判断SQL语句是否规范;
  1. 将SQL语句和数据库的数据字典(列、表、视图等等)进行绑定(Bind)。
  1. 如果相关的Projection、Data Source等都是存在的话,就表示这个SQL语句是可以执行的。
  1. 一般的数据库会提供几个执行计划,这些计划一般都有运行统计数据,数据库会在这些计划中选择一个最优计划(Optimize)。
  2. 计划执行(Execute),按Operation–>Data Source–>Result的次序来进行。
  1. 在执行过程有时候甚至不需要读取物理表就可以返回结果。
  2. 比如重新运行刚运行过的SQL语句,可能直接从数据库的缓冲池中获取返回结果。

4.3Catalyst 执行优化器

Catalyst 是 Spark SQL 执行优化器的代号,所有 Spark SQL 语句最终都能通过它来解析、优化,最终生成可以执行的 Java 字节码。

Catalyst 最主要的数据结构是树,所有 SQL 语句都会用树结构来存储,树中的每个节点有一个类(class),以及 0 或多个子节点。Scala 中定义的新的节点类型都是 TreeNode 这个类的子类。

Catalyst 另外一个重要的概念是规则。基本上,所有优化都是基于规则的。可以用规则对树进行操作,树中的节点是只读的,所以树也是只读的。规则中定义的函数可能实现从一棵树转换成一颗新树。

整个 Catalyst 的执行过程可以分为以下 4 个阶段:

  1. 分析阶段,分析逻辑树,解决引用;
  2. 逻辑优化阶段;
  3. 物理计划阶段,Catalyst 会生成多个计划,并基于成本进行对比;
  4. 代码生成阶段;
  5. spark的缺陷 spark优点_mapreduce_05

4.4优化策略

  • RBO(Rule-based optimization)基于规则的优化
  • 优化思路主要是减少参与计算的数据量以及计算本身的代价。
  • CBO 基于代价优化策略
  • 它充分考虑了数据本身的特点(如大小、分布)以及操作算子的特点(中间结果集的分布及大小)及代价,从而更好的选择执行代价最小的物理执行计划,即 SparkPlan。

Spark 以 DAG 的方法执行上述 Physical Plan。

在执行 DAG 的过程中,Adaptive Execution 根据运行时信息动态调整执行计划从而提高执行效率。

5.分布式SQL引擎

5.1运行Spark SQL CLI

Spark SQL CLI是一种在本地模式下运行Hive metastore的便捷工具。

注意,Spark SQL CLI无法与Thrift JDBC服务器通信。

启动Spark SQL CLI

  • ./bin/spark-sql

操作如下图所示:

spark的缺陷 spark优点_spark_06

5.2运行Thrift JDBC/ODBC Server

  • 启动Thrift JDBC/ODBC服务
  • ./sbin/start-thriftserver.sh
  • 默认情况下,服务器监听 localhost:10000。可以通过任一环境变量重写该行为,即:
    export HIVE_SERVER2_THRIFT_PORT=<listening-port>export HIVE_SERVER2_THRIFT_BIND_HOST=<listening-host>
  • 使用beeline测试Thrift JDBC/ODBC服务器:
  • ./bin/beeline
  • 连接到JDBC/ODBC服务器:beeline> !connect jdbc:hive2://localhost:10000
  • beeline会询问你的用户名和密码。在非安全模式下,只需在机器上输入用户名和空白密码即可。
  • 注意:如果遇到SQL查询结果中文显示乱码的问题,可以通过修改系统编码的方式解决,比如数据库是UTF-8编码,在启动beeline之前:LANG=zh_CN.UTF-8;./bin/beeline
  • !exit退出beeline终端

启动Thrift JDBC/ODBC服务,操作如下图所示:

spark的缺陷 spark优点_spark的缺陷_07

使用beeline测试Thrift JDBC/ODBC服务器,操作如下图所示:

spark的缺陷 spark优点_mapreduce_08

注意,用户名是在hive-site.xml中配置的,密码为任意即可。

6.编程流程

SparkSQL编程流程如下图所示:

spark的缺陷 spark优点_编程语言_09

7.Spark-SQL案例

添加依赖:

<!--Spark SQL-->
<dependency>
  <groupId>org.apache.spark</groupId>
  <artifactId>spark-sql_${spark.scala.version}</artifactId>
  <version>${spark.version}</version>
</dependency>

编码如下:

package com.briup.sql

import org.apache.spark.SparkConf
import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession}

case class User(name:String,age:Int)
object SparkSqlFirst {
  def main(args: Array[String]): Unit = {

    //1.获取SparkSession对象
    val spark=SparkSession.builder()
        .master("local[*]")
        .appName("spark_sql")
        .getOrCreate();
    
    //2.导入隐式支持
    //会隐式将RDD对象转化为DataFarame/Dataset对象
    import  spark.implicits._;
	
    //3.读取json数据源获取Dataset对象
   	val rowDS: Dataset[Row] =spark.read.json("spark/src/data/resources/people.json");
		//将Row对象转化为User对象
    val userDS: Dataset[User] =dataset.as[User];
		
    //4.输出到控制台
    userDS.show()
    rowDS.show();
    
		//5.关闭会话对象
    spark.close();
  }
}