Spark之【SparkSQL編程】系列(No1)——《SparkSession與DataFrame》

        上一篇博客已經爲大家介紹完了SparkSQL的基本概念以及其提供的兩個編程抽象:DataFrame和DataSet,本篇博客,博主要爲大家介紹的是關於SparkSQL編程的內容。考慮到內容比較繁瑣,故分成了一個系列博客。本篇作爲該系列的第一篇博客,爲大家介紹的是SparkSession與DataFrame

        碼字不易,先贊後看,養成習慣!
在這裏插入圖片描述


        

SparkSQL編程

1. SparkSession

        在老的版本中,SparkSQL提供兩種SQL查詢起始點:一個叫SQLContext,用於Spark自己提供的SQL查詢;一個叫HiveContext,用於連接Hive的查詢。

        SparkSession是Spark最新的SQL查詢起始點,實質上是SQLContext和HiveContext的組合,所以在SQLContext和HiveContext上可用的API在SparkSession上同樣是可以使用的。SparkSession內部封裝了sparkContext,所以計算實際上是由sparkContext完成的。

2. DataFrame

2.1 創建

        在Spark SQL中SparkSession是創建DataFrame和執行SQL的入口,創建DataFrame有三種方式:通過Spark的數據源進行創建;從一個存在的RDD進行轉換;還可以從Hive Table進行查詢返回。

在正式開始之前,我們需要準備數據源。
vim /opt/data/people.json

{"name":"Michael"}
{"name":"Andy", "age":30}
{"name":"Justin", "age":19}

將其上傳到集羣上。
hadoop fs -put /opt/data/people.json /input

ok~

        
1) 從Spark數據源進行創建

(1) 查看Spark數據源進行創建的文件格式,
spark.read.按tab鍵表示顯示:

scala> spark.read.
csv   format   jdbc   json   load   option   options   orc   parquet   schema   table   text   textFile

(2)讀取json文件創建DataFrame

注意:spark.read.load默認獲取parquet格式文件

scala> val df = spark.read.json("/input/people.json")
df: org.apache.spark.sql.DataFrame = [age: bigint, name: string]

(3)展示結果

scala> df.show
+----+-------+
| age|   name|
+----+-------+
|null|Michael|
|  30|   Andy|
|  19| Justin|
+----+-------+

2)從RDD中轉換

參照第2.5節的內容:DateFrame 轉換爲RDD

3) 從Hive Table進行查詢返回

這個將在後面的博文中涉及到,這裏暫且不談。

2.2 SQL風格語法 (主要)

1)創建一個DataFrame

scala> val df = spark.read.json("/input/people.json")
df: org.apache.spark.sql.DataFrame = [age: bigint, name: string]

2)對DataFrame創建一個臨時表

scala> df.createOrReplaceTempView("people")

3)通過SQL語句實現查詢全表

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

4)結果展示

scala> sqlDF.show
+----+-------+
| age|   name|
+----+-------+
|null|Michael|
|  30|   Andy|
|  19| Justin|
+----+-------+

        注意:臨時表是Session範圍的,Session退出後,表就失效了。如果想應用範圍內仍有效,可以使用全局表。注意使用全局表時需要全路徑訪問,如:global_temp:people。

全局的臨時視圖存在於系統數據庫 global_temp中,我們必須加上庫名去引用它

5)對於DataFrame創建一個全局表

scala> df.createGlobalTempView("people")

6)通過SQL語句實現查詢全表

scala> spark.sql("select * from global_temp.people").show()
+----+-------+
| age|   name|
+----+-------+
|null|Michael|
|  30|   Andy|
|  19| Justin|
+----+-------+

3. DSL 風格語法 (次要)

1)創建一個DataFrame

scala> val df = spark.read.json("/input/people.json")
df: org.apache.spark.sql.DataFrame = [age: bigint, name: string]

2)查看DataFrame的Schema信息

scala> df.printSchema
root
 |-- age: long (nullable = true)
 |-- name: string (nullable = true)

