如何在Spark中同时处理多个DataFrame?

时间:2017-10-27 18:34:52

标签: apache-spark

我对Spark非常陌生,所以我的术语可能会关闭,但这就是我要做的事情:

  • 我每天都有一组CSV文件代表S3上数据库中表格的快照(称之为表A,B,C,存储在例如s3://bucket/20171027/a.csv.gz
  • 我想在密钥(id)上使用Spark SQL加入这些表(一天),然后将连接表作为JSON保存到S3。

我能够按顺序(日复一日)执行此操作,但希望利用Spark并行化。

我目前的流程大致是:

  • 列出S3中的所有文件
  • 按时间戳分组
  • 创建要加入的文件名数组
  • result是timestamp =>的地图文件(例如20171027 => [" s3://foo/20171027/a.csv" ;," s3://foo/20171027/b.csv"])

然后,对于每一天,我将每个文件加载到DataFrame中,在删除重复列时执行一些逻辑,然后调用df1.join(df2)。连接完成后,我调用df.write.json

每天都可以独立完成,但我无法弄清楚如何让Spark同时运行这些连接操作。我尝试使用带有时间戳的sc.parallelize作为序列,但我不能让Spark上下文在执行程序中加载DataFrames,如果在调用parallelize之前加载DataFrames,执行程序可以&# 39;读取它们并抛出NullObjectException。我想我需要研究使用期货,但我想知道是否有其他选择来完成我想要做的事情,或者我是否让它变得比它需要的更复杂。

1 个答案:

答案 0 :(得分:1)

我想出的解决方案是使用Futures,其线程池等于执行程序的数量。每天循环,我执行连接表的操作,然后在自己的Future中写入磁盘。线程池将并发限制为执行程序的数量。然后等待所有期货在完成之前完成。

implicit val ec = ExecutionContext.fromExecutorService(Executors.newWorkStealingPool(numExecutors))
val futures = ArrayBuffer[Future[Unit]]()

for (date <- files.keys) {
  val f = Future {
    // load tables from S3 into data frames
    // join data frames on ID
    // write joined dataframe to S3
  }
  futures += f
}

futures.foreach(f => Await.ready(f, Duration.Inf))