> For the complete documentation index, see [llms.txt](https://spark-nctu.gitbook.io/spark/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://spark-nctu.gitbook.io/spark/rdd-cao-zuo/rdd-vs.-dataframe-vs.-dataset.md).

# RDD vs. DataFrame vs. DataSet

作為一個新興的平行運算平台，Spark 如宿命般在穩定以及效率兩端徘迴。RDD 這個原本 Spark 設計的核心概念，在 Spark 3.0 之後將進入冷凍 (maintenance mode)。在未來，新的 API 開發將基於新的 DataFrame 資料型態。因此，我們將先來探索這些新興的資料型態，並嘗試了解，為什麼 Spark 要做出這樣的變革。

## RDD vs. DataFrame vs. DataSet

我們先來看看 RDD 和 DataFrame 的差別。

DataFrame 是由 schemeRDD 型態衍生而來，簡單來說，就是一種有資料格式的 RDD。因此，和 RDD 一樣，可以視為一組**不可變**、**分散式**的**資料元素集合**。然而，和 RDD 不同，DataFrame 必須定義其資料格式，比較像是一個 SQL 的表格，我們可以以下圖表示:

![https://databricks.com/blog/2016/07/14/a-tale-of-three-apache-spark-apis-rdds-dataframes-and-datasets.html](/files/-LWaGUTbhD9ZsQfL559I)

上圖的 DataFrame 定義了各欄位 (Column) 的意義，因此，可以方便我們做更抽象的資料處理。而對於 RDD 而言，每一個 Person 物件並沒有格式化，而每一列 (Row) 的資料則分散儲存於各節點。這樣的一組分散式資料，可以進行上述的 Action 和 Transformation 運算。

事實上，上圖的 DataFrame 由於定義了各欄位的資料格式，更接近於 DataSet 的概念。對於 DataFrame 而言，可以視為是 untypied DataSet，也就是說，定義了例如像是 Age 的欄位，卻沒有定義 Age 的型態，而要到處理時才會決定型態。對於程式語言而言，這樣的屬性稱為 dynamically typed，代表像是: Python、matlab、R 等。另一方面，DataSet 這種預先定義好資料型態的方法，稱為 statically typed，我們可以在像是 Java、C、Scala (Java-based) 中看到此類語言的特性。

簡單來說，statically typed 更加安全，可以在編譯階段就找到錯誤，dynamically typed 的語言則可以進行抽象的語言操作，讓程式簡潔而易懂，我可以把比較列下表。

![https://databricks.com/blog/2016/07/14/a-tale-of-three-apache-spark-apis-rdds-dataframes-and-datasets.html](/files/-LWe693rUZoxvDzDv3Ew)

考慮到程式語言的特性，顯然的，Python 無法支援 DataSet API。

## 從 RDD 到 DataFrame

在 Spark 3.0 中，RDD-based 的 API 要停止更新，而主要支援 DataFrame-based 的 API。但是，這並不代表 RDD 這種資料型態將從 Spark 中消失。事實上，不論是 DataFrame 還是 DataSet 都是基於 RDD 的架構完成，RDD 仍然是最基礎的 Spark 資料型態，也是 Spark 可以提供平行化的設計。我們可以從下圖中看到，DataFrame 和 DataSet 實際上是透過 Catalyst 來建立 RDD。

![https://www.ithome.com.tw/news/112026](/files/-LWe9Kdxm3-Fy0uVjk0z)

Catalyst Optimizer 是 Spark SQL 中建立的一個模組，提供基於查詢與運算優化 RDD 配置的一個最佳化工具。換句話說，我們所宣告的 DataFrame 和 DataSet 將根據我們對其處理的動作，在 Spark 底層轉化成 RDD。

此時，出現一個有趣的問題: 為什麼直接操作 RDD，會比較沒有效率？而透過 DataFrame 或是 DataSet 的抽象操作反而更有效率呢？這是因為當我們直接操作 RDD 時，會傾向重複宣告 RDD，或是對一個大型的 RDD 進行操作，而不是真的對需要的資料進行操作。
