我想知道我们是否可以在两个数据帧的联接操作期间强制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()
进行了检查)。我找不到任何在线资源来解释如何做到这一点。
谢谢!
答案 0 :(得分:1)
但是,从理论上讲,可以使用say(groupid,other_column_a)进行联接
那是不正确的。要执行联接,Spark必须将所有带有groupid
的记录移动到单个分区,因此在以下情况下可以使用(groupid,other_column_a)
(groupid, other_column_a)
,其中有连接键。other_column_a
和group_id
之间存在功能关系。第一个条件显然不满足,因为您仅通过groupid
参加,第二个条件不能解决问题,因为分配会相同或更差。
对于偏斜联接,还有其他可能的解决方案,例如对偏斜组的单独处理或迭代广播联接(请参见Spark final task takes 100x times longer than first 199, how to improve中的答案和评论)。
答案 1 :(得分:1)
如果您要加入某个整数列,则可以对数据帧进行分区,并取模数..即您想要多少个分区..这样,共享一些公共哈希值的id将是分组到一个分区中。然后您可以通过分解多个联接来执行联接。以循环方式依次联接每个分区。我已经详细解释了这种情况。Efficient pyspark join