【问题标题】:How to get all different records in two different spark rdd如何在两个不同的spark rdd中获取所有不同的记录
【发布时间】:2020-10-03 17:56:37
【问题描述】:

对 spark 和 RDD 来说非常新,所以我希望我能很好地解释我所追求的东西,以便有人理解和帮助:)

我有两组非常大的数据,比如说 300 万行和 50 列存储在 hadoop hdfs 中。 我想要做的是将这两个读入 RDD,以便它使用并行性 & 我想返回包含所有不匹配的记录(来自任一 RDD)的第三个 RDD。

希望下面有助于显示我想要做什么... 只是试图以最快最有效的方式找到所有不同的记录......

数据的顺序不一定相同 - rdd1 的第 1 行可能是 rdd2 的第 4 行。

提前非常感谢!!

所以...这似乎在做我想做的事,但似乎很容易正确...

%spark

import org.apache.spark.sql.DataFrame
import org.apache.spark.rdd.RDD
import sqlContext.implicits._
import org.apache.spark.sql._

//create the tab1 rdd.
val rdd1 = sqlContext.sql("select * FROM table1").withColumn("source",lit("tab1"))

//create the tab2 rdd.
val rdd2 = sqlContext.sql("select * FROM table2").withColumn("source",lit("tab2"))

//create the rdd of all misaligned records between table1 and the table2.
val rdd3 = rdd1.except(rdd2).unionAll(rdd2.except(rdd1))

//rdd3.printSchema()    
//val rdd3 = rdd1.except(rdd2)

//drop the temporary table that was used to create a hive compatible table from the last run.
sqlContext.dropTempTable("table3")

//register the new temporary table.
rdd3.toDF().registerTempTable("table3")

//drop the old compare table.
sqlContext.sql("drop table if exists data_base.compare_table")

//create the new version of the s_asset compare table.
sqlContext.sql("create table data_base.compare_table as select * from table3")

这是我到目前为止完成的最后一段代码,它似乎正在完成这项工作 - 不确定完整数据集的性能,让我的手指交叉......

非常感谢所有花时间帮助这个可怜的人 :)

附言如果有人有性能更高的解决方案,我很想听听! 或者如果您可以看到一些问题,这可能意味着它会返回错误的结果。

【问题讨论】:

  • 可以使用rdd.fullOuterJoin。
  • 有什么特别的东西可以让它分布在所有节点上吗?
  • 不是很大恕我直言
  • fullOuterJoin 无法正常工作,您可能需要 df1.leftOuter.df2 union df2.leftOuter.df1 条件
  • 哈哈@thebluephantom - 它实际上比这大得多,只是我没有想到实际的数字:)

标签: scala apache-spark pyspark rdd


【解决方案1】:
  1. 将两个数据框加载为df1,df2
  2. 添加source列,默认值分别为rdd1rdd2
  3. 联合 df1df2
  4. "rowid", "name", "status", "lastupdated" 分组并按集合收集其来源
  5. 过滤所有具有单一来源的行
import org.apache.spark.sql.functions._

object OuterJoin {

  def main(args: Array[String]): Unit = {

    val spark = Constant.getSparkSess

    import spark.implicits._

    val cols = Array("rowid", "name", "status", "lastupdated")

    val df1 = List(
      ("1-za23f0", "product1", "active", "30-12-2019"),
      ("1-za23f1", "product2", "inactive", "31-12-2019"),
      ("1-za23f2", "product3", "inactive", "01-01-2020"),
      ("1-za23f3", "product4", "inactive", "02-01-2020"),
      ("1-za23f4", "product5", "inactive", "03-01-2020"))
      .toDF(cols:_ *)
      .withColumn("source",lit("rdd1"))

    val df2 = List(
      ("1-za23f0", "product1", "active", "30-12-2019"),
      ("1-za23f1", "product2", "active", "31-12-2019"),
      ("1-za23f2", "product3", "active", "01-01-2020"),
      ("1-za23f3", "product1", "inactive", "02-01-2020"),
      ("1-za23f4", "product5", "inactive", "03-01-2020"))
      .toDF(cols:_ *)
        .withColumn("source",lit("rdd2"))

    df1.union(df2)
      .groupBy(cols.map(col):_ *)
      .agg(collect_set("source").as("sources"))
      .filter(size(col("sources")) === 1)
      .withColumn("from_rdd", explode(col("sources") ))
      .drop("sources")
      .show()
  }

}

【讨论】:

  • 谢谢@QuickSilver 我想我已经接近了,但是我收到了联合 :310: 错误:值联合不是 org.apache.spark.sql 的成员。 DataFrame df1.union(df2) 假设这可能是因为我们目前被一些旧版本卡住并且目前无法升级。如果我将其更改为 unionAll,我会得到以下输出: import org.apache.spark.sql.functions._ main: (args: Array[String])Unit 不确定这是否有所不同,但我使用的是 spark 解释器在齐柏林飞艇中。
  • 不 :( sc.version - res7: String = 1.6.3 util.Properties.versionString - res8: String = 版本 2.10.5
  • 您应该能够合并 RDD 并在自定义键上按它们分组,只有代码会有点长@torz
  • 这就是我最初想做的事情,但在尝试做这件事时迷路了,让我看看我是否能找到我在一两个星期前开始快速浏览时开始的事情......
  • 我刚刚添加到我原来的问题中以显示似乎有效的方法,到目前为止我看到的前几个结果都很好。但似乎很容易正确?我错过了什么吗?
【解决方案2】:

您可以将数据读入数据帧而不是 Rdds,然后使用 union 和 group by 来实现结果

【讨论】:

  • 我最初是在想这个,但我认为我在某处读到它没有正确分布在所有节点上......如果是这样,那就太好了,使用 pandas df 会更舒服
  • 确实如此,在后台它只创建 RDD,当我们创建 Dataframe 时,它​​会自动在默认节点/配置上进行颚化
【解决方案3】:

两者都可以与“full_outer”连接,然后应用过滤器,其中字段值在两者中进行比较:

val filterCondition = cols
  .map(c => (col(s"l.$c") =!= col(s"r.$c") || col(s"l.$c").isNull || col(s"r.$c").isNull))
  .reduce((acc, c) => acc || c)

df1.alias("l")
  .join(df2.alias("r"), $"l.rowid" === $"r.rowid", "full_outer")
  .where(filterCondition)

输出:

+--------+--------+--------+-----------+------+--------+--------+--------+-----------+------+
|rowid   |name    |status  |lastupdated|source|rowid   |name    |status  |lastupdated|source|
+--------+--------+--------+-----------+------+--------+--------+--------+-----------+------+
|1-za23f1|product2|inactive|31-12-2019 |rdd1  |1-za23f1|product2|active  |31-12-2019 |rdd2  |
|1-za23f2|product3|inactive|01-01-2020 |rdd1  |1-za23f2|product3|active  |01-01-2020 |rdd2  |
|1-za23f3|product4|inactive|02-01-2020 |rdd1  |1-za23f3|product1|inactive|02-01-2020 |rdd2  |
+--------+--------+--------+-----------+------+--------+--------+--------+-----------+------+

【讨论】:

    猜你喜欢
    • 2020-09-06
    • 1970-01-01
    • 2016-03-23
    • 2018-06-10
    • 2016-12-01
    • 2014-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多