Dataset是分布式數(shù)據(jù)集合粒蜈。Dataset是Spark1.6新增的接口宴卖,用以提供RDDs(強類型等恐,有使用強大的lambda函數(shù)的能力)的優(yōu)點和Spark SQL的經(jīng)優(yōu)化的執(zhí)行引擎的優(yōu)點途样。Dataset可以從JVM對象進行構造并通過轉(zhuǎn)換函數(shù)(如map壹甥,flatmap,filter等)進行操作。DatasetAPI支持Scala和Java颁股。Python不支持Dataset API么库。但因為Python本身的動態(tài)性傻丝,DatasetAPI的許多優(yōu)點都已經(jīng)可用(比如甘有,你可以通過名字很自然的訪問一行的某一個字段,如row.columnName)葡缰,R的情況與此類似亏掀。
Dataset與RDD很像,不同的是它并不使用Java序列化或者Kryo泛释,而是使用特殊的編碼器來為網(wǎng)絡間的處理或傳輸?shù)膶ο筮M行序列化滤愕。對轉(zhuǎn)換一個對象為字節(jié)的過程來說編碼器和標準系列化器都是可靠的,編碼器的代碼是自動生成并且使用了一種格式怜校,這種格式允許Spark在不需要將字節(jié)解碼成對象的情況下執(zhí)行很多操作间影,如filtering、sorting和hashing等茄茁。
DataFrame是Dataset組織成列的數(shù)據(jù)集魂贬。它在概念上相當于關系型數(shù)據(jù)庫中的表,或者R/Python中的數(shù)據(jù)幀裙顽,但是在底層進行了更多的優(yōu)化付燥。DataFrames可以從多種數(shù)據(jù)源創(chuàng)建,例如:結構化數(shù)據(jù)文件愈犹、Hive中的表键科、外部數(shù)據(jù)庫或者已存在的RDDs。DataFrame API支持Scala漩怎、Java勋颖、Python和R。在Scala和Java中DataFrame其實是Dataset的RowS的形式的表示勋锤。在Scala API中牙言,DataFrame僅僅是Dataset[Row]的別名。但在Java中怪得,使用者需要使用Dataset來表示一個DataFrame咱枉。
但是 DataFrame 出來后發(fā)現(xiàn)有些情況下 RDD 可以表達的邏輯用 DataFrame 無法表達。比如 要對 group by 或 join 后的結果用自定義的函數(shù),可能用 SQL 是無法表達的徒恋。如下代碼:
case class ClassData(a: String, b: Int)
case class ClassNullableData(a: String, b: Integer)
val ds = Seq(ClassData("a", 1), ClassData("a", 2)).toDS()
val agged = ds.groupByKey(d => ClassNullableData(d.a, null))
.mapGroups {
case (key, values) => key.a + values.map(_.b).sum
}
中間處理過程的數(shù)據(jù)是自定義的類型,并且 groupby 后的聚合邏輯也是自定義的蚕断,故用 SQL 比較難以表達,所以提出了 Dataset API入挣。Dataset API 擴展 DataFrame API 支持靜態(tài)類型和運行已經(jīng)存在的 Scala 或 Java 語言的用戶自定義函數(shù)亿乳。同時 Dataset 也能享受 Spark SQL 里所有性能 帶來的提升。
Spark SQL的Scala接口支持自動的將一個包含case class的RDD轉(zhuǎn)換為DataFrame。這個case class定義了表結構葛假。Caseclass的參數(shù)名是通過反射機制讀取障陶,然后變成列名。Caseclass可以嵌套或者包含像Seq或Array之類的復雜類型聊训。這個RDD可以隱式的轉(zhuǎn)換為一個DataFrame抱究,然后被注冊為一張表。這個表可以隨后被SQL的statement使用带斑。
Spark SQL支持兩種將已存在的RDD轉(zhuǎn)化為Dataset的方法鼓寺。第一種方法使用反射推斷包含特定類型對象的RDD的結構。這種基于反射的方法代碼更加簡潔勋磕,并且當你在寫Spark程序的時候已經(jīng)知道RDD的結構的情況下效果很好妈候。
第二種創(chuàng)建Dataset的方法是通過編程接口建立一個結構,然后將它應用于一個存在的RDD挂滓。雖然這種方法更加繁瑣苦银,但它允許你在運行之前不知道其中的列和對應的類型的情況下構建Dataset。
DataFrame和DataSet可以相互轉(zhuǎn)化赶站,df.as[ElementType]這樣可以把DataFrame轉(zhuǎn)化為DataSet幔虏,ds.toDF()這樣可以把DataSet轉(zhuǎn)化為DataFrame。