[大数据]Spark(3)SparkSQL(1)

1. SparkSQL概述1.1 SparkSQLSpark SQL是Spark用于结构化数据(structured data)处理的Spark模块。与基本的Spark RDD API不同,Spark SQL的抽象数据类型为Spark提供了关于数据结构和正在执行的计算的更多信息。在内部,Spark SQL使用这些额外的信息去做一些额外的优化,有多种方式与Spark SQL进行交互,比如: SQL和DatasetAPI。当计算结果的时候,使用的是相同的执行引擎,不依赖你正在使用哪种API或者语言。这
摘要由CSDN通过智能技术生成

1. SparkSQL概述

1.1 SparkSQL

Spark SQL是Spark用于结构化数据(structured data)处理的Spark模块。
与基本的Spark RDD API不同,Spark SQL的抽象数据类型为Spark提供了关于数据结构和正在执行的计算的更多信息。
在内部,Spark SQL使用这些额外的信息去做一些额外的优化,有多种方式与Spark SQL进行交互,比如: SQL和DatasetAPI。
当计算结果的时候,使用的是相同的执行引擎,不依赖你正在使用哪种API或者语言。这种统一也就意味着开发者可以很容易在不同的API之间进行切换,这些API提供了最自然的方式来表达给定的转换。
我们已经学习了Hive,它是将Hive SQL转换成 MapReduce然后提交到集群上执行,大大简化了编写 MapReduce的程序的复杂性,由于MapReduce这种计算模型执行效率比较慢。所以Spark SQL的应运而生,它是将Spark SQL转换成RDD,然后提交到集群执行,执行效率非常快!
Spark SQL它提供了2个编程抽象,类似Spark Core中的RDD
DataFrame
DataSet

1.2 SparkSQL特点

1.2.1 易整合

无缝的整合了 SQL 查询和 Spark 编程
在这里插入图片描述

1.2.2 统一的数据访问方式

使用相同的方式连接不同的数据源
在这里插入图片描述

1.2.3 兼容Hive

在这里插入图片描述

1.2.4 标准的数据连接

通过 JDBC 或者 ODBC 来连接
在这里插入图片描述

1.3 什么是DataFrame

在Spark中,DataFrame是一种以RDD为基础的分布式数据集,类似于传统数据库中的二维表格。DataFrame与RDD的主要区别在于,前者带有schema元信息,即DataFrame所表示的二维表数据集的每一列都带有名称和类型。这使得Spark SQL得以洞察更多的结构信息,从而对藏于DataFrame背后的数据源以及作用于DataFrame之上的变换进行了针对性的优化,最终达到大幅提升运行时效率的目标。反观RDD,由于无从得知所存数据元素的具体内部结构,Spark Core只能在stage层面进行简单、通用的流水线优化。
同时,与Hive类似,DataFrame也支持嵌套数据类型(struct、array和map)。从 API 易用性的角度上看,DataFrame API提供的是一套高层的关系操作,比函数式的RDD API 要更加友好,门槛更低。

在这里插入图片描述
上图直观地体现了DataFrame和RDD的区别。
左侧的RDD[Person]虽然以Person为类型参数,但Spark框架本身不了解Person类的内部结构。而右侧的DataFrame却提供了详细的结构信息,使得 Spark SQL 可以清楚地知道该数据集中包含哪些列,每列的名称和类型各是什么。
DataFrame是为数据提供了Schema的视图。可以把它当做数据库中的一张表来对待
DataFrame也是懒执行的,但性能上比RDD要高,主要原因:优化的执行计划,即查询计划通过Spark catalyst optimiser进行优化。比如下面一个例子:
在这里插入图片描述
为了说明查询优化,我们来看上图展示的人口数据分析的示例。图中构造了两个DataFrame,将它们join之后又做了一次filter操作。
如果原封不动地执行这个执行计划,最终的执行效率是不高的。因为join是一个代价较大的操作,也可能会产生一个较大的数据集。如果我们能将filter下推到 join下方,先对DataFrame进行过滤,再join过滤后的较小的结果集,便可以有效缩短执行时间。而Spark SQL的查询优化器正是这样做的。简而言之,逻辑查询计划优化就是一个利用基于关系代数的等价变换,将高成本的操作替换为低成本操作的过程。
在这里插入图片描述

1.4 什么是DataSet

DataSet是分布式数据集合。DataSet是Spark 1.6中添加的一个新抽象,是DataFrame的一个扩展。它提供了RDD的优势(强类型,使用强大的lambda函数的能力)以及Spark SQL优化执行引擎的优点。DataSet也可以使用功能性的转换(操作map,flatMap,filter等等)。
是DataFrame API的一个扩展,是SparkSQL最新的数据抽象
用户友好的API风格,既具有类型安全检查也具有DataFrame的查询优化特性;
用样例类来定义DataSet中数据的结构信息,样例类中每个属性的名称直接映射到DataSet中的字段名称;
DataSet是强类型的。比如可以有DataSet[Car],DataSet[Person]。
DataFrame是DataSet的特列,DataFrame=DataSet[Row] ,所以可以通过as方法将DataFrame转换为DataSet。Row是一个类型,跟Car、Person这些的类型一样,所有的表结构信息都用Row来表示。
在这里插入图片描述

