繁体   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