Spark - 如果已存在,则更新记录(在镶木地板文件中)

时间:2016-11-25 10:37:50

标签: java apache-spark spark-dataframe parquet

我正在编写一个Spark作业来读取json文件中的数据并将其写入镶木地板文件,下面是示例代码:

    DataFrame dataFrame = new DataFrameReader(sqlContext).json(textFile);
    dataFrame = dataFrame.withColumn("year", year(to_date(unix_timestamp(dataFrame.col("date"), "YYYY-MM-dd'T'hh:mm:ss.SSS").cast("timestamp"))));
    dataFrame = dataFrame.withColumn("month", month(to_date(unix_timestamp(dataFrame.col("date"), "YYYY-MM-dd'T'hh:mm:ss.SSS").cast("timestamp"))));
    dataFrame.write().mode(SaveMode.Append).partitionBy("year", "month").parquet("<some_path>");

Json文件由许多json记录组成,我希望记录在镶木地板中更新(如果它已经存在)。我尝试过Append模式,但似乎是在文件级别而不是记录级别上工作(即如果文件已存在,则最后写入)。因此,为同一文件运行此作业会复制记录。

我们有什么方法可以指定数据帧行id作为唯一键,并且如果已经存在,请求spark更新记录?所有保存模式似乎都在检查文件而不是记录。

2 个答案:

答案 0 :(得分:1)

Parquet是一种文件格式而不是数据库,为了通过id实现更新,您需要读取文件,更新内存中的值,而不是将数据重新写入新文件(或覆盖现有文件)。

如果这是一个经常发生的用例,那么使用数据库可能会更好。

答案 1 :(得分:0)

您可以查看Apache ORC文件格式,请参阅:

https://orc.apache.org/docs/acid.html

根据您的用例,如果您希望保持在HDFS之上,请使用HBase。

但请记住,HDFS是一次写入文件系统,如果这不符合您的需要,请选择其他内容(也许是elasticsearch,mongodb)。

否则,在HDFS中,您必须每次都创建新文件,您必须设置增量过程来构建“delta”文件,然后合并OLD + DELTA = NEW_DATA。