RDD、DataFrame、DataSet 三者的關係
➢ Spark1.0 => RDD
➢ Spark1.3 => DataFrame
➢ Spark1.6 => Dataset
如果同樣的數據都給到這三個數據結構,他們分別計算之後,都會給出相同的結果。不同是的他們的執行效率和執行方式。在後期的 Spark版本DataSet 有可能會逐步取代RDD和DataFrame 成爲唯一的API 接口。
三者的共性
➢ RDD、DataFrame、DataSet 全都是 spark 平臺下的分佈式彈性數據集,爲處理超大型數據提供便利;
➢ 三者都有惰性機制,在進行創建、轉換,如map 方法時,不會立即執行,只有在遇到Action 如 foreach 時,三者纔會開始遍歷運算;
➢ 三者有許多共同的函數,如 filter,排序等;
➢ 在對DataFrame 和Dataset 進行操作許多操作都需要這個包:import spark.implicits._(在創建好 SparkSession 對象後儘量直接導入)
➢ 三者都會根據 Spark 的內存情況自動緩存運算,這樣即使數據量很大,也不用擔心會內存溢出
➢ 三者都有 partition 的概念
➢ DataFrame 和DataSet 均可使用模式匹配獲取各個字段的值和類型
三者的區別
RDD
➢ RDD一般和 spark mllib 同時使用
➢ RDD不支持 sparksql 操作
DataFrame
➢ 與RDD和Dataset 不同,DataFrame 每一行的類型固定爲Row,每一列的值沒法直接訪問,只有通過解析才能獲取各個字段的值
➢ DataFrame 與DataSet 一般不與 spark mllib 同時使用
➢ DataFrame 與DataSet 均支持 SparkSQL 的操作,比如 select,groupby 之類,還能註冊臨時表/視窗,進行 sql 語句操作
➢ DataFrame 與DataSet 支持一些特別方便的保存方式,比如保存成 csv,可以帶上表頭,這樣每一列的字段名一目瞭然
DataSet
➢ Dataset 和DataFrame 擁有完全相同的成員函數,區別只是每一行的數據類型不同。DataFrame 其實就是DataSet 的一個特例 typeDataFrame = Dataset[Row]
➢ DataFrame 也可以叫Dataset[Row],每一行的類型是Row,不解析,每一行究竟有哪些字段,各個字段又是什麼類型都無從得知,只能用上面提到的 getAS 方法或者共性中的第七條提到的模式匹配拿出特定字段。而Dataset 中,每一行是什麼類型是不一定的,在自定義了case class 之後可以很自由的獲得每一行的信息
RDD、DataFrame、DataSet 三者的轉換
DataFrame與DataSet轉換
package sparkSQL.study
import org.apache.spark.SparkConf
import org.apache.spark.sql.{
Dataset, SparkSession}
object DF_DS {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setAppName("DataFrame_DateSet...").setMaster("local[*]")
val sparkSession = SparkSession.builder().config(conf).getOrCreate()
import sparkSession.implicits._
// TODO DataFrame <==> DataSet
val rdd = sparkSession.sparkContext.makeRDD(List(("zahngsan", 18), ("lisi", 20)))
val dataFrame = rdd.toDF("name", "age")
dataFrame.show()
val ds = dataFrame.as[UserDF_DS]
ds.show()
val dataFrame1 = ds.toDF()
dataFrame1.show()
sparkSession.stop()
}
case class UserDF_DS( name:String, age:Int)
}
DataFrame與RDD轉換
package sparkSQL.study
import org.apache.spark.SparkConf
import org.apache.spark.sql.SparkSession
object DF_RDD {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setAppName("DataFrame_RDD...").setMaster("local[*]")
val sparkSession = SparkSession.builder().config(conf).getOrCreate()
import sparkSession.implicits._
// TODO DataFrame <==> RDD
val rdd = sparkSession.sparkContext.makeRDD(List(("zahngsan", 18), ("lisi", 20)))
val dataFrame = rdd.toDF("name", "age")
dataFrame.show()
val rdd1 = dataFrame.rdd
rdd1.collect().foreach(println)
sparkSession.stop()
}
}
RDD與DataSet轉換
package sparkSQL.study
import org.apache.spark.SparkConf
import org.apache.spark.sql.SparkSession
object RDD_DS {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setAppName("DataSet_RDD...").setMaster("local[*]")
val sparkSession = SparkSession.builder().config(conf).getOrCreate()
import sparkSession.implicits._
// TODO RDD <==> DataSet
val rdd = sparkSession.sparkContext.makeRDD(List(("zahngsan", 18), ("lisi", 20)))
val ds = rdd.map {
case (name, age) => {
UserRDD_DS(name, age)
}
}.toDS()
ds.show()
val rdd1 = ds.rdd
rdd1.collect().foreach(println)
sparkSession.stop()
}
case class UserRDD_DS(name:String, age:Int)
}
所需依賴:
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.12</artifactId>
<version>3.0.1</version>
</dependency>