一、SparkSQL简介
SparkSQL,就是Spark生态体系中的构建在SparkCore基础之上的一个基于SQL的计算模块。SparkSQL的前身不叫SparkSQL,而叫Shark,最开始的时候底层代码优化,sql的解析、执行引擎等等完全基于Hive,总之Shark的执行速度要比hive高出一个数量级,但是hive的发展制约了Shark,所以在15年中旬的时候,shark负责人,将shark项目结束掉,重新独立出来的一个项目,就是sparksql,不再依赖hive,做了独立的发展,逐渐的形成两条互相独立的业务:SparkSQL和Hive-On-Spark。在SparkSQL发展过程中,同时也吸收了Shark有些的特点:基于内存的列存储,动态字节码优化技术。
二、SparkSQL特点
1、强大的整合能力
可以在spark程序中混合SQL查询操作
2、统一的数据访问接口
使得sparksql可以非常便捷的进行数据访问操作
3、可以读写hive中的数据
对于hive的强大支持,是sparksql重要的能力之一
4、提供了支持JDBC/ODBC
为了方便一些BI组件的调用数据,使得对数据访问变得多元化,功能完整化
总结:
SparkSQL就是Spark生态体系中用于处理结构化数据的一个模块。换句话说,SparkSQL处理的就是二维表数据。
①结构化数据是什么?存储在关系型数据库中的数据,就是结构化数据;
②半结构化数据是什么?类似xml、json等的格式的数据被称之为半结构化数据;
③非结构化数据是什么?音频、视频、图片等为非结构化数据。
三、SparkSQL编程入口和模型
1、SparkSQL编程入口
在SparkSQL中的编程模型,不再是SparkContext,但是创建需要依赖SparkContext。SparkSQL中的编程模型,在spark2.0以前的版本中为SQLContext和HiveContext,HiveContext是SQLContext的一个子类,提供Hive中特有的一些功能,比如row_number开窗函数等等,这是SQLContext所不具备的,在Spark2.0之后将这两个进行了合并——SparkSession。使用工厂构建器(Builder方式)模式创建SparkSession。
//创建sparkSql程序入口
val spark = SparkSession.builder()
.appName("sparksql")
.master("local[*]")
.enableHiveSupport()//开启hive支持,支持hive的相关操作
.getOrCreate()
//通过sparkSql程序入口调用SparkContext
val sc = spark.sparkContext
//设置日志级别
sc.setLogLevel("WARN")
2、SparkSQL编程模型
主要通过两种方式操作SparkSQL,一种就是SQL,另一种为DataFrame和Dataset。
people.json数据:
{“name”:“json”,“age”:23,“hobby”:“running”}
{“name”:“charles”,“age”:32,“hobby”:“basketball”}
{“name”:“tom”,“age”:28,“hobby”:“football”}
{“name”:“lili”,“age”:24,“hobby”:“running”}
{“name”:“bob”,“age”:20,“hobby”:“swimming”}
1、SQL
就和Hive操作一样,但是需要清楚一点的是,SQL操作的是表,所以要想用SQL进行操作,就需要将SparkSQL对应的编程模型转化成为一张表才可以。同时支持,通用sql和hivesql。
//SQL风格
//加载数据
val dataFrame = spark.read.json("F:\\test\\people.json")
//想要使用SQL风格,必须将数据首先注册为一张表
dataFrame.createOrReplaceTempView("person")
//查询所有数据
spark.sql("select * from person").show()
//查询age和name,并将age+10岁
spark.sql("select name,age+10 as age from person").show()
//查询name和age,只要age>30的
val sql=
"""
|select * from person where age>30
""".stripMargin
spark.sql(sql).show()
2、DSL(DataFrame&DataSet)
为方便大家使用函数式编程的思想,类似sparkcore的编程模式,sparksql也支持DSL(Domain Specified Language,领域专用语言,或者特定领域语言),即通过DataFrame和Dataset来支持类似RDD的编程。
DataFrame和Dataset是SparkSQL中的编程模型。DataFrame和Dataset我们都可以理解为是一张mysql中的二维表,表有什么?表头,表名,字段,字段类型。RDD其实说白了也是一张二维表,但是这张二维表相比较于DataFrame和Dataset却少了很多东西,比如表头,表名,字段,字段类型,只有数据。
一般的,将RDD称之为Spark体系中的第一代编程模型;DataFrame比RDD多了一个Schema元数据信息,被称之为Spark体系中的第二代编程模型;Dataset吸收了RDD的优点(强类型推断和强大的函数式编程)和DataFrame中的优化(SQL优化引擎,内存列存储),成为Spark的最新一代的编程模型。
//DSL风格(领域专用语言),就是通过dataFrame和Dataset来支持类似RDD的编程,调用函数
//加载数据
val dataFrame = spark.read.json("F:\\test\\people.json")
//查询name,hobby
dataFrame.select("name","hobby").show()
//需要导包
import spark.implicits._
//查询name和age,只要age>30岁的人
dataFrame.select("name","age").filter($"age">30).show()
//查询age,并将每个age+10岁
dataFrame.select($"age",$"age"+10 as "age1").show()
3、RDD V.S DataFrame V.S Dataset
1、RDD
弹性分布式数据集,是Spark对数据进行的一种抽象,可以理解为Spark对数据的一种组织方式,更简单些说,RDD就是一种数据结构,里面包含了数据和操作数据的方法。
RDD是Spark最底层的抽象,目前是开发者用的最多的,但逐步会转向DataFrame和Dataset(当然,这是Spark的发展趋势)调整。
2、DataFrame
DataFrame在RDD的基础上加了Schema(描述数据的信息,可以认为是元数据,DataFrame曾经就有个名字叫SchemaRDD)
假设RDD中的两行数据长这样
那么DataFrame中的数据长这样
DataFrame比RDD多了一个表头信息(Schema),像一张表了,DataFrame还配套了新的操作数据的方法,DataFrame API(如df.select())和SQL(select id, name from xx_table where …)。
通过DataFrame API或SQL处理数据,会自动经过Spark 优化器(Catalyst)的优化,即使你写的程序或SQL不高效,也可以运行的很快。
3、Dataset
Dataset提供了强类型支持,也是在RDD的每行数据加了类型约束
假设RDD中的两行数据长这样
那么Dataset中的数据长这样
或者也可以是这样,其中每行数据是个Object
相比DataFrame,Dataset提供了编译时类型检查,对于分布式程序来讲,提交一次作业太费劲了(要编译、打包、上传、运行),到提交到集群运行时才发现错误,实在是不方便,这也是引入Dataset的一个重要原因。