将更新保存到数据框中,然后在spark scala中重复使用保存的数据框

时间:2018-07-17 12:20:12

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

我有多个传入文件,我必须将每个传入文件与源文件进行比较,然后合并并用新行替换旧行,并在源文件中添加多余的行(如果有的话)。后记我必须使用更新的源文件并与另一个传入文件进行比较,对其进行更新,然后继续进行。

到目前为止,我已经为每个文件创建了数据框,并使用join进行了比较和合并。我想将所有更新保存在源文件中,然后再次使用更新的源文件来比较和更新传入的文件。

          val merge = df.union(dfSource.join(df, Seq( "EmployeeID" ),joinType= "left_anti").orderBy("EmployeeID") )

          merge.write.mode ("append").format("text").insertInto("dfSource")
              merge.show()

我尝试过这种方式,但是它不会更新dfSource数据帧。有人可以帮忙吗。

谢谢

1 个答案:

答案 0 :(得分:0)

不可能这样。需要使用表,然后将其保存到文件中作为流程的最后一部分。

建议您按照以下方式调整方法-允许并行加载,但我真的怀疑这样做没有好处。

  1. 按传送顺序装入所有文件,装入的每个记录都用文件序列号和记录类型中的时间戳或某些排序序列进行标记。例如。例如,按顺序位于位置2的文件X获取以seqnum = 2加载的记录。如果在SPARK域中执行全部操作,则可以对正在处理的文件使用DF方法,并将其追加到Impala / Hive KUDU表中。

    < / li>
  2. 对于同一文件中的记录,如果同一文件中可以存在相同的键,则应用monotonically_increasing_id()在文件中进行排序。参见DataFrame-ified zipWithIndex。或通过转换通过RDD通过zipWithIndex返回DF。

  3. 然后发出select语句以获取具有最大值时间戳记的键值,每个键seq_num。例如。如果在当前运行的3个记录中,例如对于key = 1,则仅需要处理一个-大概是值最高的一个。

  4. 另存为新文件。

  5. 相应地处理此新文件。

  6. OR:

    绕过步骤3,以asc顺序读取并相应地处理数据。

评论: 通常,我通过从文件名中提取时间戳来设置分区键,并通过LOAD将该数据加载到HIVE / IMPALA。需要一些LINUX脚本/处理。这是一个风格问题,不应该是真正的大数据瓶颈。

以下是带有模拟输入的代码段,说明了如何进行某些方面操作以允许针对UPSerts的键进行MAX选择。您需要添加的Operation DEL,ALT。尽管我认为您实际上可以根据我所看到的做到这一点:

import org.apache.spark.sql.functions._
import spark.implicits._
import org.apache.spark.sql._
import org.apache.spark.sql.types._ 

def dfSchema(columnNames: List[String]): StructType =
  StructType(
    Seq(
      StructField(name = "key", dataType = StringType, nullable = false),
      StructField(name = "file", dataType = StringType, nullable = false),
      StructField(name = "ts", dataType = StringType, nullable = false),
      StructField(name = "val", dataType = StringType, nullable = false),
      StructField(name = "seq_val", dataType = LongType, nullable = false)      
    )
  )

val newSchema = dfSchema(List("key", "file", "ts", "val", "seq_val"))

val df1 = Seq(
   ("A","F1", "ts1","1"),
   ("B","F1", "ts1","10"),
   ("A","F1", "ts2","2"),
   ("C","F2", "ts3","8"),
   ("A","F2", "ts3","3"),
   ("A","F0", "ts0","0")  
 ).toDF("key", "file", "ts","val")

val rddWithId = df1.sort($"key", $"ts".asc).rdd.zipWithIndex
val dfZippedWithId =  spark.createDataFrame(rddWithId.map{ case (row, index) => Row.fromSeq(row.toSeq ++ Array(index))}, newSchema)

dfZippedWithId.show

返回:

+---+----+---+---+-------+
|key|file| ts|val|seq_val|
+---+----+---+---+-------+
|  A|  F0|ts0|  0|      0|
|  A|  F1|ts1|  1|      1|
|  A|  F1|ts2|  2|      2|
|  A|  F2|ts3|  3|      3|
|  B|  F1|ts1| 10|      4|
|  C|  F2|ts3|  8|      5|
+---+----+---+---+-------+

准备进行后续处理。