我看到,如果我的加入条件涉及OR子句,那么与拥有AND子句相比将花费很长时间。我正在加入fullouter。
我的单元测试没有明显的区别,但是当针对大型数据集运行时,它的运行速度非常慢
df1.join(df2, expr("id1 = id2 AND amount1 = amount2"), "fullouter").cache()
以下内容运行很长时间,即慢了10倍左右
df1.join(df2, expr("id1 = id2 OR amount1 = amount2"), "fullouter").cache()
有什么想法吗?
答案 0 :(得分:1)
TL; DR 这两者之间的性能差异是可以预期的。
逻辑连接(AND
)可以表示为基于混洗的操作(排序合并连接或混洗哈希连接)-这意味着每条记录仅需传输到一个子分区,基于联接条件中包含的所有表达式的哈希值。
在最坏的情况下(所有联接键都是恒定的,并且两个数据集之间都匹配),它可以进行N * M比较,将所有记录改组到一个分区中,但是具有真实数据的典型情况应该更多效率高,可以进行大约N + M的比较。
逻辑析取(OR
)不能表示为简单的基于随机播放的操作,因为可以将散列到不同存储桶的记录进行匹配*。因此,Spark使用笛卡尔积,然后进行选择,始终将每个记录多次传输并进行N * M比较。