如何通过spark插入HDFS?

时间:2019-01-18 00:04:10

标签: apache-spark apache-spark-sql hdfs bigdata

我在HDFS中对数据进行了分区。在某个时候,我决定对其进行更新。算法为:

  • 从kafka主题中读取新数据。
  • 找出新数据的分区名称。
  • 从具有HDFS中这些名称的分区中加载数据。
  • 将HDFS数据与新数据合并。
  • 覆盖磁盘上已经存在的分区。

问题是,如果新数据具有磁盘上尚不存在的分区,该怎么办。在这种情况下,它们不会被写入。 https://stackoverflow.com/a/49691528/10681828 <-例如,此解决方案不编写新分区。 enter image description here

上图描述了这种情况。让我们将左磁盘视为HDFS中已经存在的分区,并将右磁盘视为我们刚刚从Kafka收到的分区。

右侧磁盘的某些分区将与现有分区相交,而其他分区则不会相交。这段代码:

spark.conf.set("spark.sql.sources.partitionOverwriteMode","dynamic")
dataFrame
    .write
    .mode(SaveMode.Overwrite)
    .partitionBy("date", "key")
    .option("header", "true")
    .format(format)
    .save(path)

无法将图片的蓝色部分写入磁盘。

那么,如何解决此问题?请提供代码。我正在寻找表现出色的人。

不懂的人的例子:

假设我们在HDFS中具有以下数据:

  • PartitionA的数据为“ 1”
  • PartitionB的数据为“ 1”

现在我们收到了这些新数据:

  • PartitionB的数据为“ 2”
  • PartitionC的数据为“ 1”

因此,分区A和B在HDFS中,分区B和C是新分区,并且由于B在HDFS中,因此我们对其进行了更新。而且我想编写C。因此最终结果应如下所示:

  • PartitionA的数据为“ 1”
  • PartitionB的数据为“ 2”
  • PartitionC的数据为“ 1”

但是如果我使用上面的代码,我会得到:

  • PartitionA的数据为“ 1”
  • PartitionB的数据为“ 2”

由于spark 2.3的新功能overwrite dynamic无法创建PartitionC。

更新:事实证明,如果您使用配置单元表,则可以使用。但是,如果您使用的是纯火花,则不会...因此,我猜蜂巢的覆盖和火花的覆盖工作有所不同。

1 个答案:

答案 0 :(得分:1)

最后,我只是决定从HDFS中删除分区的“绿色”子集,而改用SaveMode.Append。我认为这是火花中的错误。