我有2个数据框:
df_1
拥有约5亿条记录和约100列df_2
拥有约5000万条记录和4列我需要将df_1
与df_2
的联接留在其中两列完全匹配,而第三列最佳匹配。最好的匹配,我的意思是从左到右有一个多对多的关系,但是我只想在长度方面在右侧得到最好的匹配。
例如
# df_1
col1 col2 col3
---------------------------
a b abcde
# df_2
col1 col2 col3 col4
-------------------------------
a b a 90
a b ab 100
a b abc 150
a c abc 90
因此,当我完全匹配col1
和col2
并与包含的字符串的最佳匹配项的col3
完全匹配时,联接的期望结果是:
col1 col2 col3 col4
-------------------------------
a b abcde 150
有些要害我的地方:
col3
的长度通常在10到15个字符之间,在右侧可以从1个字符变为9个字符df_1
和df_2
都类似地偏向col3
虽然我能做到这一点,但是却得到了糟糕的表现。
我尝试了以下解决方案,但仍无所获:
df_2
(因为广播太大而无法广播)col1
和col1
上完全连接,并在like
上使用col3
(很糟糕)col3
中df_2
上的值以尝试解决倾斜(改进但仍然很慢)col1
,col2
和col3
的串联连接(其中左侧的串联是一个col3
的子字符串)(改进但仍然很慢)使用spark进行连接的最有效方法是什么?
答案 0 :(得分:0)
一个更好的选择是在加入之前减小数据大小(我们无法消除加入)。我们可以减少如下:
首先,加载数据
scala> import org.apache.spark.sql.expressions.Window
import org.apache.spark.sql.expressions.Window
scala> import org.apache.spark.sql.functions._
import org.apache.spark.sql.functions._
scala> df1.show
+---+---+-----+
| c1| c2| c3|
+---+---+-----+
| a| b|abcde|
| c| d| fd|
+---+---+-----+
scala> df2.show
+---+---+----+---+
| c1| c2| c3| c4|
+---+---+----+---+
| a| b| a| 90|
| a| b| abd|100|
| a| b|abcd|150|
| c| d|wewe| 79|
+---+---+----+---+
现在,我们需要使用窗口函数并找出两列的最大值
,以在连接之前减小df2的大小(这将减少连接所需的时间,因为数据大小较小)。scala> df2.withColumn("len", length($"c3")).withColumn("res", row_number().over(wind1)).filter($"res" === 1).withColumn("res2", row_number().over(wind2)).filter($"res2"=== 1).select("c1", "c2", "c3", "c4").show()
+---+---+----+---+
| c1| c2| c3| c4|
+---+---+----+---+
| c| d|wewe| 79|
| a| b|abcd|150|
+---+---+----+---+
可尝试的东西:
1>您可以加入这个简化的数据框并应用您正在使用的逻辑
2>尝试进行并集df1.withColumn("c4", lit(0)).union(df2)
,然后应用上述逻辑。
希望这会有所帮助