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

  • Post author:
  • Post category:其他




[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

添加一个别名。这个操作,迷惑到我了。我试不出来。

既然是因为

df1



df2

具有相同的血缘关系的话,那么是不是意味着我将这个

血缘关系破坏掉

就可以将这个问题解决了。



下面是我的解决方案:



解决方案1:

在这里插入图片描述

这样做的话,程序可以正常地跑通了。没有报错误。



解决方案2:



df1



df2

都注册成表,然后用

SparkSQL

操作,像这样

在这里插入图片描述



结束语

我感觉

Spark



DSL

的风格的

SQL

查询语言,比起

SparkSQL

语句还是有一些局限的,有些操作利用

Spark



DSL

风格的

SQL

查询的话,非常不方便。。。。

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



版权声明:本文为OldDirverHelpMe原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。