Spark的 RDD, DataFrame和Dataset,何時使用它們,為什麼?

Spark的 RDD, DataFrame和Dataset,何時使用它們,為什麼?

原文地址:Spark 的 RDD, DataFrame, and Dataset 三種API

https://databricks.com/blog/2016/07/14/a-tale-of-three-apache-spark-apis-rdds-dataframes-and-datasets.html

對開發者來說,沒有什麼比一套生成力高、又簡單易用,還直觀和富有表現力的API更受愛戴的了。

Spark最吸引開發者的就是簡單易用、跨語言(Scala, Java, Python, and R)的API。

本文主要講解Apache Spark 2.0中RDD,DataFrame和Dataset三種API;它們各自適合的使用場景;它們的性能和優化;列舉使用DataFrame和DataSet代替RDD的場景。本文聚焦DataFrame和Dataset,因為這是Apache Spark 2.0的API統一的重點。

Apache Spark 2.0統一API的主要動機是:簡化Spark。通過減少用戶學習的概念和提供結構化的數據進行處理。除了結構化,Spark也提供higher-level抽象和API作為特定領域語言(DSL)。

彈性數據集(RDD)

RDD是Spark建立之初的核心API。RDD是不可變分佈式彈性數據集,在Spark集群中可跨節點分區,並提供分佈式low-level API來操作RDD,包括transformation和action。

何時使用RDD?

使用RDD的一般場景:

  • 你需要使用low-level的transformation和action來控制你的數據集;
  • 你的數據集非結構化,比如:流媒體或者文本流;
  • 你想使用函數式編程來操作你的數據,而不是用特定領域語言(DSL)表達;
  • 你不想加入schema,比如,當通過名字或者列處理(或訪問)數據屬性不在意列式存儲格式;
  • 當你可以放棄使用DataFrame和Dataset來優化結構化和半結構化數據集的時候。

在Spark2.0中RDD發生了什麼

你可能會問:RDD是不是成為“二等公民”了?或者是不是乾脆以後不用了?

答案當然是NO!

通過後面的描述你會得知:Spark用戶可以在RDD,DataFrame和Dataset三種數據集之間無縫轉換,而且只需要使用超級簡單的API方法。

DataFrames

DataFrame與RDD相同之處,都是不可變分佈式彈性數據集。不同之處在於,DataFrame的數據集都是按指定列存儲,即結構化數據。類似於傳統數據庫中的表。DataFrame的設計是為了讓大數據處理起來更容易。DataFrame允許開發者把結構化數據集導入DataFrame,並做了higher-level的抽象;DataFrame提供特定領域的語言(DSL)API來操作你的數據集。

在Spark2.0中,DataFrame API將會和Dataset API合併,統一數據處理API。由於這個統一“有點急”,導致大部分Spark開發者對Dataset的high-level和type-safe API並沒有什麼概念。

Spark的 RDD, DataFrame和Dataset,何時使用它們,為什麼?


DataSets

從Spark2.0開始,DataSets扮演了兩種不同的角色:強類型API和弱類型API,見下表。從概念上來講,可以把DataFrame 當作一個泛型對象的集合DataSet[Row], Row是一個弱類型JVM 對象。相對應地,如果JVM對象是通過Scala的case class或者Java class來表示的,Dataset是強類型的。

Spark的 RDD, DataFrame和Dataset,何時使用它們,為什麼?

Dataset API的優勢

對於Spark開發者而言,你將從Spark 2.0的DataFrame和Dataset統一的API獲得以下好處:

1. 靜態類型和運行時類型安全

考慮靜態類型和運行時類型安全,SQL有很少的限制而Dataset限制很多。例如,Spark SQL查詢語句,你直到運行時才能發現語法錯誤(syntax error),代價較大。然後DataFrame和Dataset在編譯時就可捕捉到錯誤,節約開發時間和成本。

Dataset API都是lambda函數和JVM typed object,任何typed-parameters不匹配即會在編譯階段報錯。因此使用Dataset節約開發時間。

Spark的 RDD, DataFrame和Dataset,何時使用它們,為什麼?

2. High-level抽象以及結構化和半結構化數據集的自定義視圖

