簡體   English   中英

Apache Spark 中的 Dataframe、Dataset 和 RDD 有什么區別?

[英]What are the differences between Dataframe, Dataset, and RDD in Apache Spark?

在 Apache Spark 中,這些 API 之間有什么區別? 為什么以及何時我們應該選擇其中一個而不是其他?

首先,讓我們定義 spark 的作用

  • 簡單地說,它所做的就是對分布式數據執行操作。 因此,操作也需要分布。 有些操作很簡單,例如過濾掉所有不遵守某些規則的項目。 其他更復雜,例如需要移動數據的 groupBy 和需要關聯來自 2 個或更多數據集的項目的 join。

  • 另一個重要的事實是輸入和輸出以不同的格式存儲,spark 具有讀取和寫入這些的連接器。 但這意味着對它們進行序列化和反序列化。 雖然是透明的,但序列化通常是最昂貴的操作。

  • 最后,spark 嘗試將數據保留在內存中以供處理,但當它不適合內存時,它會在每個工作人員本地 [ser/deser]ialize 數據。 再一次,它是透明地完成的,但成本可能很高。 有趣的事實:估計數據大小可能需要時間

API

  • RDD

這是 spark 提供的第一個 API。 簡單地說,它是分布在集群上的 scala/java 對象的無序序列。 在其上執行的所有操作都是 jvm 方法(傳遞給 map、flatmap、groupBy、...),這些方法需要被序列化,發送給所有工作人員,並應用於那里的 jvm 對象。 這與使用 scala Seq 幾乎相同,但是是分布式的。 它是強類型的,這意味着“如果它編譯然后它工作”(如果你不作弊)。 但是,可能會出現許多分發問題。 特別是如果 spark 不知道如何 [反] 序列化 jvm 類和方法。

  • 數據框

它緊隨其后,在語義上與 RDD 非常不同。 數據被視為表,可以對其進行sql操作等操作。 它根本沒有輸入,因此在執行過程中隨時可能出現錯誤。 但是,我認為有 2 個優點:(1)很多人習慣於 table/sql 語義和操作,(2)spark 不需要反序列化整行來處理它的列之一,如果數據格式提供合適的列訪問。 很多都這樣做,例如最常用的 parquet 文件格式。

  • 數據集

這是對 Dataframe 的改進,帶來了一些類型安全。 數據集是我們將與 jvm 類相關的“編碼器”關聯到的數據幀。 所以spark可以在執行代碼之前檢查數據模式是否正確。 但是請注意,有時我們可以讀到數據集是強類型的,但事實並非如此:它帶來了一些強類型安全性,您無法編譯使用具有未聲明類型的數據集的代碼。 但是很容易編寫可以編譯但在運行時仍然失敗的代碼。 這是因為許多數據集操作會丟失類型(除了過濾器之外的幾乎所有內容)。 這仍然是一個巨大的改進,因為即使我們犯了錯誤,它也會很快失敗:失敗發生在解釋 spark DAG 時(即在開始時)而不是在數據處理期間。

注意:數據框現在只是無類型的數據集( Dataset<Row>

注2:Dataset提供了RDD的主要API,如map、flatMap等。 據我所知,轉換為 rdd,然后應用 map/flatMap,然后轉換為數據集是一種捷徑。 這很實用,但也隱藏了轉換,因此很難意識到發生了可能代價高昂的 ser/deserialization。

優點和缺點

  • 數據集:

    • 優點:優化了面向列存儲的操作
    • 優點:許多操作也不需要反序列化
    • 優點:如果你喜歡,可以提供 table/sql 語義(我不;)
    • 優點:數據集操作帶有一個優化引擎“催化劑”,可以提高代碼的性能。 但是我不確定它是否真的那么好。 如果你知道你的代碼是什么,即對數據做了什么,你的代碼應該自己優化。
    • 缺點:大多數操作松散的打字
    • 缺點:對於不適合它的復雜算法,數據集操作可能變得過於復雜。 我知道的兩個主要限制是管理無效數據和復雜的數學算法。
  • 數據框:

    • 優點:在丟失類型的數據集操作之間需要
    • 缺點:只需使用 Dataset 它具有所有優點和更多
  • RDD:

    • 優點:(真的)強類型
    • 優點:scala/java 語義。 您可以像處理內存中集合的單 jvm 應用程序一樣設計您的代碼。 好吧,具有功能語義:)
    • 缺點:在前面提到的任何步驟中,都需要完整的 jvm 反序列化來處理數據:在讀取輸入之后,以及需要在工作人員之間移動數據或存儲在本地以管理內存限制的所有處理步驟之間。

結論

  • 只需默認使用數據集:

    • 使用編碼器讀取輸入,如果數據格式允許,它將在開始時驗證輸入模式
    • 使用數據集操作,當您松開類型時,返回到已鍵入的數據集。 通常,使用類型化數據集作為所有方法的輸入和輸出。
  • 在某些情況下,您要編碼的內容過於復雜而無法使用數據集操作來表達。 大多數應用程序沒有,但它經常發生在我實現復雜數學模型的工作中。 在這種情況下:

    • 從數據集開始
    • 使用數據集操作盡可能多地過濾和混洗(groupBy,join)數據
    • 一旦您只有所需的數據並且不需要移動它們,就轉換為 rdd 並應用您進行復雜的計算。

簡而言之:

  • RDD來自 Spark 的早期版本。 Dataframes 仍然在“幕后”使用。
  • 數據幀是在 Spark 1.x 后期引入的,並在 Spark 2.x 中真正成熟。 它們現在是首選存儲。 它們在 Java 中實現為數據集。
  • 數據集是通用實現,例如您可以擁有一個數據集。

我使用數據幀並強烈推薦它們:Spark 的優化器 Catalyst 可以理解更好的數據集(以及數據幀),並且 Row 是比純 JVM 對象更好的存儲容器。 你會發現很多關於內部的博客文章(包括 Databricks')。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM