第 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()
發佈了182 篇原創文章 · 獲贊 20 · 訪問量 9659
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章