DataFrame是Dataset[Row]的集合,把結構化數據集視圖轉換成半結構化數據集。例如,有個海量IoT設備事件數據集,用JSON格式表示。JSON是一個半結構化數據格式,很適合使用Dataset, 轉成強類型的Dataset[DeviceIoTData]。

Spark的 RDD, DataFrame和Dataset,何時使用它們,為什麼?

使用Scala為JSON數據DeviceIoTData定義case class。

Spark的 RDD, DataFrame和Dataset,何時使用它們,為什麼?

緊接著,從JSON文件讀取數據

Spark的 RDD, DataFrame和Dataset,何時使用它們,為什麼?

上面代碼運行時底層會發生下面3件事。

Spark讀取JSON文件,推斷出其schema,創建一個DataFrame;

Spark把數據集轉換DataFrame -> Dataset[Row],泛型Row object,因為這時還不知道其確切類型;

Spark進行轉換:Dataset[Row] -> Dataset[DeviceIoTData],DeviceIoTData類的Scala JVM object

我們的大多數人,在操作結構化數據時,都習慣於以列的方式查看和處理數據列,或者訪問對象的指定列。Dataset 是Dataset[ElementType]類型對象的集合,既可以編譯時類型安全,也可以為強類型的JVM對象定義視圖。從上面代碼獲取到的數據可以很簡單的展示出來,或者用高層方法處理。

Spark的 RDD, DataFrame和Dataset,何時使用它們,為什麼?

3. 簡單易用的API

雖然結構化數據會給Spark程序操作數據集帶來挺多限制,但它卻引進了豐富的語義和易用的特定領域語言。大部分計算可以被Dataset的high-level API所支持。例如,簡單的操作agg,select,avg,map,filter或者groupBy即可訪問DeviceIoTData類型的Dataset。

使用特定領域語言API進行計算是非常簡單的。例如,使用filter()和map()創建另一個Dataset。

把計算過程翻譯成領域API比RDD的關係代數式表達式要容易的多。例如:

Spark的 RDD, DataFrame和Dataset,何時使用它們,為什麼?

4. 性能和優化

使用DataFrame和Dataset API獲得空間效率和性能優化的兩個原因:

首先:因為DataFrame和Dataset是在Spark SQL 引擎上構建的,它會使用Catalyst優化器來生成優化過的邏輯計劃和物理查詢計劃。

R,Java,Scala或者Python的DataFrame/Dataset API,所有的關係型的查詢都運行在相同的代碼優化器下,代碼優化器帶來的的是空間和速度的提升。不同的是Dataset[T]強類型API優化數據引擎任務,而弱類型API DataFrame在交互式分析場景上更快,更合適。

Spark的 RDD, DataFrame和Dataset,何時使用它們,為什麼?

其次,通過博客https://databricks.com/blog/2016/05/23/apache-spark-as-a-compiler-joining-a-billion-rows-per-second-on-a-laptop.html 可以知道:Dataset能使用Encoder映射特定類型的JVM 對象到Tungsten內部內存表示。Tungsten的Encoder可以有效的序列化/反序列化JVM object,生成字節碼來提高執行速度。

什麼時候使用DataFrame或者Dataset?

  • 你想使用豐富的語義,high-level抽象,和特定領域語言API,那你可以使用DataFrame或者Dataset;
  • 你處理的半結構化數據集需要high-level表達,filter,map,aggregation,average,sum,SQL查詢,列式訪問和使用lambda函數,那你可以使用DataFrame或者Dataset;
  • 想利用編譯時高度的type-safety,Catalyst優化和Tungsten的code生成,那你可以使用DataFrame或者Dataset;
  • 你想統一和簡化API使用跨Spark的Library,那你可以使用DataFrame或者Dataset;
  • 如果你是一個R使用者,那你可以使用DataFrame或者Dataset;
  • 如果你是一個Python使用者,那你可以使用DataFrame或者Dataset。

你可以無縫地把DataFrame或者Dataset轉化成一個RDD,只需簡單的調用.rdd:

Spark的 RDD, DataFrame和Dataset,何時使用它們,為什麼?

總結

通過上面的分析,什麼情況選擇RDD,DataFrame還是Dataset已經很明顯了。RDD適合需要low-level函數式編程和操作數據集的情況;DataFrame和Dataset適合結構化數據集,使用high-level和特定領域語言(DSL)編程,空間效率高和速度快。


分享到:


相關文章: