Spark SQL执行的是笛卡尔积连接而非内部连接

13

在先进行一些计算之后,我正在尝试将两个数据帧彼此连接起来。命令很简单:

employee.join(employer, employee("id") === employer("id"))

然而,这个连接似乎执行笛卡尔积连接,完全忽略了我的 === 语句。有人知道为什么会出现这种情况吗?


欢迎来到 SO NNamed。如果您需要帮助,请给我们一个机会 :) 开始的好地方是提供最小、完整和可验证的示例 - zero323
1个回答

36

我认为我曾经遇到过同样的问题。请检查是否有警告:

Constructing trivially true equals predicate [..]
创建联接操作后,如果需要的话,只需给员工或雇主数据框中的一个列设置别名,例如:

like this:

创建联接操作后,若需要,则可对员工或雇主 DataFrame 中的某一列进行别名设置,例如:

like this:

employee.select(<columns you want>, employee("id").as("id_e"))

然后在employee("id_e") === employer("id")上执行连接操作。

说明。 看一下这个操作流程:

enter image description here

如果您直接使用DataFrame A计算DataFrame B并在来自DataFrame A的列Id上将它们连接在一起,您将无法执行所需的连接。 DataFrameB中的ID列实际上是来自DataFrameA的完全相同的列,因此Spark将仅断言该列与其本身相等,因此谓词显然为真。 为了避免这种情况,您必须对其中一个列进行别名处理,以便它们在Spark中显示为“不同”的列。目前只有警告消息以这种方式实现:

    def === (other: Any): Column = {
    val right = lit(other).expr
    if (this.expr == right) {
      logWarning(
        s"Constructing trivially true equals predicate, '${this.expr} = $right'. " +
          "Perhaps you need to use aliases.")
    }
    EqualTo(expr, right)
  }

对我来说,这并不是一个非常好的解决方案(很容易错过警告信息),希望它能得到改善。

不过你很幸运能看到这个警告消息,它不久前才被添加。 ;)


1
我在整个周末都在苦苦挣扎,试图解决1.5.2中的连接问题——这是其中之一,您的答案节省了很多沮丧。谢谢! - Pyrce
直到我开始深入研究Spark代码,才摆脱了同样的挫败感 ;)。 - TheMP
直到今天(2020)为止,这个问题仍然没有被解决。我也遇到了同样的问题。感谢Niemand,节省了我很多时间。 - Abira
2023年:这种行为仍然存在,我花了3天时间来修复它,直到我来到这里! - Dima Naychuk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接