使用数据集,大型java类和单例时,Spark传递函数

时间:2017-03-24 01:20:19

标签: apache-spark parquet apache-spark-dataset

我在这里阅读了这篇文章:https://spark.apache.org/docs/latest/programming-guide.html(请参阅将函数传递给Spark),但我的用例是使用类型化数据集和我的案例类。我正在尝试使用单例对象来保存映射方法。我想知道如何最好地打包我需要的功能来优化我的舞台的性能(将数据集从一种类型转换为另一种类型,并写入镶木地板)。

目前,舞台步骤耗时非常长,大约300万行(约1.5小时),大约880 MB的数据输出到s3中的镶木地板。

我在群集模式下运行使用min executors = 3,max executors = 10,每个执行器上有4个内核,驱动程序内存为8gb。

-

高级编码部分:

我将一个案例类C1映射到另一个案例类C2。 C1和C2有大约16个字段,各种类型,如java.sql.Timestamp,Option [String] Option [Int],String,Int,BigInt。

case class C1(field1 : _, field2 : _, field3 : _, ...)
case class C2(field1 : _, field2 : _, field3 : _, ...)

为了从C1映射到C2,我需要从https://github.com/drtimcooper/LatLongToTimezone复制的非常大的java类 J的功能(静态方法)。

public class J {
   public static String getValue((float) v) = ...
}    

我已经在util类Util中编写了映射函数,它有许多其他由映射函数调用的有用函数。

======

基本上我的代码流程如下:

case class C1(field1 : _, field2 : _, field3 : _, ...)
case class C2(field1 : _, field2 : _, field3 : _, ...)

// very large java class J that only contains static methods
public class J {
   public static String getValue((float) v) = ...

   ...
}    

object Util {
  def m1(i: Int): Int = ...

  def m2(l: Option[BigDecimal], l2: Option[BigDecimal]): Int = {
      J.getValue(l.get, l2.get)
  }

  ...

  def convert_C1_to_C2(c1: C1): C2 = {
    C2(
      field1 = m1(c1.field1),
      field2 = m2(c1.field2, c1.field3),
      ...
  }
}

dataframe.as[C1].map(Util.convert_C1_to_C2)
    .mode(SaveMode.Overwrite)
    .parquet("s3a://s3Path")

有更优化的方式来写这个吗?或者任何人都可以指出我这样做的任何明显错误?看看我的代码,我不确定为什么要花这么长时间才能完成任务。

我已经尝试过合并说,16个分区可以减少s3中的文件数量,但这似乎会让作业运行得慢得多。通常会有64个分区没有任何合并。

1 个答案:

答案 0 :(得分:0)

您可能只是遇到了elsewhere所涉及的慢速伪造s3重命名问题。这里讨论了一些修正。