
Spark SQL
一、Spark SQL概述
Spark SQL是Spark用来处理结构化数据的一个模块,它提供了2个编程抽象:DataFrame和DataSet,并且作为分布式SQL查询引擎的作用。
我们已经学习了Hive,它是将Hive SQL转换成MapReduce然后提交到集群上执行,大大简化了编写MapReduc的程序的复杂性,由于MapReduce这种计算模型执行效率比较慢。所有Spark SQL应运而生,它是将Spark SQL转换成RDD,然后提交到集群执行,执行效率非常快!
1.什么是DataFrame
与RDD类似,DataFrame也是一个分布式数据容器。然而DataFrame更像传统数据库的二维表格,除了数据以外,还记录数据的结构信息,即schema。从API易用性的角度上看,DataFrame API提供的是一套高层的关系操作,比函数式的RDD API要更加友好,门槛更低。

上图直观地体现了DataFrame和RDD的区别。左侧的RDD[Person]虽然以Person为类型参数,但Spark框架本身不了解Person类的内部结构。而右侧的DataFrame却提供了详细的结构信息,使得Spark SQL可以清楚地知道该数据集中包含哪些列,每列的名称和类型各是什么。DataFrame是为数据提供了Schema的视图。可以把它当做数据库中的一张表来对待,DataFrame也是懒执行的。性能上比RDD要高,主要原因:优化的执行计划:查询计划通过Spark catalyst optimiser进行优化。

2.什么是DataSet
1)是Dataframe API的一个扩展,是Spark最新的数据抽象。
2)用户友好的API风格,既具有类型安全检查也具有Dataframe的查询优化特性。
3)样例类被用来在Dataset中定义数据的结构信息,样例类中每个属性的名称直接映射到DataSet中的字段名称。
4) Dataframe是Dataset的特列,DataFrame=Dataset[Row] ,所以可以通过as方法将Dataframe转换为Dataset。Row是一个类型,跟Car、Person这些的类型一样,所有的表结构信息我都用Row来表示。
5)DataSet是强类型的。比如可以有DataSet[Car],DataSet[Person].
6)DataFrame只是知道字段,但是不知道字段的类型,所以在执行这些操作的时候是没办法在编译的时候检查是否类型失败的,比如你可以对一个String进行减法操作,在执行的时候才报错,而DataSet不仅仅知道字段,而且知道字段类型,所以有更严格的错误检查。就跟JSON对象和类对象之间的类比。
二、Spark SQL编程
- 添加依赖
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.11</artifactId>
<version>2.4.3</version>
</dependency>
1.DataFrame
1.1 创建DataFrame
- 创建a.json
{
"name":"zhangsan","age":20}
{
"name":"李四","age":22}
{
"name":"wanguw","age":24}
- 读取上边创建的文件,创建DataFrame对象
val spark: SparkSession =
SparkSession.builder()
.appName("ceshi")
.master("local[*]")
.getOrCreate()
val df: DataFrame = spark.read.json("F:\\datas\\a.json")
df.show()
spark.stop()
- 展示结果
+---+--------+
|age| name|
+---+--------+
| 20|zhangsan|
| 22| 李四|
| 24| wanguw|
+---+--------+
1.2 SQL风格语法 [重点]
需求:读取json文件创建DataFrame,建立临时表,通过SQL语句查询数据
val df: DataFrame = spark.read.json("F:\\datas\\a.json")
df.createOrReplaceTempView("t_user")
val sqlDF: DataFrame = spark.sql("select * from t_user")
sqlDF.show()
展示结果
+---+--------+
|age| name|
+---+--------+
| 20|zhangsan|
| 22| 李四|
| 24| wanguw|
+---+--------+
1.3 DSL风格语法
需求:读取json文件创建DataFrame,通过DSL方法查询
import spark.implicits._
val df = spark.read.json("F:\\datas\\a.json")
df.printSchema() //打印Schema结构
//指定列查询
df.select($"name",$"age").show()
//查询大于20岁的
df.filter($"age">20).show()
//根据年龄分组,统计个数
df.groupBy("age").count().show()
1.4 RDD转换为DataFrame
注意:如果需要RDD与DF或者DS之间操作,那么都需要引入 import spark.implicits._
- 创建a.txt
zhangsan 20
lisi 20
wangwu 23
zhaoliu 45
- 读取上边创建的文件,创建RDD后,转换为DataFrame对象
import spark.implicits._ //这是一行代码,做隐式转换 spark是上边定义的变量
val rdd1: RDD[String] = spark.sparkContext.textFile("F:\\datas\\a.txt")
val df: DataFrame = rdd1.map(v => {
val p: Array[String] = v.split("\t")
(p(0), p(1))
}).toDF("name", "age")
df.show()
1.5 DataFrame转换为RDD
val df = spark.read.json("F:\\datas\\a.json")
val rdd: RDD[Row] = df.rdd
rdd.collect().foreach(v=>println(v))
2.DataSet
Dataset是具有强类型的数据集合,需要提供对应的类型信息。
2.1 创建DataSet
- 定义case class
case class Person(name:String,age:Long)
- 创建List集合,转换为DataSet对象
import spark.implicits._
val ds: Dataset[Person] = List(Person("zhangsan",20),Person("lisi",22)).toDS()
ds.show()
2.2 RDD转换为DataSet
import spark.implicits._
val rdd1: RDD[String] = spark.sparkContext.textFile("F:\\datas\\a.txt")
rdd1.map(v=>{
val arr: Array[String

Spark SQL是Spark用于结构化数据处理的模块,提供DataFrame和DataSet两种编程抽象。DataFrame是带Schema的分布式数据集,类似于数据库表格,具有优化的执行计划。DataSet是DataFrame的扩展,具备类型安全和查询优化特性。本文详细介绍了DataFrame和DataSet的创建、转换、互操作,以及如何使用SQL和DSL进行查询,包括从RDD转换、自定义函数、数据加载与保存,并通过实际练习加深对Spark SQL的理解。
最低0.47元/天 解锁文章
115

被折叠的 条评论
为什么被折叠?