2.SparkSQL编程

2.1 SparkSession新的起始点

在老的版本中,SparkSQL提供两种SQL查询起始点:一个叫SQLContext,用于Spark自己提供的SQL查询;一个叫HiveContext,用于连接Hive的查询。
SparkSession是Spark最新的SQL查询起始点,实质上是SQLContext和HiveContext的组合,所以在SQLContex和HiveContext上可用的API在SparkSession上同样是可以使用的。SparkSession内部封装了sparkContext,所以计算实际上是由sparkContext完成的。当我们使用 spark-shell 的时候, spark 会自动的创建一个叫做spark的SparkSession, 就像我们以前可以自动获取到一个sc来表示SparkContext。
在这里插入图片描述

2.2 DataFrame

Spark SQL的DataFrame API 允许我们使用 DataFrame 而不用必须去注册临时表或者生成SQL表达式。DataFrame API 既有transformation操作也有action操作,DataFrame的转换从本质上来说更具有关系, 而 DataSet API 提供了更加函数式的 API。

2.2.1 创建DataFrame

在Spark SQL中SparkSession是创建DataFrame和执行SQL的入口,创建DataFrame有三种方式:通过Spark的数据源进行创建;从一个存在的RDD进行转换;还可以从Hive Table进行查询返回。

Spark支持创建文件的数据源格式:
在这里插入图片描述

2.2.2 SQL风格语法、

1)创建一个DataFrame

var df = spark.read.json("/opt/module/spark-local/people.json")
df.show()

在这里插入图片描述
2)对DataFrame创建一个临时表

df.createOrReplaceTempView("people")

3)通过SQL语句实现查询全表

scala> var sqlDF = spark.sql("SELECT * FROM people")
sqlDF: org.apache.spark.sql.DataFrame = [age: bigint, name: string]
sqlDF.show

在这里插入图片描述

2.2.3 DSL风格语法

DataFrame提供一个特定领域语言(domain-specific language, DSL)去管理结构化的数据,可以在 Scala, Java, Python 和 R 中使用 DSL,使用 DSL 语法风格不必去创建临时视图了。
1)创建DataFrame

val df = spark.read.json("/opt/module/spark-local /people.json")

2)查看DataFrame的Schema信息
在这里插入图片描述
3)只查看"name"列数据

df.select("name").show()

在这里插入图片描述
4)查看所有列

df.select("*").show

在这里插入图片描述
5)查看name类以及age+1的数据

df.select($"name",$"age" + 1).show

在这里插入图片描述
6)查看age大于19的数据

df.filter($"age">19).show

在这里插入图片描述
7)按照”age”分组,查看数据条数

df.groupBy("age").count.show

在这里插入图片描述

2.2.4 RDD转换为DataFrame

注意:如果需要RDD与DF或者DS之间操作,那么都需要引入 import spark.implicits._ (spark不是包名,而是sparkSession对象的名称,所以必须先创建SparkSession对象再导入. implicits是一个内部object)

数据准备:

在/opt/module/spark-local/目录下准备people.txt

qiaofeng,18
xuzhu,19
duanyu,20 

创建RDD

peopleRDD.map{
   
    str=>{
   
        var fields = str.split(",");
        (fields(0),fields(1).toInt)
    }
}.toDF("name","age").show

1)手动确定转换

peopleRDD.map{
   
    str=>{
   
        var fields = str.split(",");
        (fields(0),fields(1).toInt)
    }
}.toDF("name","age").show

在这里插入图片描述
2)通过样例类反射转换(常用)

创建一个样例类:

case class People(name:String,age:Int)
peopleRDD.map{
   x=> var fields=x.split(",");People(fields(0),fields(1).toInt)}.toDF.show

输出同上

2.2.5 DataFrame转换为RDD

1)创建一个DataFrame

df = spark.read.json("/opt/module/spark-local/people.json")

2)将DataFrame转换为RDD

val dfToRDD = df.rdd

3)打印RDD

dfToRDD.collect

输出:

res2: Array[org.apache.spark.sql.Row] = Array([30,qiaofeng], [20,xuzhu], [10,duanyu])

2.3 DataSet

DataSet是具有强类型的数据集合,需要提供对应的类型信息。

2.3.1 创建DataSet

1)使用样例类序列创建DataSet

case class Person(name: String, age: Long)
val caseClassDS = Seq(Person("wangyuyan",2)).toDS()
caseClassDS.show

在这里插入图片描述
2)使用基本类型的序列创建DataSet

val ds = Seq(1,2,3,4,5,6<
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值