spark - scala - 使用覆盖模式

时间:2017-09-28 16:52:25

标签: scala apache-spark

我想知道这里究竟是什么“覆盖”。假设我在表“tb1”中有一个包含以下记录的表(抱歉表示表示不好)

驱动程序vin make model

martin abc ford escape
john abd toyota camry
amy abe chevrolet malibu
carlos abf honda civic

现在我有以下数据框(mydf)具有相同的列,但具有以下行/数据

martin abf toyota corolla
carlos abg nissan versa

使用覆盖模式将上述数据帧保存到“tb1”后,数据帧是否会完全删除“tb1”的内容并写入mydf的数据(上述两条记录)?

但是,我希望覆盖模式仅覆盖列“driver”具有相同值的那些行。在这种情况下,在“tb1”中有4条记录,mydf只会覆盖2条以上的记录,结果表如下 -

驱动程序vin make model

martin abf toyota corolla
john abd toyota camry
amy abe chevrolet malibu
carlos abg nissan versa

我可以使用覆盖模式实现此功能吗?

mydf.write.mode(SaveMode.Overwrite).saveAsTable("tb1")

2 个答案:

答案 0 :(得分:7)

您的意思是在主键上合并2个数据帧。您希望合并两个数据框并将旧行替换为新行,并附加额外的行(如果存在)。

这不能通过SaveMode.Overwrite或SaveMode.append来实现。

为此,您需要在主键上实现2个数据帧的合并功能。

像这样的东西

 parentDF = // actual dataframe
 deltaDF = // new delta to be merged


 val updateDF = spark.sql("select parentDF.* from parentDF join deltaDF on parentDF.id = deltaDF.id")
 val totalDF = parentDF.except(updateDF).union(deltaDF)
 totalDF.write.mode(SaveMode.Overwrite).saveAsTable("tb1")

答案 1 :(得分:3)

回答你的问题:

  

我可以使用覆盖模式实现此功能吗?

不,你不能。

Overwrite的功能实际上是,删除所有要填充的表并再次创建它,但现在使用你告诉它的新DataFrame。

要获得所需的结果,您可以执行以下操作:

  • 将表格信息保存为“更新”到新的DataFrame中:

    val dfTable = hiveContext.read.table(“table_tb1”)

  • 在要更新的表的DF(dfTable)之间执行左连接,并且 DF(mydf)带有你的新信息,穿过你的“PK”,那个 在您的情况下,将是 驱动程序 列。

在同一句子中,您过滤 mydf(“driver”)为空的记录,这些记录是不匹配且没有更新的记录对于这些。

val newDf = dfTable.join(mydf, dfTable("driver") === mydf("driver"), "leftouter" ).filter(mydf("driver").isNull)
  • 之后,截断表 tb1 并插入两个DataFrame: newDF mydf DataFrames:

|

dfArchivo.write.mode(SaveMode.Append).insertInto("table_tb1")  /** Info with no changes */
mydf.write.mode(SaveMode.Append).insertInto("table_tb1") /** Info updated */

通过这种方式,您可以获得所需的结果。

问候。