RDD知識(shí)點(diǎn)總結(jié)
五大特性,寬窄依賴(lài)等詳見(jiàn)連接:
http://www.itdecent.cn/p/592b985c443c Spark--Spark RDD知識(shí)點(diǎn)總結(jié)
總結(jié)來(lái)說(shuō):
?RDD是一個(gè)懶執(zhí)行的不可變的可以支持Lambda表達(dá)式的并行數(shù)據(jù)集合。
?RDD的最大好處就是簡(jiǎn)單,API的人性化程度很高。
?RDD的劣勢(shì)是性能限制,它是一個(gè)JVM駐內(nèi)存對(duì)象,這也就決定了存在GC的限制和數(shù)據(jù)增加時(shí)Java序列化成本的升高。
GC和序列化是嚴(yán)重影響RDD執(zhí)行效率的重要原因;
DataFrame
-
與RDD類(lèi)似,DataFrame也是一個(gè)分布式數(shù)據(jù)容器。然而DataFrame更像傳統(tǒng)數(shù)據(jù)庫(kù)的二維表格,除了數(shù)據(jù)以外,還記錄數(shù)據(jù)的結(jié)構(gòu)信息,即schema。同時(shí),與Hive類(lèi)似,DataFrame也支持嵌套數(shù)據(jù)類(lèi)型(struct、array和map)。從API易用性的角度上看,DataFrame API提供的是一套高層的關(guān)系操作,比函數(shù)式的RDD API要更加友好,門(mén)檻更低。由于與R和Pandas的DataFrame類(lèi)似,Spark DataFrame很好地繼承了傳統(tǒng)單機(jī)數(shù)據(jù)分析的開(kāi)發(fā)體驗(yàn)。
spark RDD與Dataframe區(qū)別.png - 上圖直觀(guān)地體現(xiàn)了DataFrame和RDD的區(qū)別。左側(cè)的RDD[Person]雖然以Person為類(lèi)型參數(shù),但Spark框架本身不了解Person類(lèi)的內(nèi)部結(jié)構(gòu)。而右側(cè)的DataFrame卻提供了詳細(xì)的結(jié)構(gòu)信息,使得Spark SQL可以清楚地知道該數(shù)據(jù)集中包含哪些列,每列的名稱(chēng)和類(lèi)型各是什么。DataFrame多了數(shù)據(jù)的結(jié)構(gòu)信息,即schema。RDD是分布式的Java對(duì)象的集合。DataFrame是分布式的Row對(duì)象的集合。DataFrame除了提供了比RDD更豐富的算子以外,更重要的特點(diǎn)是提升執(zhí)行效率、減少數(shù)據(jù)讀取以及執(zhí)行計(jì)劃的優(yōu)化,比如filter下推、裁剪等。
- DataFrame是為數(shù)據(jù)提供了Schema的視圖??梢园阉?dāng)做數(shù)據(jù)庫(kù)中的一張表來(lái)對(duì)待
- DataFrame也是懶執(zhí)行的。
- 性能上比RDD要高,主要有兩方面原因:
- 定制化內(nèi)存管理
- 數(shù)據(jù)以二進(jìn)制的方式存在于非堆內(nèi)存,節(jié)省了大量空間之外,還擺脫了GC的限制。(后文詳細(xì)分許)
- 優(yōu)化的執(zhí)行計(jì)劃
- 查詢(xún)計(jì)劃通過(guò)Spark catalyst optimiser進(jìn)行優(yōu)化.(后文詳細(xì)分析)
- 定制化內(nèi)存管理
Dataset
- 是Dataframe API的一個(gè)擴(kuò)展,是Spark最新的數(shù)據(jù)抽象
- 用戶(hù)友好的API風(fēng)格,既具有類(lèi)型安全檢查也具有Dataframe的查詢(xún)優(yōu)化特性。
- Dataset支持編解碼器,當(dāng)需要訪(fǎng)問(wèn)非堆上的數(shù)據(jù)時(shí)可以避免反序列化整個(gè)對(duì)象,提高了效率。
- 樣例類(lèi)被用來(lái)在Dataset中定義數(shù)據(jù)的結(jié)構(gòu)信息,樣例類(lèi)中每個(gè)屬性的名稱(chēng)直接映射到DataSet中的字段名稱(chēng)。
- Dataframe是Dataset的特列,DataFrame=Dataset[Row] ,所以可以通過(guò)as方法將Dataframe轉(zhuǎn)換為Dataset。Row是一個(gè)類(lèi)型,跟Car、Person這些的類(lèi)型一樣,所有的表結(jié)構(gòu)信息我都用Row來(lái)表示。
- DataSet是強(qiáng)類(lèi)型的。比如可以有Dataset[Car],Dataset[Person].
DataFrame只是知道字段,但是不知道字段的類(lèi)型,所以在執(zhí)行這些操作的時(shí)候是沒(méi)辦法在編譯的時(shí)候檢查是否類(lèi)型失敗的,比如你可以對(duì)一個(gè)String進(jìn)行減法操作,在執(zhí)行的時(shí)候才報(bào)錯(cuò),而DataSet不僅僅知道字段,而且知道字段類(lèi)型,所以有更嚴(yán)格的錯(cuò)誤檢查。就跟JSON對(duì)象和類(lèi)對(duì)象之間的類(lèi)比。
-
關(guān)于第六條的具體理解如下:
spark df和ds在編譯方面的區(qū)別.PNG
-
RDD轉(zhuǎn)換DataFrame后不可逆,但RDD轉(zhuǎn)換Dataset是可逆的(這也是Dataset產(chǎn)生的原因)。如下操作所示:
spark RDD與ds相互轉(zhuǎn)換.PNG
- 總結(jié)
- RDD讓我們能夠決定怎么做,而DataFrame和DataSet讓我們決定做什么,控制的粒度不一樣。
三者的共性
1、RDD、DataFrame、Dataset全都是spark平臺(tái)下的分布式彈性數(shù)據(jù)集,為處理超大型數(shù)據(jù)提供便利
2、三者都有惰性機(jī)制,在進(jìn)行創(chuàng)建、轉(zhuǎn)換,如map方法時(shí),不會(huì)立即執(zhí)行,只有在遇到Action如foreach時(shí),三者才會(huì)開(kāi)始遍歷運(yùn)算,極端情況下,如果代碼里面有創(chuàng)建、轉(zhuǎn)換,但是后面沒(méi)有在Action中使用對(duì)應(yīng)的結(jié)果,在執(zhí)行時(shí)會(huì)被直接跳過(guò).
3、三者都會(huì)根據(jù)spark的內(nèi)存情況自動(dòng)緩存運(yùn)算,這樣即使數(shù)據(jù)量很大,也不用擔(dān)心會(huì)內(nèi)存溢出
4、三者都有partition的概念
5、三者有許多共同的函數(shù),如filter,排序等
6、在對(duì)DataFrame和Dataset進(jìn)行操作許多操作都需要這個(gè)包進(jìn)行支持
import spark.implicits._
7、DataFrame和Dataset均可使用模式匹配獲取各個(gè)字段的值和類(lèi)型
三者的區(qū)別
RDD優(yōu)缺點(diǎn)
- 優(yōu)點(diǎn):
(1)編譯時(shí)類(lèi)型安全;
編譯時(shí)就能檢查出類(lèi)型錯(cuò)誤;
(2)面向?qū)ο蟮木幊田L(fēng)格 ;
直接通過(guò)對(duì)象調(diào)用方法的形式來(lái)操作數(shù)據(jù); - 缺點(diǎn):
(1)序列化和反序列化的性能開(kāi)銷(xiāo) ;
無(wú)論是集群間的通信, 還是IO操作都需要對(duì)對(duì)象的結(jié)構(gòu)和數(shù)據(jù)進(jìn)行序列化和反序列化。
(2)GC的性能開(kāi)銷(xiāo) ;
頻繁的創(chuàng)建和銷(xiāo)毀對(duì)象, 勢(shì)必會(huì)增加GC;
DataFrame優(yōu)缺點(diǎn)
- 優(yōu)點(diǎn):
(1)DataFrame提供了數(shù)據(jù)的詳細(xì)的結(jié)構(gòu)信息,即schema,使得Spark SQL可以清楚地知道該數(shù)據(jù)集中包含哪些列,每列的名稱(chēng)和類(lèi)型各是什么,可以像表一樣對(duì)數(shù)據(jù)進(jìn)行操作,可以使用sql進(jìn)行直接操作,提供了DSL風(fēng)格語(yǔ)法和SQL風(fēng)格語(yǔ)法;
(2)DataFrame還引入了off-heap,意味著JVM堆以外的內(nèi)存,這些內(nèi)存直接受操作系統(tǒng)管理(而不是JVM)。Spark能夠以二進(jìn)制的形式序列化數(shù)據(jù)(不包括結(jié)構(gòu))到off-heap中, 當(dāng)要操作數(shù)據(jù)時(shí), 就直接操作off-heap內(nèi)存。可以快速操作數(shù)據(jù),避免大量的GC;(注意:df在通信和IO的時(shí)候,只需要序列化和反序列化數(shù)據(jù), 而結(jié)構(gòu)的部分就可以省略了)
(3) RDD是分布式的Java對(duì)象的集合。DataFrame是分布式的Row對(duì)象的集合。DataFrame除了提供了比RDD更豐富的算子以外,更重要的特點(diǎn)是提升執(zhí)行效率、減少數(shù)據(jù)讀取以及執(zhí)行計(jì)劃的優(yōu)化。
(4) 執(zhí)行優(yōu)化,通過(guò)DataFrame API或SQL處理數(shù)據(jù),會(huì)自動(dòng)經(jīng)過(guò)Spark 優(yōu)化器(Catalyst)的優(yōu)化,即使你寫(xiě)的程序或SQL不高效,也可以運(yùn)行的很快。
(5)減少數(shù)據(jù)讀取,分析大數(shù)據(jù),最快的方法就是 —忽略它。這里的“忽略”并不是熟視無(wú)睹,而是根據(jù)查詢(xún)條件進(jìn)行恰當(dāng)?shù)募糁Α?br> 對(duì)于一些“智能”數(shù)據(jù)格 式,Spark SQL還可以根據(jù)數(shù)據(jù)文件中附帶的統(tǒng)計(jì)信息來(lái)進(jìn)行剪枝。簡(jiǎn)單來(lái)說(shuō),在這類(lèi)數(shù)據(jù)格式中,數(shù)據(jù)是分段保存的,每段數(shù)據(jù)都帶有最大值、最小值、null值數(shù)量等 一些基本的統(tǒng)計(jì)信息。當(dāng)統(tǒng)計(jì)信息表名某一數(shù)據(jù)段肯定不包括符合查詢(xún)條件的目標(biāo)數(shù)據(jù)時(shí),該數(shù)據(jù)段就可以直接跳過(guò)(例如某整數(shù)列a某段的最大值為100,而查詢(xún)條件要求a > 200)。此外,Spark SQL也可以充分利用RCFile、ORC、Parquet等列式存儲(chǔ)格式的優(yōu)勢(shì),僅掃描查詢(xún)真正涉及的列,忽略其余列的數(shù)據(jù)。 - 缺點(diǎn):
(1) DataFrame不是類(lèi)型安全的,API也不是面向?qū)ο蟮娘L(fēng)格;
DataSet優(yōu)缺點(diǎn)
- 優(yōu)點(diǎn):
(1)DataSet包含了DataFrame的功能,Spark2.0中兩者統(tǒng)一,DataFrame表示為DataSet[Row],即DataSet的子集。
(2)DataSet可以在編譯時(shí)檢查類(lèi)型;
(3)并且是面向?qū)ο蟮木幊探涌冢?br> (4) 集中了RDD的優(yōu)點(diǎn)(強(qiáng)類(lèi)型和可以用強(qiáng)大lambda函數(shù))以及使用了Spark SQL優(yōu)化的執(zhí)行引擎。DataSet可以通過(guò)JVM的對(duì)象進(jìn)行構(gòu)建,可以用函數(shù)式的轉(zhuǎn)換(map/flatmap/filter)進(jìn)行多種操作。 - 缺點(diǎn):
暫未整理,以后補(bǔ)上;
DataFrame轉(zhuǎn)成RDD會(huì)不會(huì)有性能的消耗
答:由df轉(zhuǎn)成rdd,df.rdd的過(guò)程會(huì)有一個(gè)反序列化的過(guò)程,會(huì)造成一定的內(nèi)存消耗,
具體詳見(jiàn)源碼解析:
/**
* Represents the content of the Dataset as an `RDD` of `T`.
*
* @group basic
* @since 1.6.0
*/
lazy val rdd: RDD[T] = {
val objectType = exprEnc.deserializer.dataType
val deserialized = CatalystSerde.deserialize[T](logicalPlan)
sparkSession.sessionState.executePlan(deserialized).toRdd.mapPartitions { rows =>
rows.map(_.get(0, objectType).asInstanceOf[T])
}
}
