数据帧全外连接中的 OR 条件降低了性能火花/scala

Nic*_*k01 3 scala join apache-spark apache-spark-sql

我看到如果我的连接条件涉及 OR 子句,则与使用 AND 子句相比,它需要很长时间。我正在做fullouter join。

我的单元测试没有显示出重大差异,但是当针对大型数据集运行时,它运行速度非常慢

df1.join(df2, expr("id1 = id2 AND amount1 = amount2"), "fullouter").cache()
Run Code Online (Sandbox Code Playgroud)

以下运行很长时间,即速度慢约 10 倍

df1.join(df2, expr("id1 = id2 OR amount1 = amount2"), "fullouter").cache()
Run Code Online (Sandbox Code Playgroud)

有什么想法吗?

zer*_*323 5

TL;DR这两者之间的性能差异是预期的。

  • 逻辑连接 ( AND) 可以表示为基于混洗的操作(排序合并连接或混洗散列连接)——这意味着每条记录必须仅传输到一个子分区,基于连接条件中包含的所有表达式的散列.

    虽然在最坏的情况下(所有连接键都是恒定的并且在两个数据集之间匹配),它可以将所有记录打乱到单个分区进行 N*M 比较,典型的场景,使用真实数据,应该更有效率,使得大约 N + M 次比较。

  • 逻辑析取 ( OR) 不能表示为简单的基于 shuffle 的操作,因为可以匹配散列到不同桶的记录*。因此 Spark 使用笛卡尔积,然后选择总是多次传输每个记录并进行 N*M 比较。