天天看點

RDD和DataFrame和DataSet三者間的差別

參考:https://blog.csdn.net/weixin_43087634/article/details/84398036

RDD和DataFrame和DataSet三者間的差別

在SparkSQL中Spark提供了兩個新的抽象,分别是DataFrame和DataSet。他們和RDD有什麼差別呢?首先從版本的産生上來看:

RDD (Spark1.0) —> Dataframe(Spark1.3) —> Dataset(Spark1.6)

如果同樣的資料都給到這三個資料結構,他們分别計算之後,都會給出相同的結果。不同是的他們的執行效率和執行方式。

在後期的Spark版本中,DataSet會逐漸取代RDD和DataFrame成為唯一的API接口。

RDD

  • RDD的最大好處就是簡單,API的人性化程度很高。
  • RDD的劣勢是性能限制,它是一個JVM駐記憶體對象,這也就決定了存在GC的限制和資料增加時Java序列化成本的升高。

Dataframe

與RDD類似,DataFrame也是一個分布式資料容器。然而DataFrame更像傳統資料庫的二維表格,除了資料以外,還記錄資料的結構資訊,即schema。

從API易用性的角度上看,DataFrame API提供的是一套高層的關系操作,比函數式的RDD API要更加友好,門檻更低。

RDD和DataFrame和DataSet三者間的差別

DataFrame除了提供了比RDD更豐富的算子以外,更重要的特點是提升執行效率、減少資料讀取以及執行計劃的優化,比如filter下推、裁剪等。

性能上比RDD要高,主要有兩方面原因: 

  1. 定制化記憶體管理,資料以二進制的方式存在于非堆記憶體,節省了大量空間之外,還擺脫了GC的限制
  2. 優化的執行計劃,查詢計劃通過Spark catalyst optimiser進行優化.

Dataframe的劣勢在于在編譯期缺少類型安全檢查,導緻運作時出錯。

Dataset

  1. 是Dataframe API的一個擴充,是Spark最新的資料抽象;
  2. 使用者友好的API風格,既具有類型安全檢查也具有Dataframe的查詢優化特性;
  3. Dataset支援編解碼器,當需要通路非堆上的資料時可以避免反序列化整個對象,提高了效率;
  4. 樣例類被用來在Dataset中定義資料的結構資訊,樣例類中每個屬性的名稱直接映射到DataSet中的字段名稱;
  5. Dataframe是Dataset的特列,DataFrame=Dataset[Row] ,是以可以通過as方法将Dataframe轉換為Dataset。Row是一個類型,跟Car、Person這些的類型一樣,所有的表結構資訊我都用Row來表示;
  6. DataSet是強類型的。比如可以有Dataset[Car],Dataset[Person]。

DataFrame隻是知道字段,但是不知道字段的類型,是以在執行這些操作的時候是沒辦法在編譯的時候檢查是否類型失敗的,比如你可以對一個String進行減法操作,在執行的時候才報錯,而DataSet不僅僅知道字段,而且知道字段類型,是以有更嚴格的錯誤檢查。就跟JSON對象和類對象之間的類比。

三者的共性

  1. RDD、DataFrame、Dataset全都是spark平台下的分布式彈性資料集,為處理超大型資料提供便利;
  2. 三者都有惰性機制,在進行建立、轉換,如map方法時,不會立即執行,隻有在遇到Action如foreach時,三者才會開始周遊運算,極端情況下,如果代碼裡面有建立、轉換,但是後面沒有在Action中使用對應的結果,在執行時會被直接跳過;
  3. 三者都會根據spark的記憶體情況自動緩存運算,這樣即使資料量很大,也不用擔心會記憶體溢出;
  4. 三者都有partition的概念;
  5. 三者有許多共同的函數,如filter,排序等;
  6. 在對DataFrame和Dataset進行操作許多操作都需要 spark.implicits._ 這個包進行支援;
  7. DataFrame和Dataset均可使用模式比對擷取各個字段的值和類型。

三者的差別

RDD:

  1. RDD一般和spark mlib同時使用;
  2. RDD不支援sparksql操作

DataFrame:

  1. 與RDD和Dataset不同,DataFrame每一行的類型固定為Row,隻有通過解析才能擷取各個字段的值;
  2. DataFrame與Dataset一般不與spark ml同時使用;
  3. DataFrame與Dataset均支援sparksql的操作,比如select,groupby之類,還能注冊臨時表/視窗,進行sql語句操作;
  4. DataFrame與Dataset支援一些特别友善的儲存方式,比如儲存成csv,可以帶上表頭,這樣每一列的字段名一目了然

Dataset:

  1. Dataset和DataFrame擁有完全相同的成員函數,差別隻是每一行的資料類型不同;
  2. DataFrame也可以叫Dataset[Row],每一行的類型是Row,不解析,每一行究竟有哪些字段,各個字段又是什麼類型都無從得知,隻能用上面提到的getAS方法或者共性中的第七條提到的模式比對拿出特定字段。而Dataset中,每一行是什麼類型是不一定的,在自定義了case class之後可以很自由的獲得每一行的資訊;
  3. Dataset在需要通路列中的某個字段時是非常友善的,然而,如果要寫一些适配性很強的函數時,如果使用Dataset,行的類型又不确定,可能是各種case class,無法實作适配,這時候用DataFrame即Dataset[Row]就能比較好的解決問題。

繼續閱讀