簡體   English   中英

spark scala:用數千列逐行更新巨大的 dataframe

[英]spark scala: update huge dataframe with thousands of columns row-by-row

這是另一個未解決問題的后續,該問題是一項相當簡單的任務,即根據前幾列的信息更新大量列(~10,000)。 行數約為100M,數據大小在TB范圍內,排除collect方法。 在有幾百列的情況下,使用 UDF 的逐列方法會失敗(對於 1500 列不行)。 此外,Spark 似乎大部分時間都使用了大約 100-200% 的 CPU(與其他使用數十個內核的操作不同)。 這讓我相信 Spark dataframe緩存命中率低,可能是由於 memory 抖動所致。

然后我嘗試使用逐行方法解決,因為 Spark 在分區內保持行完整。 最直接的解決方法可能是使用case class並具有在行內有效處理並將更新的行作為可以轉換為 Z6A8064B5DF4794555500553C47C55057DZ 的元組的方法,利用需要修改的所有列使用相同的 UDF 這一事實。 但是,由於數量眾多,無法在case class的定義中命名列。 所以我嘗試如下。

scala> case class Gt(id: String*)

scala> val test = Gt("a", "b", "c")
test: Gt = Gt(WrappedArray(a, b, c))

scala> val columns = Seq("C1", "C2", "X1", "X2", "X3", "X4")
columns: Seq[String] = List(C1, C2, X1, X2, X3, X4)

scala> val data = Seq(("abc", "212", "1", "2", "3", "4"),("def", "436", "2", "2", "1", "8"),("abc", "510", "1", "2", "5", "8"))
data: Seq[(String, String, String, String, String, String)] = List((abc,212,1,2,3,4), (def,436,2,2,1,8), (abc,510,1,2,5,8))

scala> val rdd = spark.sparkContext.parallelize(data)
rdd: org.apache.spark.rdd.RDD[(String, String, String, String, String, String)] = ParallelCollectionRDD[220] at parallelize at <console>:34

scala> var df = spark.createDataFrame(rdd).toDF(columns:_*)
df: org.apache.spark.sql.DataFrame = [C1: string, C2: string ... 4 more fields]

scala> var ds = spark.createDataFrame(rdd).toDF(columns:_*).as[Gt]
java.lang.ClassNotFoundException: scala.<repeated>
  at scala.reflect.internal.util.AbstractFileClassLoader.findClass(AbstractFileClassLoader.scala:62)
  at java.lang.ClassLoader.loadClass(ClassLoader.java:424)

如果定義了參數,則Gt工作正常,否則如所見。

如果有人可以建議逐行更新 dataframe 的路徑,我將不勝感激。 鑒於復雜的計算,在當前情況下無法直接表達。

我終於找到了解決問題的兩種方法。

  1. 一次處理整行,然后應用 UDF,然后
  2. 將所有列合並為一個數組,並使用UDF進行處理。

雖然兩者都有效,但 (1) 速度更快,因為它沒有轉換開銷,另外,Spark 在任何情況下都適用於 Row-wise 數據(因此緩存局部性沒有額外的好處)。

暫無
暫無

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

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