sparksql
1、课程目标
- 1、掌握sparksql原理
- 2、掌握DataFrame和DataSet数据结构和使用方式
- 3、掌握通过sparksql来开发简单的应用程序
2、sparksql概述
2.1 sparksql前世今生
- spark是专门为spark设计的大规模数据仓库系统
- spark需要依赖于hive的代码,同时也依赖于spark的版本
- 随着数据处理的复杂度越来越高,并且性能也要求很高
- 发现之前hivesql底层运行mapreduce代码这种思想限制了shark的发展
- 最后就把shark这个框架废弃了,把工作的重点转移到sparksql
2.2 sparksql是什么
-
Spark SQL is Apache Spark’s module for working with structured data
-
sparksql是spark的一个用来处理结构化数据的模块
-
它提供了一个编程抽象叫做DataFrame并且作为分布式SQL查询引擎的作用。
3、sparksql特性
- 1、易整合
- 可以使用sparksql与spark应用程序进行混合使用
- 同时也可以使用不同的语言进行代码开发
- java
- scala
- python
- R
- 2、统一的数据源访问
- sparksql可以使用一种相同的方式来访问外部的数据源
- SparkSession.read.文件格式方法(该格式的文件路径)
- sparksql可以使用一种相同的方式来访问外部的数据源
- 3、兼容hive
- sparksql可以支持hivesql的语法,使用sparksql来操作hivesql
- 4、支持行业标准的数据库连接
- sparksql支持jdbc或者是odbc来连接上数据库
4、DataFrame
4.1 dataFrame是什么
dataFrame它的前身是schmeRDD,schemaRDD是直接继承自RDD,在spark1.3.0之后把schemaRDD改为DataFrame,它不在直接继承自RDD,而是自己实现了RDD的一些方法。
在Spark中,DataFrame是一种以RDD为基础的分布式数据集,类似于传统数据库的二维表格,DataFrame带有Schema元信息,即DataFrame所表示的二维表数据集的每一列都带有名称和类型,但底层做了更多的优化
4.2 RDD与DataFrame优缺点对比
-
RDD
- 优点
- 1、编译时类型安全
- 通过RDD开发程序,在编译的时候会进行类型检查
- 2、具有面向对象编程的风格
- 1、编译时类型安全
- 缺点
- 1、序列化和反序列化性能开销很大
- 数据在跨进程进行网络传输的时候,需要先把数据内容本身和数据的结构信息进行序列化,后期通过反序列化来恢复得到该对象。
- 2、构建大量的对象会带来频繁的GC
- 对象的创建一般是使用heap堆中的内存去存储,如果内存空间不足需要进行gc,把一些不是进行使用的对象清除掉,来腾出更多的内存空间。不断进行gc的后果导致线程任务不断的暂停,任务执行的效率是比较低。
- 1、序列化和反序列化性能开销很大
- 优点
-
dataFrame
-
dataFrame它引入了schema和off-heap概念
-
优点
-
1、dataFrame由于引入了schema(数据的结构信息–元数据信息),这个时候数据在进行网络传输的时候只需要序列化数据本身就可以了,对于数据的结构信息可以省略掉。它是解决了rdd序列化和反序列化性能开销很大这个缺点
-
2、dataFrame由于引入了off-heap(直接使用操作系统层面上的内存,不在使用堆中的内存)
- 这里大量的对象创建就不在heap堆中,直接使用操作系统层面上的内存,后期就可以保证堆中空间是比较充足,就不会导致频繁的gc。它是解决了RDD构建大量的对象会带来频繁的GC
-
-
缺点
- dataFrame引入了schema和off-heap分别解决了rdd的缺点,同时它丢失了rdd的优点。
- 1、编译时类型不安全
- 2、不具备面向对象编程的风格
- dataFrame引入了schema和off-heap分别解决了rdd的缺点,同时它丢失了rdd的优点。
-
5、DataSet
5.1 dataSet是什么
DataSet是分布式的数据集合,Dataset提供了强类型支持,也是在RDD的每行数据加了类型约束。DataSet是在Spark1.6中添加的新的接口。
5.2 dataFrame和dataSet互相转换
- 1、dataFrame转换成dataSet
- val ds=df.as[强类型]
- val ds=df.as[String]
- 2、dataSet转换成dataFrame
- val df=ds.toDF
- 补充:
- 可以把dataFrame和dataSet调用rdd这个方法,获取得到一个rdd。
5.3 创建DataSet
-
1、通过sparkSession调用方法createDataset构建
val ds=spark.createDataset(List(1,2,3,4)) val ds=spark.createDataset(sc.textFile("/person.txt"))
-
2、通过一个rdd转换生成一个dataSet
val ds=sc.textFile("/person.txt").toDS
-
3、通过一个dataFrame转换生成一个dataSet
val ds=df.as[类型]
-
4、通过一个已经存在dataSet转换生成一个新的dataSet
ds.map(x=>x+" beijing").show
6、基于IDEA开发代码将rdd转换成dataFrame
-
1、引入依赖
<dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-sql_2.11</artifactId> <version>2.1.3</version> </dependency>
6.1 利用反射机制
- 1、代码开发
package cn.itcast.sparksql
import org.apache.spark.SparkContext
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.{Column, DataFrame, SparkSession}
//todo:实现将rdd转换成dataFrame,利用了反射机制(定义一个样例类)
case class Person(id:Int,name:String,age:Int)
object CaseClassSchema {
def main(args: Array[String]): Unit = {
//1、创建SparkSession
val spark: SparkSession = SparkSession.builder().appName("CaseClassSchema").master("local[2]").getOrCreate()
//2、创建SparkContext
val sc: SparkContext = spark.sparkContext
sc.setLogLevel("warn")
//3、读取数据文件
val rdd1: RDD[Array[String]] = sc.textFile("E:\\person.txt").map(_.split(" "))
//4、将rdd1与样例类进行关联
val personRDD: RDD[Person] = rdd1.map(x=>Person(x(0).toInt,x(1),x(2).toInt))
//5、将RDD转换成dataFrame
//手动导入隐式转换
import spark.implicits._
val personDF: DataFrame = personRDD.toDF
//6、操作
//-------------------DSL风格语法-----------------start
//打印schema
personDF.printSchema()
//展示数据,默认展示前20条数据
personDF.show() //name:zhangsanxxxxxxxxxxxxxxxxxxxxxxxx
//展示第一个数据
println(personDF.first())
personDF.head(3).foreach(println)
//获取name字段对应的数据
personDF.select("name").show()
personDF.select($"name").show()
personDF.select(new Column("name")).show()
//查询多个字段的结果数据
personDF.select("name","id","age").show()
//实现age+1操作
personDF.select($"age"+1).show()
//过滤出年龄大于30的用户信息
personDF.filter($"age" >30).show()
println(personDF.filter($"age" >30).count())
//按照年龄进行分组统计
personDF.groupBy("age").count().show()
//-------------------DSL风格语法-----------------end
//-------------------SQL风格语法-----------------start
personDF.createTempView("person")
spark.sql("select * from person").show()
spark.sql("select * from person where age >30").show()
spark.sql("select * from person where id=6").show()
spark.sql("select count(*) from person group by age ").show()
//-------------------SQL风格语法-----------------end
sc.stop()
spark.stop()
}
}