Spark多个数据集联接性能问题

时间:2018-12-13 07:56:04

标签: apache-spark

所以目前我有一张这样的桌子

userID, day, itemID
1,       1,   A
1,       1,   B
2,       2,   A
2,       2,   C
...

,这意味着用户1在第1天购买了商品A,依此类推。我首先需要提取具有相同itemID的不同数据集,例如以下

userID, day, itemID
1,       1,   A
2,       2,   A
...

userID, day, itemID
1,       1,   B
...

然后,每个数据集将产生遵循相同格式的输出,例如:

userID result
1,      x
...

然后,我将外部连接所有这些结果。 如您所见,我遇到的问题是性能,结果数据集的数量取决于我拥有多少个不同的itemID,数量为6时效果很好,整个过程在2分钟内完成,但数量为45时,需要30分钟,我还在等待。该程序只是停留在ContextCleaner:54上,运行非常缓慢。

我已经尝试过在具有超过100G RAM的云上运行此程序,我很好奇为什么连接大量表太慢了。

更新: 最终我出现了stackoverflow错误... 我看了一下执行查询,它很长,我想做一个for循环来连接45个以上的表不是一个好主意。

仅需使用代码示例进一步说明问题

List<String> itemIDs = ...;
Dataset<Row> ret = null;
for (String itemID : itemIDs) {
    Dataset<Row> df = mainDF.filter(col("itemID").equalTo(itemID));
    Dataset<Row> result = someFunction(df);
  if (ret == null) ret = combined;
  else {
    combined = combined.withColumnRenamed("userID", "userID_right");
    ret = ret.join(
            combined,
            ret.col("userID").equalTo(combined.col("userID_right")),
            "full_outer")
            .withColumn("user_id",
                    coalesce(col("userID"), col("userID_right")))
           .drop("userID", "userID_right")
            .withColumnRenamed("user_id", "userID");
  }
}

最终,当我在45次迭代之后尝试执行ret.show()时,我的机器几乎就死了。

另一个更新: 因此,我想出了如何加快处理速度,将要连接的数据集进行了一个漫长而复杂的转换,它继承了默认的分区数200,显然,当您多次连接具有大量分区的表时,它几乎就死了,但是如果您可以将数据集重新分区为较小的大小(以我为例,则为8),则它的速度要快得多,并在3分钟内完成。干杯。 我认为大部分原因是由于我对RDD的运作方式缺乏深入的了解。

最终更新: 因此,基本上不要将50个或100个以上的小表连接在一起,我认为这不是火花的工作原理,而是可以将其转换为纯Java对象并在其中进行操作。

另一件事是,这种累积操作将使物理计划成倍增长,并且您可以尝试检查点来简化这种情况,但是,当您想要几百个相对较小的表时,它并不会更快一起加入。

0 个答案:

没有答案