[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
查询的话,非常不方便。。。。
如果看到这篇文章的大佬有什么更好的方法请在下面留言。谢谢。