加入Spark后有效地统计记录

时间:2020-10-02 18:49:56

标签: scala apache-spark dataset

这就是我在做什么。我需要获取一个数据集而不是其他数据集中存在的记录数,然后再次与第三个数据集结合以获取其他一些列。

val tooCompare = dw
        .select(
          "loc",
          "id",
          "country",
          "region"
        ).dropDuplicates()

val previous = dw
        .select(
          "loc",
          "id",
          "country",
          "region"
        ).dropDuplicates()

val delta = tooCompare.exceptAll(previous).cache()
 
val records = delta
        .join(
          dw,//another dataset
          delta
            .col("loc").equalTo(dw.col("loc"))
            .and(delta.col("id").equalTo(dw.col("id")))
            .and(delta.col("country").equalTo(dw.col("country")))
            .and(delta.col("region").equalTo(dw.col("region")))
        )
        .drop(delta.col("loc"))
        .drop(delta.col("id"))
        .drop(delta.col("country"))
        .drop(delta.col("region"))
        .cache()
    }

 val recordsToSend = records.cache()
 val count = recordsToSend.select("loc").distinct().count()

有没有更有效的方法来做到这一点? 我是Spark的新手。我很确定我在这里错过了一些东西

2 个答案:

答案 0 :(得分:0)

我建议使用SQL使其更具可读性。

首先,创建相关数据帧的临时视图。不确切知道您拥有哪些数据帧,类似

dfToCompare.createOrReplaceTempView("toCompare")
previousDf.createOrReplaceTempView("previous")
anotherDataSet.createOrReplaceTempView("another")

然后,您可以在一条SQL语句中继续执行所有操作

val records = spark.sql("""select loc, id, country,region
              from toCompare c
              inner join another a
               on a.loc = c.loc  
                and a.id = p.id
                and a.country = c.country
                and a.region = c.region
             where not exists (select null
                                from previous p
                                where p.loc = c.loc  
                                 and p.id = p.id
                                 and p.country = c.country
                                 and p.region = c.region""")

然后您可以像以前一样进行操作...

val recordsToSend = records.cache()
val count = recordsToSend.select("loc").distinct().count()

答案 1 :(得分:0)

我认为您粘贴为tooCompare的代码中可能存在一些错误,并且以前的代码是相同的,+第三个数据集联接引用deAnon但表上的dw...。

对于此示例答案,假设您的当前表称为“当前”,上一个表称为“上一个”,第三个表为“额外”。然后:

val delta = current.join(
              previous, 
              Seq("loc","id","country","region"), 
              "leftanti"
            ).select("loc","id","country","region").distinct

val recordsToSend = delta
                    .join(
                      extra,
                      Seq("loc", "id", "country", "region")
                    )

val count = recordsToSend.select("loc").distinct().count()

这可能会更有效,但是我很感谢您评论它是否确实有效!

顺便说一句:请注意,我使用Seq [String]作为连接参数(这要求列名称在两个表上都相同,并且不会产生列的两个副本)。但是,原始的连接逻辑可以更简洁地编写,如下所示(使用我的命名约定):

val recordsToSend = delta
                    .join(
                      extra,
                      delta("loc") === extra("loc")
                        && delta("id") === extra("id")
                        && delta("country") === extra("country")
                        && delta("region") === extra("region")
                    )
                    .drop(delta("loc"))
                    .drop(delta("id"))
                    .drop(delta("country"))
                    .drop(delta("region"))

更好的做法是编写一个drop函数,该函数可以让您提供不止一列,但现在我真的不在讨论主题了;-)

相关问题