簡體   English   中英

Spark 2.0 數據集與數據幀

[英]Spark 2.0 Dataset vs DataFrame

從 spark 2.0.1 開始我有一些問題。 我閱讀了很多文檔,但到目前為止找不到足夠的答案:

  • 之間有什么區別
    • df.select("foo")
    • df.select($"foo")
  • 我理解正確嗎
    • myDataSet.map(foo.someVal)是類型安全的,不會轉換為RDD而是保留在 DataSet 表示中/沒有額外的開銷(2.0.0 的性能明智)
  • 所有其他命令,例如 select, .. 只是語法糖。 它們不是類型安全的,可以使用映射代替。 如果沒有 map 語句,我怎么能df.select("foo")類型安全?
    • 為什么我應該使用 UDF / UADF 而不是地圖(假設地圖保留在數據集表示中)?
  1. df.select("foo")df.select($"foo")之間的df.select("foo")是簽名。 前一個需要至少一個String ,后一個需要零個或多個Columns 除此之外沒有任何實際區別。
  2. myDataSet.map(foo.someVal)類型檢查,但由於任何Dataset操作都使用對象的RDD ,並且與DataFrame操作相比,有很大的開銷。 我們來看一個簡單的例子:

     case class FooBar(foo: Int, bar: String) val ds = Seq(FooBar(1, "x")).toDS ds.map(_.foo).explain
     == Physical Plan == *SerializeFromObject [input[0, int, true] AS value#123] +- *MapElements <function1>, obj#122: int +- *DeserializeToObject newInstance(class $line67.$read$$iw$$iw$FooBar), obj#121: $line67.$read$$iw$$iw$FooBar +- LocalTableScan [foo#117, bar#118]

    如您所見,此執行計划需要訪問所有字段,並且必須是DeserializeToObject

  3. 不。一般來說,其他方法不是語法糖,會生成明顯不同的執行計划。 例如:

     ds.select($"foo").explain
     == Physical Plan == LocalTableScan [foo#117]

    與之前顯示的計划相比,它可以直接訪問列。 這與其說是 API 的限制,不如說是操作語義差異的結果。

  4. 如果沒有 map 語句,我怎么能 df.select("foo") 類型安全?

    沒有這樣的選擇。 類型列允許您將靜態Dataset轉換為另一個靜態類型Dataset

     ds.select($"bar".as[Int])

    沒有類型安全。 還有一些其他嘗試包括類型安全的優化操作,比如類型化聚合,但是這個實驗性的 API。

  5. 為什么我應該使用 UDF / UADF 而不是地圖

    這完全取決於你。 Spark 中的每個分布式數據結構都有自己的優點和缺點(例如,參見Spark UDAF with ArrayType as bufferSchema performance issues )。

就我個人而言,我發現靜態類型的Dataset是最沒用的:

  • 不要提供與Dataset[Row]相同范圍的優化(盡管它們共享存儲格式和一些執行計划優化,但它並沒有完全受益於代碼生成或堆外存儲),也不要訪問DataFrame所有分析功能.

  • 類型轉換是黑盒,有效地為優化器創建分析障礙。 例如選擇(過濾器)不能被推到類型轉換上:

     ds.groupBy("foo").agg(sum($"bar") as "bar").as[FooBar].filter(x => true).where($"foo" === 1).explain
     == Physical Plan == *Filter (foo#133 = 1) +- *Filter <function1>.apply +- *HashAggregate(keys=[foo#133], functions=[sum(cast(bar#134 as double))]) +- Exchange hashpartitioning(foo#133, 200) +- *HashAggregate(keys=[foo#133], functions=[partial_sum(cast(bar#134 as double))]) +- LocalTableScan [foo#133, bar#134]

    相比:

     ds.groupBy("foo").agg(sum($"bar") as "bar").as[FooBar].where($"foo" === 1).explain
     == Physical Plan == *HashAggregate(keys=[foo#133], functions=[sum(cast(bar#134 as double))]) +- Exchange hashpartitioning(foo#133, 200) +- *HashAggregate(keys=[foo#133], functions=[partial_sum(cast(bar#134 as double))]) +- *Filter (foo#133 = 1) +- LocalTableScan [foo#133, bar#134]

    這會影響謂詞下推或投影下推等功能。

  • 不像RDDs那樣靈活,只有一小部分本地支持的類型。

  • 當使用as方法轉換Dataset時, Encoders “類型安全”是有爭議的。 因為數據形狀不是使用簽名編碼的,所以編譯器只能驗證Encoder的存在。

相關問題:

Spark Dataset比 Spark Dataframe強大得多。 小例子 - 您只能創建RowTuple或任何原始數據類型的Dataframe ,但Dataset使您能夠創建任何非原始類型的Dataset 即您可以從字面上創建對象類型的Dataset

例如:

case class Employee(id:Int,name:String)

Dataset[Employee]   // is valid
Dataframe[Employee] // is invalid

DATAFRAME:DataFrame 是一種抽象,它允許數據的模式視圖。

case class Person(name: String, age: Int, address: String)

定義類 Person

scala > val df = List ( Person ( “Sumanth”, 23, “BNG”)

數據框與數據集

DATASET:Data Set 是 Dataframe API 的擴展,它是最新的抽象,它試圖提供 RDD 和 Dataframe 的最佳功能。

暫無
暫無

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

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