3)只查看"name"列數據

scala> df.select("name").show()
+-------+
|   name|
+-------+
|Michael|
|   Andy|
| Justin|
+-------+

4)查看"name"列數據以及"age+1"數據

scala> df.select($"name", $"age" + 1).show()
+-------+---------+
|   name|(age + 1)|
+-------+---------+
|Michael|     null|
|   Andy|       31|
| Justin|       20|
+-------+---------+

5)查看"age"大於"21"的數據

scala> df.filter($"age" > 21).show()
+---+----+
|age|name|
+---+----+
| 30|Andy|
+---+----+

6)按照"age"分組,查看數據條數

scala> df.groupBy("age").count().show()
+----+-----+
| age|count|
+----+-----+
|  19|     1|
|null|     1|
|  30|     1|
+----+-----+

2.4 RDD轉換爲DateFrame

注意:如果需要RDD與DF或者DS之間操作,那麼都需要引入 import spark.implicits._【spark不是包名,而是sparkSession對象的名稱】

準備工作:

數據文件people.txt
vim /opt/data/people.txt
zhangsan,17
lisi,20,
wangwu,19

上傳至hdfs集羣
hdfs dfs -put /opt/data/people.txt /input

前置條件: 導入隱式轉換並創建一個RDD

scala> import spark.implicits._
import spark.implicits._

scala> val peopleRDD = sc.textFile("/input/people.txt")
peopleRDD: org.apache.spark.rdd.RDD[String] = examples/src/main/resources/people.txt MapPartitionsRDD[3] at textFile at <console>:27

1)通過手動確定轉換

scala> peopleRDD.map{x=>val para = x.split(",");(para(0),para(1).trim.toInt)}.toDF("name","age")
res1: org.apache.spark.sql.DataFrame = [name: string, age: int]

2)通過反射確定(需要用到樣例類)

<1>創建一個樣例類

scala> case class People(name:String, age:Int)

<2>根據樣例類將RDD轉換爲DataFrame

scala> peopleRDD.map{ x => val para = x.split(",");People(para(0),para(1).trim.toInt)}.toDF
res2: org.apache.spark.sql.DataFrame = [name: string, age: int]

3)通過編程的方式(瞭解)

<1>導入所需的類型

scala> import org.apache.spark.sql.types._
import org.apache.spark.sql.types._

<2>創建Schema

scala> val structType: StructType = StructType(StructField("name", StringType) :: StructField("age", IntegerType) :: Nil)
structType: org.apache.spark.sql.types.StructType = StructType(StructField(name,StringType,true), StructField(age,IntegerType,true))

<3>導入所需的類型

scala> import org.apache.spark.sql.Row
import org.apache.spark.sql.Row

<4>根據給定的類型創建二元組RDD

scala> val data = peopleRDD.map{ x => val para = x.split(",");Row(para(0),para(1).trim.toInt)}
data: org.apache.spark.rdd.RDD[org.apache.spark.sql.Row] = MapPartitionsRDD[6] at map at <console>:33

<5>根據數據及給定的schema創建DataFrame

scala> val dataFrame = spark.createDataFrame(data, structType)
dataFrame: org.apache.spark.sql.DataFrame = [name: string, age: int]

2.5 DateFrame 轉換爲RDD

直接調用rdd即可。

1) 創建一個DataFrame

scala> val df = spark.read.json("/input/people.json")
df: org.apache.spark.sql.DataFrame = [age: bigint, name: string]

2)將DataFrame轉換爲RDD

scala> val dfToRDD = df.rdd
dfToRDD: org.apache.spark.rdd.RDD[org.apache.spark.sql.Row] = MapPartitionsRDD[19] at rdd at <console>:29

3)打印RDD

scala> dfToRDD.collect
res13: Array[org.apache.spark.sql.Row] = Array([Michael, 29], [Andy, 30], [Justin, 19])

        好了,本次的分享就到這裏。下一篇博客將爲大家帶來DataSet的內容,敬請期待!!!

        
        
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章