第 4 章 SparkSQL数据源

上篇:第 3章 IDEA创建SparkSQL程序


通用加载/保存方法

1、手动指定选项

Spark SQL的DataFrame接口支持多种数据源的操作。一个DataFrame可以进行RDDs方式的操作,也可以被注册为临时表。把DataFrame注册为临时表之后,就可以对该DataFrame执行SQL查询。
Spark SQL的默认数据源为Parquet格式。数据源为Parquet文件时,Spark SQL可以方便的执行所有的操作。修改配置项spark.sql.sources.default,可修改默认数据源格式。

读取

//查看文件格式
scala> spark.read.
csv   format   jdbc   json   load   option   options   orc   parquet   schema   table   text   textFile

//
scala> spark.read.load("file:///usr/local/hadoop/module/datas/2.json")

报错信息:
在这里插入图片描述
查看spark文件信息:
在这里插入图片描述
尝试读取users.parquet这个文件的信息:

scala> spark.read.load("file:///usr/local/hadoop/Spark/spark-2.1.1-bin-hadoop2.7/examples/src/main/resources/users.parquet")
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
res1: org.apache.spark.sql.DataFrame = [name: string, favorite_color: string ... 1 more field]

发现没报错!

展现数据:

scala> spark.read.load("file:///usr/local/hadoop/Spark/spark-2.1.1-bin-hadoop2.7/examples/src/main/resources/users.parquet").show
+------+--------------+----------------+
|  name|favorite_color|favorite_numbers|
+------+--------------+----------------+
|Alyssa|          null|  [3, 9, 15, 20]|
|   Ben|           red|              []|
+------+--------------+----------------+

以上说明,直接读取json文件格式,数据将会报错!

想要读取json格式,正确执行方式:

//通用方式
scala> spark.read.format("json").load("file:///usr/local/hadoop/module/datas/2.json").show
+---+--------+
|age|    name|
+---+--------+
| 20|zhangsan|
| 24|    lisi|
| 27|  wangwu|
+---+--------+

//简化方式
scala> spark.read.json("file:///usr/local/hadoop/module/datas/2.json").show
+---+--------+
|age|    name|
+---+--------+
| 20|zhangsan|
| 24|    lisi|
| 27|  wangwu|
+---+--------+

保存数据

//读取这数据表
scala> val df = spark.read.json("file:///usr/local/hadoop/module/datas/2.json")
df: org.apache.spark.sql.DataFrame = [age: bigint, name: string]

//新创建一个output文件夹,并把刚读取的数据表保存在output文件夹
scala> df.write.save("file:///usr/local/hadoop/module/datas/output")

效果图:
parquet格式的
在这里插入图片描述
若想更换为json,可以这样执行:

scala> df.write.format("json").save("file:///usr/local/hadoop/module/datas/output1")

效果图:
在这里插入图片描述
若文件本身就存在,我们可以使用追加方式保存也行,如:

//追加方式保存
scala> df.write.format("json").mode("append").save("file:///usr/local/hadoop/module/datas/output")

效果图:
在这里插入图片描述

小结:

当数据源格式不是parquet格式文件时,需要手动指定数据源的格式。数据源格式需要指定全名(例如:org.apache.spark.sql.parquet),如果数据源格式为内置格式,则只需要指定简称定json,
parquet, jdbc, orc, libsvm, csv, text来指定数据的格式。
可以通过SparkSession提供的read.load方法用于通用加载数据,使用write和save保存数据

文件保存选项

可以采用SaveMode执行存储操作,SaveMode定义了对数据的处理模式。需要注意的是,这些保存模式不使用任何锁定,不是原子操作。此外,当使用Overwrite方式执行时,在输出新数据之前原数据就已经被删除。SaveMode详细介绍如下表:
在这里插入图片描述


2、JSON文件

Spark SQL 能够自动推测 JSON数据集的结构,并将它加载为一个Dataset[Row]. 可以通过SparkSession.read.json()去加载一个 一个JSON 文件。
注意:这个JSON文件不是一个传统的JSON文件,每一行都得是一个JSON串。


3、Parquet文件

Parquet是一种流行的列式存储格式,可以高效地存储具有嵌套字段的记录。Parquet格式经常在Hadoop生态圈中被使用,它也支持Spark SQL的全部数据类型。Spark SQL 提供了直接读取和存储 Parquet 格式文件的方法。


4、 JDBC

Spark SQL可以通过JDBC从关系型数据库中读取数据的方式创建DataFrame,通过对DataFrame一系列的计算后,还可以将数据再写回关系型数据库中。

