【发布时间】:2019-06-12 06:00:02
【问题描述】:
我在 HDFS 中对数据进行了分区。在某个时候,我决定更新它。算法是:
- 从 kafka 主题中读取新数据。
- 找出新数据的分区名称。
- 从 HDFS 中具有这些名称的分区加载数据。
- 将 HDFS 数据与新数据合并。
- 覆盖磁盘上已有的分区。
问题是,如果新数据具有磁盘上尚不存在的分区怎么办。在这种情况下,它们不会被写入。 https://stackoverflow.com/a/49691528/10681828
上图描述了这种情况。让我们将左侧磁盘视为已经在 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”
- 分区 B 的数据为“1”
现在我们收到了这个新数据:
- 分区 B 有数据“2”
- PartitionC 的数据为“1”
因此,分区 A 和 B 在 HDFS 中,分区 B 和 C 是新分区,由于 B 在 HDFS 中,我们对其进行更新。我想写C。所以最终的结果应该是这样的:
- PartitionA 的数据为“1”
- 分区 B 有数据“2”
- PartitionC 的数据为“1”
但是如果我使用上面的代码,我会得到:
- PartitionA 的数据为“1”
- 分区 B 有数据“2”
因为 spark 2.3 的新功能 overwrite dynamic 无法创建 PartitionC。
更新:事实证明,如果您改用 hive 表,这将起作用。但是如果你使用纯火花它不会......所以,我猜蜂巢的覆盖和火花的覆盖工作不同。
【问题讨论】:
-
我不确定在使用之前设置属性是否会影响其功能,但我只是遇到了这个问题,设置这个属性
"spark.sql.sources.partitionOverwriteMode": "dynamic"对我有用。 我在创建 spark 会话时设置了它。您可能想尝试一下。 -
这很奇怪。我稍后会对此进行测试并报告。
-
@mrbolichi 喜欢这样:
SparkSession.builder() .config("spark.sql.sources.partitionOverwriteMode", "dynamic") .appName("Ingester") .getOrCreate()? -
我刚试了,没用。
-
您是否尝试将
save放入 Hive 表中?我仅通过插入 Hive 表来重现此行为
标签: apache-spark apache-spark-sql hdfs bigdata