[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查询的话,非常不方便。。。。
如果看到这篇文章的大佬有什么更好的方法请在下面留言。谢谢。
本文介绍了在遇到Spark报错'Detected cartesian product for LEFT OUTER join'时的解决方法,强调首先检查SQL语句是否确实需要笛卡尔查询。提供了两种解决方案:为表名添加别名和将DataFrame注册为表后使用SQL查询。讨论了Spark SQL的局限性,并邀请读者分享更好的处理方式。
5909

被折叠的 条评论
为什么被折叠?



