Spark> 2-联接操作期间的自定义分区键

时间:2018-11-29 12:21:23

标签: apache-spark join apache-spark-sql

我想知道我们是否可以在两个数据帧的联接操作期间强制Spark使用自定义分区键。

例如,让我们考虑

df1: DataFrame - [groupid, other_column_a]
df2: DataFrame - [groupid, other_column_b]

如果我跑步

df_join = df1.join(df2, "groupid")

Spark将设置“ groupid”作为分区键,并在每个分区上执行联接。问题是,如果分区太大,这可能会耗尽计算机上的内存。

但是,从理论上讲,可以说(groupid, other_column_a)作为分区键来执行连接(以减小每个分区的大小)。

是否可以使用Spark进行操作?我试着做 预先df1.repartition("group_id","other_column_a"),但这被联接覆盖(我用df_join.explain()进行了检查)。我找不到任何在线资源来解释如何做到这一点。

谢谢!

Visual explanation

2 个答案:

答案 0 :(得分:1)

  

但是,从理论上讲,可以使用say(groupid,other_column_a)进行联接

那是不正确的。要执行联接,Spark必须将所有带有groupid的记录移动到单个分区,因此在以下情况下可以使用(groupid,other_column_a)

  • (groupid, other_column_a),其中有连接键。
  • other_column_agroup_id之间存在功能关系。

第一个条件显然不满足,因为您仅通过groupid参加,第二个条件不能解决问题,因为分配会相同或更差。

对于偏斜联接,还有其他可能的解决方案,例如对偏斜组的单独处理或迭代广播联接(请参见Spark final task takes 100x times longer than first 199, how to improve中的答案和评论)。

答案 1 :(得分:1)

如果您要加入某个整数列,则可以对数据帧进行分区,并取模数..即您想要多少个分区..这样,共享一些公共哈希值的id将是分组到一个分区中。然后您可以通过分解多个联接来执行联接。以循环方式依次联接每个分区。我已经详细解释了这种情况。Efficient pyspark join