SparkSQL核心编程

基本介绍

DataFrame 和 DataSet 模型是Spark SQL 所提供的两个编程抽象,SparkSQL核心编程主要是关于使用DataFrame 和 DataSet 模型进行编程以及它们之间的关系和转换。

Spark Core 中,如果想要执行应用程序,需要首先构建上下文环境对象 SparkContext,Spark SQL 其实可以理解为对 Spark Core 的一种封装,不仅仅在模型上进行了封装,上下文环境对象也进行了封装。

在老的版本中,SparkSQL 提供两种 SQL 查询起始点:

  • SQLContext,用于 Spark自己提供的 SQL 查询
  • HiveContext,用于连接 Hive 的查询。

SparkSession 是 Spark 最新的 SQL 查询起始点,实质上是 SQLContext 和 HiveContext的组合,所以在 SQLContex 和 HiveContext 上可用的 API 在 SparkSession 上同样是可以使用的。SparkSession 内部封装了 SparkContext,所以计算实际上是由 sparkContext 完成的。

DataFrame

Spark SQL 的 DataFrame API 允许直接使用 DataFrame 而不用必须去注册临时表或者生成 SQL 表达式。DataFrame API 既有 transformation 操作也有 action 操作。

创建 DataFrame

在 Spark SQL 中 SparkSession 是创建 DataFrame 和执行 SQL 的入口,创建 DataFrame有三种方式:

  • 通过 Spark 的数据源进行创建;
  • 从一个存在的 RDD 进行转换;
  • 从 HiveTable 进行查询返回。

(1)通过 Spark 的数据源进行创建

①进入Spark

[xzc@hadoop102 spark-local]$ bin/spark-shell

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

scala> spark.read.

在这里插入图片描述
③在 spark 的 bin/data 目录中创建 user.json 文件

{
    
    "username": "zhangsan","age":20}
{
    
    "username": "lisi", "age":30}
{
    
    "username": "wangwu", "age":40}

在这里插入图片描述
④读取 json 文件创建 DataFrame

scala> val df = spark.read.json("data/user.json")

在这里插入图片描述
⑤展示结果

scala> df.show

在这里插入图片描述
(2)从RDD转换
在 IDEA 中开发程序时,如果需要 RDD 与 DF 或者 DS 之间互相操作,那么需要引入 以下代码:

import spark.implicits._ 

这里的 spark 不是 Scala 中的包名,而是创建的 sparkSession 对象的变量名称,所以必须先创建 SparkSession 对象再导入。这里的 spark 对象不能使用 var 声明,因为 Scala 只支持val 修饰的对象的引入。 而在spark-shell 中无需导入,自动完成此操作。

①在 spark 的 bin/data 目录中创建id.txt文档
在这里插入图片描述
②读取txt文件

scala> val idRDD = sc.textFile("data/id.txt") 

在这里插入图片描述
③转换为DataFrame并展示结果

scala> idRDD.toDF("id").show 

在这里插入图片描述
注:实际开发中,一般通过样例类将 RDD 转换为 DataFrame

scala> case class User(name:String, age:Int) 
scala> sc.makeRDD(List(("zhangsan",30), ("lisi",40))).map(t=>User(t._1, t._2)).toDF.show 

在这里插入图片描述
(3)从Hive Table查询返回
Apache Hive 是 Hadoop 上的 SQL 引擎,Spark SQL 编译时可以包含 Hive 支持,也可以不包含。包含 Hive 支持的 Spark SQL 可以支持 Hive 表访问、UDF (用户自定义函数)以及 Hive 查询语(HiveQL/HQL)等。需要强调的一点是,如果要在 Spark SQL 中包含Hive 的库,并不需要事先安装 Hive。若要把 Spark SQL 连接到一个部署好的 Hive 上,你必须把 hive-site.xml 复制到 Spark 的配置文件目录中($SPARK_HOME/conf)。即使没有部署好 Hive,Spark SQL 也可以运行。
hive-site.xml文件下载,需要根据自己的配置修改个别内容

注意:如果你没有部署好 Hive,Spark SQL 会在当前的工作目录中创建出自己的 Hive 元数据仓库,叫作metastore_db。此外,如果你尝试使用 HiveQL 中的 CREATE TABLE (并非 CREATE EXTERNAL TABLE)语句来创建表,这些表会被放在你默认的文件系统中的 /user/hive/warehouse 目录中(如果你的 classpath 中有配好的 hdfs-site.xml,默认的文件系统就是 HDFS,否则就是本地文件系统)。
spark-shell 默认是 Hive 支持的;代码中是默认不支持的,需要手动指定(加一个参数即可)。

1)内嵌的 HIVE

如果使用 Spark 内嵌的 Hive, 则什么都不用做, 直接使用即可.
Hive 的元数据存储在 derby 中, 默认仓库地址:$SPARK_HOME/spark-warehouse

①展示tables

scala> spark.sql("show tables").show 

在这里插入图片描述
②创建一个表

scala> spark.sql("create table aa(id int)") 

在这里插入图片描述
在这里插入图片描述
③向表中加载本地数据并展示

scala> spark.sql("load data local inpath 'data/id.txt' into table aa") 
scala> spark.sql("select * from aa").show 

在这里插入图片描述
在这里插入图片描述
注:在实际使用中, 几乎没有任何人会使用内置的 Hive

2)外部的 HIVE

