输入:
我有两个数据集:
samples_1
数据集,其中包含以下列:timestamp, id, x, y
和500M记录。samples_2
数据集,其列与sample_1
相同,并有5000万条记录。注释:
timestamp
和id
构成了
每条记录,即timestamp
和id
都可以重复。id
无法在另一数据集中复制。不过,timestamp
可以在两个数据集中重复。问题:
我想做的是:对于(timestamp_1, id_1)
中的每个sample_1
元组,我需要从(timestamp_2, id_2, x_2, y_2)
中找到所有sample_2
,其中timestamp_1
等于timestamp_2
。
我尝试过的内容:
samples_2
.withColumn("combined", struct("id", "x", "y"))
.groupBy("timestamp")
.agg(collect_list("combined").as("combined_list"))
.join(samples_2, Seq("timestamp"), "rightouter")
.map {
case Row(timestamp: String, samples: mutable.WrappedArray[GenericRowWithSchema], id_1: String, x_1: Float, y_1: Float) =>
val overlappingSamples = samples.map {case Row(id_2: String, x_2: Float, y_2: Float) => (id_2, x_2, y_2)}
if(overlappingSamples.nonEmpty) {
val stringifiedSamples = overlappingSamples.map(x => s"${x._1}:${x._2}:${x._3}")
(timestamp, id_1, stringifiedSamples.mkString("&"))
} else {
(timestamp, id_1,"", "")
}
case Row(timestamp: String, _, id_1: String, x_1: Float, y_1: Float) => // no overlapping samples
(timestamp, id_1, "", "")
}
.write
.csv(outputPath)
我已经尝试了这段代码(使用较小的数据集),并且给出了我想要的结果。这里的问题是,当我对较大的数据集运行它时,它变得非常慢。我读到我需要通过--conf spark.sql.shuffle.partitions=5000
配置分区数,但这并不能解决问题。
答案 0 :(得分:0)
我在上面的查询中看到的问题是相互绑定的混洗操作太多。我没有检查联接的实际逻辑,但是spark中有一个常见问题需要处理。
我认为,当执行DAG在SPARK中变长时,它几乎不脆弱。原因是第一阶段的任何失败都需要重新计算整个DAG。
我采取的策略是通过保留每次联接的结果来打破多个较小DAG中的DAG或宗族。
val result = datasetA.join(datasetB).persist()
result.count // forces the materialization
// use the result variable in other join
在这里,计数是强制性的,就像其他操作一样,持久存储是懒惰的,需要明确的操作(计数)来强制结果的加入和实现。
您可以为您的工作尝试相同的方法并检查性能。