簡介
spark SQL部分,DF是很重要的一個操作單位。
DataFrame是組織成命名列的數據集。它在概念上等同於關係數據庫中的表,但在底層具有更豐富的優化。DataFrames可以從各種來源構建:
- 結構化數據文件
- hive中的表
- 外部數據庫或現有RDDs
DataFrame和RDD區別
總的來說,DataFrame多了數據的結構信息,也就是schema,可以理解爲每一個表的元數據或者說表結構信息。
他大體上就是這樣一個關係:
DF= RDD + schema
優點:
DataFrame是分佈式的Row對象的集合。DataFrame除了提供了比RDD更豐富的算子以外,更重要的特點是提升執行效率、減少數據讀取以及執行計劃的優化。
Datasets : DF之上的更高級抽象
Datasets是在Spark1.6中添加的一個新的接口。
首先Datasets提供了RDD的優點,強類型化,使用了lambda等等。
並且Datasets可以從JVM對象進行構造,兼容性更好,並且可以使用map等函數去操作。
DataFrames
總的來說有兩種方法來創建DataFrames
(*)Case Class
- 定義case class,
也就相當於schema,其中規定了表結構信息。
case class students(sid:String, sname:String, classNum:Int, comm:String)
非常簡單和淺顯吧。
- 讀取數據(RDD)
有了schema我們需要將數據也就是RDD對應到表結構中。
val data = sc.textFile("hdfs://myComputer:9000/braylon/test.csv").map(_.split(","))
val df = data.map(x => students(x(0).trim(),x(1).trim(),x(2).toInt,x(3).trim()))
其中比較重要的就是數據類型的轉換,String的話就可以不用轉換,但是對於Int的話就需要toInt變化。
- RDD -> DF
我們上面得到的就是df,但是其實df仍然是一個RDD。這不是我們想要的DF。所以還需要一個轉換。
val df2DF = df.toDF
//然後就可以查詢和操作了,sparkSQL也就可以使用了
df2DF.show
(*)SparkSession創建DF
第二種方法是使用SparkSession
SparkSession
SparkSession是Apache Spark 2.x引入的,提供了一個統一的切入點來使用Spark的各項功能,並且提供DataFrame和DataSet相關的API操作。簡化了用戶操作Spark的監護流程。
比如對於1.x,我們需要建立SparkConf和SparkContext,SparkSession就簡化了,不需要顯示創建這兩個對象,因爲他們封裝在了SparkSession中。
(*)
創建StructType,定義Schema結構信息。
val schema = StructType(List(StructField("sid", DataTypes.StringType),
StructField("sname", DataTypes.StringType),
StructField("classNum", DataTypes.IntegerType),
StructField("comm", DataTypes.StringType)))
import org.apache.spark.sql.types._
val data = sc.textFile("hdfs://ip:9000/braylon/test.csv").map(_.split(","))
val df_ = data.map(x => Row(x(0),x(1),x(2).Int,x(3)))
//import org.apache.spark.sql.Row
val DF = spark.createDataFrame(df_,schema)
(*) Json文件創建DF
val df = spark.read.json("json文件")
DataFrame中使用SQL語句
- 創建視圖
df.createOrReplaceTempView("students_tmp")
- 查詢
spark.sql("select * from students_tmp").show
視圖
上面使用的是一個在Session生命週期中的臨時views。在Spark SQL中,如果擁有一個臨時的view,並想在不同的Session中共享,而且在application的運行週期內可用,那麼就需要創建一個全局的臨時view。並記得使用的時候加上global_temp作爲前綴來引用它,因爲全局的臨時view是綁定到系統保留的數據庫global_temp上。
① 創建一個普通的view和一個全局的view
df.createOrReplaceTempView("tableView1")
df.createGlobalTempView("tableView2")
② 在當前會話中執行查詢,均可查詢出結果。
spark.sql("select * from tableView1").show
spark.sql("select * from global_temp.tableView2").show
③ 開啓一個新的會話,執行同樣的查詢
spark.newSession.sql("select * from tableView1").show (ERROR)
spark.newSession.sql("select * from global_temp.tableView2").show
大家共~~