注意:需要将相关的数据库驱动放到spark的类路径下

准备工作:(RDD数据库、user数据表)在这里插入图片描述

从Mysql数据库加载数据

在spark的shell命令执行:

(1)从Mysql数据库加载数据方式一

scala> val jdbcDF = spark.read.format("jdbc").option("url", "jdbc:mysql://hadoop105:3306/RDD").option("dbtable", "user").option("user", "root").option("password", "123456").load()

报错信息:
在这里插入图片描述
拷贝mysql驱动jar文件

[root@hadoop105 ~]# cp /usr/local/java/mysql/my-libs/mysql-connector-java-5.1.27/mysql-connector-java-5.1.27-bin.jar /usr/local/hadoop/Spark/spark-2.1.1-bin-hadoop2.7/jars 

拷贝成功,如图所示在这里插入图片描述
由于Spark的配置文件中的ar包发生改变,所以需要重新启动方可生效:

scala> val jdbcDF = spark.read.format("jdbc").option("url", "jdbc:mysql://hadoop105:3306/RDD").option("dbtable", "user").option("user", "root").option("password", "123456").load()
jdbcDF: org.apache.spark.sql.DataFrame = [id: int, name: string ... 1 more field]

//显示数据
scala> jdbcDF.show
+---+--------+---+
| id|    name|age|
+---+--------+---+
|  1|zhangsan| 23|
|  2|    lisi| 25|
|  3|  wangwu| 29|
+---+--------+---+


(2)从Mysql数据库加载数据方式二

scala> val connectionProperties = new java.util. Properties()
connectionProperties: java.util.Properties = {}

scala> connectionProperties.put("user", "root")
res36: Object = null

scala> connectionProperties.put("password", "123456")
res37: Object = null

scala> val jdbcDF2 = spark.read.jdbc("jdbc:mysql://hadoop105:3306/RDD", "user", connectionProperties)
jdbcDF2: org.apache.spark.sql.DataFrame = [id: int, name: string ... 1 more field]


scala> jdbcDF2.show
+---+--------+---+
| id|    name|age|
+---+--------+---+
|  1|zhangsan| 23|
|  2|    lisi| 25|
|  3|  wangwu| 29|
+---+--------+---+

将数据写入Mysql

准备工作:
在这里插入图片描述
(1)执行,将数据写入Mysql方式一

//将数据写入Mysql
scala>  jdbcDF2.write.jdbc("jdbc:mysql://hadoop105:3306/RDD", "user", connectionProperties)

报错信息:
在这里插入图片描述
正确执行:

scala> jdbcDF2.write.mode("append").jdbc("jdbc:mysql://hadoop105:3306/RDD", "user", connectionProperties)

注意:
在这里插入图片描述
在这里插入图片描述
注意:取消id为主键

//读数据
scala> val jdbcDF2 = spark.read.jdbc("jdbc:mysql://hadoop105:3306/RDD", "user", connectionProperties)
jdbcDF2: org.apache.spark.sql.DataFrame = [id: int, name: string ... 1 more field]

//写数据
scala> jdbcDF2.write.mode("append").jdbc("jdbc:mysql://hadoop105:3306/RDD", "user", connectionProperties)

效果图:
在这里插入图片描述


5、Hive数据库

Apache Hive是Hadoop上的SQL引擎,Spark SQL编译时可以包含Hive支持,也可以不包含。包含Hive支持的Spark
SQL可以支持Hive表访问、UDF(用户自定义函数)以及 Hive
查询语言(HiveQL/HQL)等。需要强调的一点是,如果要在Spark
SQL中包含Hive的库,并不需要事先安装Hive。一般来说,最好还是在编译Spark
SQL时引入Hive支持,这样就可以使用这些特性了。如果你下载的是二进制版本的 Spark,它应该已经在编译时添加了 Hive 支持。

若要把Spark SQL连接到一个部署好的Hive上,你必须把hive-site.xml复制到
Spark的配置文件目录中($SPARK_HOME/conf)。即使没有部署好Hive,Spark SQL也可以运行。
需要注意的是,如果你没有部署好Hive,Spark SQL会在当前的工作目录中创建出自己的Hive 元数据仓库,叫作
metastore_db。此外,如果你尝试使用 HiveQL 中的 CREATE TABLE (并非 CREATE EXTERNAL
TABLE)语句来创建表,这些表会被放在你默认的文件系统中的 /user/hive/warehouse 目录中(如果你的 classpath
中有配好的 hdfs-site.xml,默认的文件系统就是 HDFS,否则就是本地文件系统)。

