Scala 将新数据附加到分区的拼花地板文件

Scala 将新数据附加到分区的拼花地板文件,scala,apache-spark,append,parquet,Scala,Apache Spark,Append,Parquet,我正在编写一个ETL过程,在这个过程中,我需要读取每小时一次的日志文件,对数据进行分区并保存它。我正在使用Spark(在Databricks中)。 日志文件是CSV文件,因此我读取它们并应用模式,然后执行转换 我的问题是,如何将每小时的数据保存为拼花格式,但附加到现有数据集?保存时,我需要按数据框中的4列进行分区 这是我的保存行: data .filter(validPartnerIds($"partnerID")) .write .partitionBy("partne

我正在编写一个ETL过程,在这个过程中,我需要读取每小时一次的日志文件,对数据进行分区并保存它。我正在使用Spark(在Databricks中)。 日志文件是CSV文件,因此我读取它们并应用模式,然后执行转换

我的问题是,如何将每小时的数据保存为拼花格式,但附加到现有数据集?保存时,我需要按数据框中的4列进行分区

这是我的保存行:

data
    .filter(validPartnerIds($"partnerID"))
    .write
    .partitionBy("partnerID","year","month","day")
    .parquet(saveDestination)
问题是,如果目标文件夹存在,则保存会抛出错误。 如果目标不存在,则我不会追加文件

我尝试过使用
.mode(“append”)
,但我发现Spark有时会中途失败,因此我最终失去了写入的数据量和仍需要写入的数据量

我使用拼花地板是因为分区大大增加了我未来的查询量。此外,我必须将数据以某种文件格式写入磁盘,不能使用Druid或Cassandra之类的数据库


对于如何划分我的数据帧并保存文件(粘贴到拼花地板或其他格式)的任何建议,我们将不胜感激

如果需要附加文件,则必须使用附加模式。我不知道您希望它生成多少个分区,但我发现如果您有许多分区,
partitionBy
将导致许多问题(内存和IO问题类似)

如果您认为问题是由于写操作花费的时间太长造成的,我建议您尝试以下两种方法:

1) 通过向配置中添加以下内容来使用snappy:

conf.set("spark.sql.parquet.compression.codec", "snappy")
2) 在
SparkContext
上的
hadoopConfiguration
中禁用元数据文件的生成,如下所示:

sc.hadoopConfiguration.set("parquet.enable.summary-metadata", "false")
生成元数据文件会有点费时(请参阅),但根据定义,它们实际上并不重要。就我个人而言,我总是禁用它们,没有任何问题


如果您生成了许多分区(>500),恐怕我能做的就是建议您研究一种不使用追加模式的解决方案-我从来没有设法让
partitionBy
处理过这么多分区。

如果您使用未排序的分区,您的数据将被分割到所有分区。这意味着每个任务都将生成数据并将其写入每个输出文件

在写入之前,请考虑根据分区列重新分区数据,使每个输出文件的所有数据都位于相同的分区上:

data
 .filter(validPartnerIds($"partnerID"))
 .repartition([optional integer,] "partnerID","year","month","day")
 .write
 .partitionBy("partnerID","year","month","day")
 .parquet(saveDestination)

请参阅:

您是否可以分享使用
.mode(append)时出现的错误
。我得到的错误是:由于:java.io.IOException:文件已存在:/tracking/v4/010316/gif=a/partnerID=111/year=2016/month=1/day=3/part-r-00147-8f30e760-3706-4e4c-bf56-e3b5515942d1.gz。我认为,当某些写入操作花费很长时间时,由于任务调度不匹配而引发此错误。@Saman你是怎么知道的解决这个问题?我正在尝试处理类似的情况。超过10000个分区,事实上甚至更多,因为每小时一个分区。我正试图围绕这个问题制定一个解决方案,有什么建议吗。?谢谢。@ds\u user,使用最新版本的spark(我使用的是Databricks运行时环境,它有许多开源spark之外的功能),您可以在编写器中使用“附加”模式。在解决此问题之前,应该重新考虑导致10k+分区的分区列。我不知道您拥有的数据量,但是否可以按天而不是按小时进行分区?尝试重新分区数据,以确保在写入数据后有200-500MB的文件。您是要一次写入所有10k分区,还是每个批都有几个分区?这就是我要解决的问题。我正试图通过列表id(或)产品id进行分区。因此,如果我为每个列表汇总到每日分区,我希望存储listingId=612/年=2018/月=3/天=5。但由于列表数量的增加,这仍然是太多的分区。有什么建议吗?谢谢你,格伦尼。我总是禁止元数据文件的生成,因为这篇博文也是:D。我肯定要创建500多个分区。我相信我的大多数问题都是因为拼花地板格式不打算用作可更新的格式,而我将其视为数据库表。您对保存我的日常数据的另一种方法有什么建议吗?我有类似的问题,我根据当前的时间戳进行分区,每个新的分区都会附加一个分区,它创建的总任务等于到目前为止的分区。i、 e如果有1000个分区和1个新分区要添加,它将运行1001任务,并增加总体作业时间。我做错什么了吗?