SparkSQL總結:
一、Spark SQL
是Spark用來處理結構化數據的一個模塊,它提供了一個編程抽象叫做DataFrame,並且作爲分佈式SQL查詢引擎的作用
二、什麼是DataFrames??
與RDD類似,DataFrames也是一個分佈式數據容器;然而DataFrame更像傳統數據庫的二維表格,除了數據以外,還記錄數據的結構信息,即schema;
同時與Hive類似,DataFrame也支持嵌套數據類型(struct,array,map).
三、創建dataframe的兩種方式:
通過數據源採集直接創建成DF格式(spark.read.json(Path))
通過StructType創建Schema,通過createDataFrame來創建DF
DataFrame與DataSet與RDD互相轉換
(1)DataFrame -> DataSet
val dataSet = dataFrame.as[Person]
(2)DataSet -> DataFrame
val dataFraem = dataSet.toDF()
(3)DataFrame -> RDD
val RDD = dataFrame.rdd
四、DataFrame兩種風格語法常用操作
1、DSL(領域特定語言)風格操作
略
2、SQL風格操作
DataFrame的一個強大之處就是我們可以將它看作是一個關係型數據表,然後可以通過在程序中使用spark.sql() 來執行SQL語句查詢,結果返回一個DataFrame:
spark.sql(“SQL語句”).show
如果想使用SQL風格的語法,需要將DataFrame註冊成表:
personDF.registerTempTable(“t_person”)
五、DataSet和DataFrame的區別
1、DataSet包含了DataFrame的功能,Spark2.0中兩者統一,DataFrame表示爲DataSet[Row],即DataSet的子集。
2、相比DataFrame,Dataset提供了編譯時類型檢查,對於分佈式程序來講,提交一次作業太費勁了(要編譯、打包、上傳、運行),
到提交到集羣運行時才發現錯誤,這會浪費大量的時間,這也是引入Dataset的一個重要原因。
3、DS狀態的RDD[Person]雖然以Person爲類型參數,但Spark框架本身不瞭解 Person類的內部結構。
而DataFrame卻提供了詳細的結構信息,使得Spark SQL可以清楚地知道該數據集中包含哪些列,每列的名稱和類型各是什麼,DataFrame多了數據的結構信息,
即schema。這樣看起來就像一張表了。
4、DataFrame通過引入schema和off-heap(不在堆裏面的內存,指的是除了不在堆的內存,使用操作系統上的內存),解決了RDD的缺點,
Spark通過schame就能夠讀懂數據, 因此在通信和IO時就只需要序列化和反序列化數據, 而結構的部分就可以省略了;通過off-heap引入,
可以快速的操作數據,避免大量的GC。但是卻丟了RDD的優點,DataFrame不是類型安全的, API也不是面向對象風格的
5、off-heap
DataFrame還引入了off-heap,意味着JVM堆以外的內存, 這些內存直接受操作系統管理(而不是JVM)。Spark能夠以二進制的形式序列化數據(不包
括結構)到off-heap中, 當要操作數據時, 就直接操作off-heap內存. 由於Spark理解schema, 所以知道該如何操作。
六、SparkSQL實現的WordCount
import org.apache.spark.sql.{Dataset, SparkSession}
/**
* @description ${DESCRIPTION}
* @author YDAlex
* @data 2019/11/20.
* @version 1.0
*/
object wc {
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder()
.appName("wordCount")
.master("local[*]")
.getOrCreate()
val words = spark.read
.textFile("G:\\IntelliJ IDEA 2019.2.1\\Workspace\\sparkStreaming\\data\\wc.txt")
import spark.implicits._
val word: Dataset[String] = words.flatMap(_.split(" "))
//SQL style
word.createOrReplaceTempView("word")//創建臨時表
/*SELECT value, COUNT(*) counts FROM word GROUP BY value ORDER BY counts DESC*/
val result = spark.sql(
"""
|select
|value,
|count(*) counts
|from word
|group by value
|order by counts desc
|""".stripMargin)
result.show()
//DSLStyle
import org.apache.spark.sql.functions._
word.groupBy($"value" as "word")
.agg(count("*") as "counts")
.orderBy($"counts" desc)
.show()
spark.close()
}
}