如果想连接外部已经部署好的 Hive,需要通过以下几个步骤:

  • Spark 要接管 Hive 需要把 hive-site.xml 拷贝到 conf/目录下
  • 把 Mysql 的驱动 copy 到 jars/目录下
  • 如果访问不到 hdfs,则需要把 core-site.xml 和 hdfs-site.xml 拷贝到 conf/目录下
  • 重启 spark-shell
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

DataSet

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

创建 DataSet

创建 DataFrame有两种方式:

  • 使用样例类序列创建 DataSet
  • 使用基本类型的序列创建 DataSet

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

①创建Person样例类

scala> case class Person(name: String, age: Long) 

在这里插入图片描述
②向表中添加数据并展示

scala> val caseClassDS = Seq(Person("zhangsan",2)).toDS() 
scala> caseClassDS.show 

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

①创建DataSet

scala> val ds = Seq(1,2,3,4,5).toDS 

在这里插入图片描述
②展示数据

scala> ds.show 

在这里插入图片描述
注:在实际使用的时候,很少用到把序列转换成 DataSet,更多的是通过RDD 来得到 DataSet

RDD 转换为 DataSet

SparkSQL 能够自动将包含有 case 类的 RDD 转换成 DataSet,case 类定义了 table 的结构,case 类属性通过反射变成了表的列名。Case 类可以包含诸如 Seq 或者 Array 等复杂的结构。

scala> case class User(name:String, age:Int) 
scala> sc.makeRDD(List(("zhangsan",30), ("lisi",49))).map(t=>User(t._1, t._2)).toDS 

在这里插入图片描述

DataSet 转换为 RDD

DataSet 其实也是对 RDD 的封装,所以可以直接获取内部的 RDD

scala> case class User(name:String, age:Int) 
scala> sc.makeRDD(List(("zhangsan",30), ("lisi",49))).map(t=>User(t._1, t._2)).toDS 
scala> val rdd = res11.rdd 
scala> rdd.collect 

在这里插入图片描述
在这里插入图片描述

DataFrame 和 DataSet 转换

DataFrame 其实是 DataSet 的特例,所以它们之间是可以互相转换的。

(1)DataFrame 转换为 DataSet

scala> case class User(name:String, age:Int)  
scala> val df = sc.makeRDD(List(("zhangsan",30), ("lisi",49))).toDF("name","age") 
scala> val ds = df.as[User] 

在这里插入图片描述
(2)DataSet 转换为 DataFrame

scala> val ds = df.as[User] 
scala> val df = ds.toDF 

在这里插入图片描述

RDD、DataFrame、DataSet 三者的关系

在 SparkSQL 中 Spark 为我们提供了两个新的抽象,分别是 DataFrame 和 DataSet。他们和 RDD 有什么区别呢?首先从版本的产生上来看:

  • Spark1.0 => RDD
  • Spark1.3 => DataFrame
  • Spark1.6 => Dataset

如果同样的数据都给到这三个数据结构,他们分别计算之后,都会给出相同的结果。不同是的他们的执行效率和执行方式。在后期的 Spark 版本中,DataSet 有可能会逐步取代 RDD和 DataFrame 成为唯一的 API 接口。

三者的共性

(1) RDD、DataFrame、DataSet 全都是 spark 平台下的分布式弹性数据集,为处理超大型数据提供便利;
(2) 三者都有惰性机制,在进行创建、转换,如 map 方法时,不会立即执行,只有在遇到Action 如 foreach 时,三者才会开始遍历运算;
(3) 三者有许多共同的函数,如 filter,排序等;
(4)在对 DataFrame 和 Dataset 进行操作许多操作都需要这个包:import spark.implicits._(在创建好 SparkSession 对象后尽量直接导入)
(5) 三者都会根据 Spark 的内存情况自动缓存运算,这样即使数据量很大,也不用担心会内存溢出
(6) 三者都有 partition 的概念
(7) DataFrame 和 DataSet 均可使用模式匹配获取各个字段的值和类型

三者的区别

(1) RDD

  • RDD 一般和 spark mllib 同时使用
  • RDD 不支持 sparksql 操作

(2) DataFrame

  • 与 RDD 和 Dataset 不同,DataFrame 每一行的类型固定为 Row,每一列的值没法直接访问,只有通过解析才能获取各个字段的值
  • DataFrame 与 DataSet 一般不与 spark mllib 同时使用
  • DataFrame 与 DataSet 均支持 SparkSQL 的操作,比如 select,groupby 之类,还能注册临时表/视窗,进行 sql 语句操作
  • DataFrame 与 DataSet 支持一些特别方便的保存方式,比如保存成 csv,可以带上表头,这样每一列的字段名一目了然(后面专门讲解)

(3)DataSet

  • Dataset 和 DataFrame 拥有完全相同的成员函数,区别只是每一行的数据类型不同。DataFrame 其实就是 DataSet 的一个特例 type DataFrame = Dataset[Row]
  • DataFrame 也可以叫 Dataset[Row],每一行的类型是 Row,不解析,每一行究竟有哪些字段,各个字段又是什么类型都无从得知,只能用上面提到的 getAS 方法或者共性中的第七条提到的模式匹配拿出特定字段。而 Dataset 中,每一行是什么类型是不一定的,在自定义了 case class 之后可以很自由的获得每一行的信息

三者的互相转换

在这里插入图片描述

Guess you like

Origin blog.csdn.net/weixin_44480968/article/details/119940664