Spark报错:Detected cartesian product for LEFT OUTER join between logical plans

本文介绍了在遇到Spark报错'Detected cartesian product for LEFT OUTER join'时的解决方法,强调首先检查SQL语句是否确实需要笛卡尔查询。提供了两种解决方案:为表名添加别名和将DataFrame注册为表后使用SQL查询。讨论了Spark SQL的局限性,并邀请读者分享更好的处理方式。

[Spark报错]:Detected cartesian product for LEFT OUTER join between logical plans

FBI warning:xian si kao yao bu yao di ka er cha xun, If true Then return
注意:先思考一下自己sql语句是不是真的需要笛卡尔查询,如果是的话,本文跳过

开门见山

测试程序:

import java.util

import org.apache.spark.sql.{DataFrame, Row, SparkSession}
import org.apache.spark.sql.types.{IntegerType, StringType, StructField, StructType}

import scala.collection.JavaConverters._

object SparkTestJoin {
  def main(args: Array[String]): Unit = {
    val spark: SparkSession = SparkSession.builder().master("local[*]").getOrCreate()

    val java: util.List[Row] = List[Row](
      Row(1, "zhangsan", 86),
      Row(2, "lisi", 97),
      Row(3, "wangwu", 100)
    ).asJava

    val struct: StructType = StructType(Seq(
      StructField("id", IntegerType, true),
      StructField("name", StringType, true),
      StructField("score", IntegerType, true)
    ))
    
    val df1: DataFrame = spark.createDataFrame(java, struct)
    val df2:DataFrame= df1              //注意这里!
    
    df1.join(df2,df1("id")<=>df2("id"),"left").show(false)
    spark.stop()
  }
}

报错如下:
在这里插入图片描述
  看到了Exception in thread "main" org.apache.spark.sql.AnalysisException: Detected cartesian product for LEFT OUTER join between logical plans
对于这个错误,我搜索了一下,发现很多文章里面都是说要打开spark笛卡尔join的开关,就是进行如下操作啦:

"spark.sql.crossJoin.enabled", "true"  //可以写到config里面

我照着做了,然后我发现,程序虽然不报错了,但是执行起来很慢。不想等它执行完了。
我思考了一下,我的计算逻辑中,不应该存在笛卡尔交集的join操作,然后又经过一段时间的搜索。我发现有一个stackOverFlow里面提到了,spark将这个操作视作笛卡尔操作的原因:join的两张表具有相同的血缘关系原文章
在下面的很小一部分提到了这个问题的原因(仅供参考)


解决方案

在原文中提到了一种给待进行join操作的两边的DataFrame添加一个别名。这个操作,迷惑到我了。我试不出来。
既然是因为df1df2具有相同的血缘关系的话,那么是不是意味着我将这个血缘关系破坏掉就可以将这个问题解决了。

下面是我的解决方案:
解决方案1:

在这里插入图片描述
这样做的话,程序可以正常地跑通了。没有报错误。

解决方案2:

df1df2都注册成表,然后用SparkSQL 操作,像这样
在这里插入图片描述

结束语

我感觉SparkDSL的风格的SQL查询语言,比起SparkSQL语句还是有一些局限的,有些操作利用SparkDSL风格的SQL查询的话,非常不方便。。。。

如果看到这篇文章的大佬有什么更好的方法请在下面留言。谢谢。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值