识别一个数据框列中存在但不存在于另一数据框列中的记录

时间:2019-05-01 20:32:47

标签: scala apache-spark dataframe apache-spark-sql

我试图选择foo中存在但bar中不存在的所有元素。我正在使用以下代码:

foo.repartition(1)
foo.cache()
bar.repartition(1)
bar.cache()
foo.select("col_1").except(bar.select("col_1"))

是否有更好或更快速的方法?在群集上运行时,目前耗时超过15分钟。

其他信息: foo将包含大约100-1000个元素。酒吧将拥有4000万以上的元素。 foo是一个数据框架,由使用Spark SQL从配置单元表(50列)中读取的数据组成。 bar是一个数据帧,包含使用KuduContext从kudu表(250列)中读取的数据。

在带有Scala 2.11.8的CDH 5.15.x上使用Spark 2.2。

1 个答案:

答案 0 :(得分:1)

如@Tzach所建议的那样,最好避免使用bar.repartition(1)bar.cache(),因为bar数据集似乎太大而无法容纳在内存中。您可以将缓存用于小型数据集,甚至更好地尝试将其广播给每个执行者。另外,如果您知道大数据集的大小,则可以使用partition_num = total_size / 500MB计算分区号,每个分区的理想大小为250-500 MB,因此,如果您的数据为10GB,则应为10GB / 500MB = 20个分区。

这是上述更改后的代码:

foo.cache() //feel free to cache the small dataset
bar.repartition(partitions_num) //this is optional

foo.select("col_1").except(bar.select("col_1"))

此外,您可以尝试使用left_anti连接,如下所示,并比较它们的性能:

foo.join(bar, foo("col_1") === bar("col_1"), "left_anti").show

这将排除bar中存在 col_1 的foo中的所有记录。

如果您的需求需要相反的名称,即排除foo中存在的bar中的记录,那么通过广播小数据集foo(如下一个代码段所示),您的程序可能会更加高效:

import org.apache.spark.sql.functions.broadcast

bar.join(broadcast(foo), bar("col1") === foo("col1"), "left_anti").show

祝你好运!