操作:

(1)内嵌Hive应用

//查看jdbcDF2数据结构:DataFrame
scala> jdbcDF2
res55: org.apache.spark.sql.DataFrame = [id: int, name: string ... 1 more field]

//创建临时表:users
scala> jdbcDF2.createTempView("users")
//显示
scala> spark.sql("show tables").show
+--------+---------+-----------+
|database|tableName|isTemporary|
+--------+---------+-----------+
|        |    users|       true|
+--------+---------+-----------+

查看文件:
在这里插入图片描述
我们可以尝试创建表:

//创建一张xxx表
scala> spark.sql("create table xxx(id int)")
20/02/11 12:41:45 WARN HiveMetaStore: Location: file:/usr/local/hadoop/Spark/spark-2.1.1-bin-hadoop2.7/bin/spark-warehouse/xxx specified for non-external table:xxx
res58: org.apache.spark.sql.DataFrame = []

//显示数据表
scala> spark.sql("show tables").show
+--------+---------+-----------+
|database|tableName|isTemporary|
+--------+---------+-----------+
| default|      xxx|      false|
|        |    users|       true|
+--------+---------+-----------+

在这里插入图片描述
我们尝试xxx表读取、写数据:

//找到student.txt文件路径读取这张表的数据,然后写到“xxx”表上
scala> spark.sql("load data local inpath '/usr/local/hadoop/module/datas/id.txt' into table xxx")
res62: org.apache.spark.sql.DataFrame = []


//显示数据
scala> spark.sql("select * from xxx").show
+---+
| id|
+---+
|  1|
|  2|
|  3|
+---+

效果图:
在这里插入图片描述
注意:如果你使用的是内部的Hive,在Spark2.0之后,spark.sql.warehouse.dir用于指定数据仓库的地址,如果你需要是用HDFS作为路径,那么需要将core-site.xml和hdfs-site.xml 加入到Spark conf目录,否则只会创建master节点上的warehouse目录,查询时会出现文件找不到的问题,这是需要使用HDFS,则需要将metastore删除,重启集群

(2)外部Hive应用

  1. 将Hive中的hive-site.xml拷贝或者软连接到Spark安装目录下的conf目录下。
    在这里插入图片描述
  2. 打开spark shell,注意带上访问Hive元数据库的JDBC客户端
[root@hadoop105 bin]# ./spark-shell 

在这里插入图片描述
3) 方式一,执行语句:

//外部表关联
scala> spark.sql("show tables").show
+--------+---------+-----------+
|database|tableName|isTemporary|
+--------+---------+-----------+
| default|  student|      false|
+--------+---------+-----------+


方式二

Spark SQL CLI可以很方便的在本地运行Hive元数据服务以及从命令行执行查询任务。在Spark目录下执行如下命令启动Spark
SQL CLI:

执行语句:

scala> [root@hadoop105 bin]# ./spark-sql 

20/02/11 13:10:46 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
20/02/11 13:10:59 WARN ObjectStore: Version information not found in metastore. hive.metastore.schema.verification is not enabled so recording the schema version 1.2.0
20/02/11 13:10:59 WARN ObjectStore: Failed to get database default, returning NoSuchObjectException
20/02/11 13:11:15 WARN ObjectStore: Failed to get database global_temp, returning NoSuchObjectException

spark-sql (default)> 

spark-sql (default)> show tables;
database	tableName	isTemporary
default	student	false
Time taken: 6.127 seconds, Fetched 1 row(s)


6、代码中使用Hive

(1)添加依赖:

<!-- https://mvnrepository.com/artifact/org.apache.spark/spark-hive -->
<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-hive_2.11</artifactId>
    <version>2.1.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.hive/hive-exec -->
<dependency>
    <groupId>org.apache.hive</groupId>
    <artifactId>hive-exec</artifactId>
    <version>1.2.1</version>
</dependency>

(2)创建SparkSession时需要添加hive支持(红色部分)

//使用内置Hive需要指定一个Hive仓库地址,若使用的是外部Hive,则需要将hive-site.xml添加到ClassPath下。
val warehouseLocation: String = new File("spark-warehouse").getAbsolutePath

val spark = SparkSession
.builder()
.appName("Spark Hive Example")
//使用内置Hive需要指定一个Hive仓库地址
.config("spark.sql.warehouse.dir", warehouseLocation)
.enableHiveSupport()
.getOrCreate()
发布了159 篇原创文章 · 获赞 19 · 访问量 9069

猜你喜欢

转载自blog.csdn.net/weixin_39868387/article/details/104253658