我们目前将一堆Avro文件上传到S3,这些文件按上传时间进行分区,我们希望将它们转换为Parquet并由该事件的customerId重新分区。
我们已经使用火花结构流传输了一个解决方案,它似乎在语义上是正确的。我们的代码有一堆看起来像
的查询Dataset<Row> sourceStream = sparkSession.readStream()
.format("com.databricks.spark.avro")
.load("/avro/input/path");
sourceStream
.drop("ingestion_hour")
.withColumn("c_id", new Column("customer_id"))
.repartition(new Column("c_id"))
.writeStream()
.trigger(Trigger.Once())
.outputMode(OutputMode.Append())
.format("parquet")
.option("checkpointLocation", "/checkpoint/path/")
.partitionBy("c_id")
.start("/parquet/output/path");
然而,似乎存在一个问题,/avro/input/path
前缀下的文件数量不断增加,从而导致每次执行ETL需要更长时间才能列出S3中的文件以便计算新文件。
我尝试将单个流式传输查询拆分为多个流式查询,这些查询每小时消耗一次,例如/avro/input/path/ingestion_hour=yyyy-MM-dd-HH
并使用检查点路径/parquet/output/path
输出到/checkpoint/path/yyyy-MM-dd-HH
的同一个接收器。然后我可以限制作业只执行过去的查询,比如12小时。但是,这项工作似乎不像在多个查询之间共享接收器是正确的事情,因为大多数记录都没有显示在输出中。
我想知道是否有某种方法可以使这种方法起作用,或者是否有不同的方法来限制列出的文件数量?