Apache spark 对delta lake具有多个相同密钥的流写入

Apache spark 对delta lake具有多个相同密钥的流写入,apache-spark,spark-streaming,delta-lake,Apache Spark,Spark Streaming,Delta Lake,我正在通过spark结构化流向delta lake写入流。每个流式批处理包含键值,也包含时间戳作为一列。delta lake不支持在源蒸汽批处理中使用多个相同的键进行更新,所以我只想使用具有最新时间戳的记录来更新delta lake。我该怎么做 这是我正在尝试的代码片段: def upsertToDelta(microBatchOutputDF: DataFrame, batchId: Long) { println(s"Executing batch $batchId ...") m

我正在通过spark结构化流向delta lake写入流。每个流式批处理包含键值,也包含时间戳作为一列。delta lake不支持在源蒸汽批处理中使用多个相同的键进行更新,所以我只想使用具有最新时间戳的记录来更新delta lake。我该怎么做

这是我正在尝试的代码片段:

def upsertToDelta(microBatchOutputDF: DataFrame, batchId: Long) {

  println(s"Executing batch $batchId ...")
  microBatchOutputDF.show()

  deltaTable.as("t")
    .merge(
      microBatchOutputDF.as("s"),
      "s.key = t.key")
    .whenMatched().updateAll()
    .whenNotMatched().insertAll()
    .execute()
}

提前感谢。

您可以从microBatchOutputDF数据帧中删除具有较旧时间戳的记录,并且只保留具有给定密钥的最新时间戳的记录

您可以使用spark的“reduceByKey”操作并实现如下自定义reduce功能

def getLatestEvents(input: DataFrame) : RDD[Row] = {
input.rdd.map(x => (x.getAs[String]("key"), x)).reduceByKey(reduceFun).map(_._2) }


def reduceFun(x: Row, y: Row) : Row = {
if (x.getAs[Timestamp]("timestamp").getTime > y.getAs[Timestamp]("timestamp").getTime) x else y }
假定键的类型为字符串&时间戳的类型为时间戳。并为您的流媒体批次“microBatchOutputDF”调用getLatestEvents。它忽略较旧的时间戳事件&只保留最新的事件

val latestRecordsDF = spark.createDataFrame(getLatestEvents(microBatchOutputDF), <schema of DF>)

然后在“latestRecordsDF”之上调用deltalake合并操作,在微批次的流媒体中,您可能会获得一个给定密钥的多个记录。为了用目标表更新它,您必须在微批次中找出密钥的最新记录。在本例中,您可以使用max of timestamp列和value列查找最新记录,并将其用于合并操作


有关查找给定密钥的最新记录的更多详细信息,请参阅此部分。

将使用相同的方法。谢谢你的回复。