Scala 火花检测笛卡尔积,尽管连接条件是非平凡的
我使用的是Spark 2.3.0,我有两个数据帧 第一个是df1,其模式为:Scala 火花检测笛卡尔积,尽管连接条件是非平凡的,scala,apache-spark,apache-spark-sql,Scala,Apache Spark,Apache Spark Sql,我使用的是Spark 2.3.0,我有两个数据帧 第一个是df1,其模式为: root |-- time: long (nullable = true) |-- channel: string (nullable = false) root |-- pprChannel: string (nullable = true) |-- ppr: integer (nullable = false) 第二个是df2,其模式为: root |-- time: long (nullable =
root
|-- time: long (nullable = true)
|-- channel: string (nullable = false)
root
|-- pprChannel: string (nullable = true)
|-- ppr: integer (nullable = false)
第二个是df2,其模式为:
root
|-- time: long (nullable = true)
|-- channel: string (nullable = false)
root
|-- pprChannel: string (nullable = true)
|-- ppr: integer (nullable = false)
我现在试着做:
spark.sql("select a.channel as channel, a.time as time, b.ppr as ppr from df1 a inner join df2 b on a.channel = b.pprChannel")
但我得到了逻辑计划之间内部联接的检测笛卡尔积
当我尝试用sc.parallelize
和简单的seq在Spark Shell上重新创建时,它是有效的
这里可能出了什么问题
改善效果追踪
下面是我使用df1时得到的结果。join(df2,'channel=='pprChannel,“inner”)。explain(true)
:
是的,df1
是一个相当复杂的计算结果,这就是它如此庞大的原因df2
是一个非常小的DF,它总是来自Map
,最多有50到100个条目通过sc触发。parallelize
。因此,我可以使用crossJoin
和where
作为解决方法。但我想理解为什么Spark认为它是笛卡尔积
后续行动2
我现在使用一种不同的方法。由于第一个DF是一个庞大的DF,它是复杂计算的结果,而第二个DF总是源自一个小地图,因此我将算法更改为使用普通的map
操作来实现它:
val bDF2Data = sc.broadcast(df2Data)
val res =
df1.
as[(Long, String)].
mapPartitions { iter =>
val df2Data = bDF2Data.value
iter.
flatMap {
case (time, channel) =>
df2Data.get(channel).map(ppr => (time, channel, ppr))
}
}.
toDF("time", "channel", "ppr").
// More operations ...
也许这会有所帮助:不幸的是,我无法从解释中找出问题所在。我添加了explain
的输出作为编辑。