簡體   English   中英

Spark:從異構數據寫入Paquet

[英]Spark: write Paquet from heterogeneous data

我有一個包含異構 JSON 的數據集,我可以按類型對其進行分組並對其應用 StructType。 例如RDD[(Type, JSON)]Set[Type] ,包含原始 RDD 的所有類型。

現在我想將這些 JSON 寫入一個類型化的 Parquet 文件,按類型分區。

我目前做的是:

val getSchema: Type => StructType = ???
val buildRow: StructType => JSON => Row = ???

types.foreach { jsonType =>
  val sparkSchema: StructType = getSchema(jsonType)
  val rows: RDD[Row] = rdd
    .filter(k => k == jsonType)
    .map { case (_, json) => buildRow(sparkSchema)(json) }
  spark.createDataFrame(rows, sparkSchema).write.parquet(path)
}

它可以工作,但效率很低,因為它需要多次遍歷原始 RDD——我通常有幾十種甚至幾百種類型。

有沒有更好的解決方案? 我試圖合並數據框,但它失敗了,因為無法合並具有不同參數的行。 或者至少我可以通過取消堅持來釋放 dataframe 占用的資源?

我想到了幾個選項(有些可能適合也可能不適合您的要求)。

  1. 如果不同的類型不需要是單獨的文件,您可以使用類似{type1col: StructType1, type2: StructType2, etc}的模式,並寫出只填充一個結構列的鑲木地板文件。
  2. 將數據重新分區,得到同一個分區(+某種二級鍵)中所有JSON個相同類型的對象,並寫出分區數據。 然后讀入並按類型過濾(如果它是分區寫的,你只需要加載一次數據)。 這只需要讀取數據 2 次(但洗牌可能很昂貴)。
  3. 您可以創建一個自定義WriteBatch ,它對(類型,JSON)的行進行操作,在寫入之前應用轉換並為每種類型保留一個打開的文件句柄。 如果您需要單獨的文件,這可能是最有效的,但需要大量代碼來維護和調試。

這將有助於加快 parquet 文件的寫入速度。 由於typesSet[Type] ,foreach 循環將按順序發生。 這意味着 parquet 文件是一個一個地寫入的(不是並行的)。 而且由於每個parquet文件的寫入都是相互獨立的,如果一次寫入多個文件應該沒有問題。

使用 scala parallel collections(參考: https://docs.scala-lang.org/overviews/parallel-collections/overview.html )將是實現它的最簡單方法。 嘗試將第 4 行編輯為:

types.par.foreach { jsonType =>

如果多次訪問,還緩存原始 RDD。

暫無
暫無

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

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