我有一个大型DataFrame,如下所示:
val df = spark.read.option("basePath", "s3://some_bucket/").json("s3://some_bucket/group_id=*/")
在s3://some_bucket
有JSON文件〜1TB,它包含5000个group_id
分区。
我想使用SparkSQL执行转换,它因每个group_id
而不同。
Spark代码如下:
// Create view
val df = spark.read.option("basePath", "s3://data_lake/").json("s3://data_lake/group_id=*/")
df.createOrReplaceTempView("lakeView")
// one of queries like this:
// SELECT
// col1 as userId,
// col2 as userName,
// .....
// FROM
// lakeView
// WHERE
// group_id = xxx;
val queries: Seq[String] = getGroupIdMapping
// ** Want to know better ways **
queries.par.foreach(query => {
val convertedDF: DataFrame = spark.sql(query)
convertedDF.write.save("s3://another_bucket/")
})
par
可以Runtime.getRuntime.availableProcessors
num并行化,它将等于驱动程序核心数。
但这似乎很奇怪而且效率不高,因为它与Spark的并行化毫无关系。
我真的想在groupBy
中使用scala.collection.Seq
之类的内容。
这不是正确的火花代码:
df.groupBy(groupId).foreach((groupId, parDF) => {
parDF.createOrReplaceTempView("lakeView")
val convertedDF: DataFrame = spark.sql(queryByGroupId)
convertedDF.write.save("s3://another_bucket")
})
答案 0 :(得分:2)
1)首先,如果您的数据已经存储在每个组ID的文件中,则没有理由将其混合,然后使用Spark按ID进行分组。 为每个组ID加载相关文件
更简单有效2)Spark本身并行计算。因此在大多数情况下,不需要外部并行化。 但如果你觉得Spark没有利用所有资源,你可以:
a)如果每个单独的计算花费的时间少于几秒,则任务调度开销与任务执行时间相当,因此可以通过并行运行少量任务来获得提升。
b)计算需要大量时间,但资源仍然未得到充分利用。那么很可能你应该增加数据集的分区数。3)如果你最终决定并行运行几个任务,可以通过这种方式实现:
yarn run encore dev