在不创建_temporary文件夹的情况下将Spark数据帧作为拼写形式写入S3

asm*_*ier 4 hadoop amazon-s3 apache-spark pyspark

我正在使用pyspark从Amazon S3上的实木复合地板文件中读取数据帧

dataS3 = sql.read.parquet("s3a://" + s3_bucket_in)
Run Code Online (Sandbox Code Playgroud)

这没有问题。但是后来我尝试写数据

dataS3.write.parquet("s3a://" + s3_bucket_out)
Run Code Online (Sandbox Code Playgroud)

我确实收到以下异常

py4j.protocol.Py4JJavaError: An error occurred while calling o39.parquet.
: java.lang.IllegalArgumentException: java.net.URISyntaxException: 
Relative path in absolute URI: s3a://<s3_bucket_out>_temporary
Run Code Online (Sandbox Code Playgroud)

在我看来,Spark尝试先创建一个_temporary文件夹,然后再进行写入以写入给定存储桶。是否可以通过某种方式防止这种情况发生,以便将火花直接写入给定的输出存储桶?

Ste*_*ran 6

您无法消除_temporary文件,因为该文件用于隐藏查询的中间工作,直到完成为止

但这没关系,因为这不是问题。问题是输出提交者在尝试写入根目录时有点困惑(无法删除它,请参阅)

您需要使用完整的前缀写入存储桶下的子目录。例如 s3a://mybucket/work/out

我要补充的是试图去提交数据S3A是不可靠的,正是因为它的方式模仿rename()的东西是一样的东西ls -rlf src | xargs -p8 -I% "cp % dst/% && rm %"。由于ls延迟了S3的一致性,因此它可能会丢失新创建的文件,因此请勿复制它们。

有关详细信息,请参见:改进Apache Spark

现在,您只能通过写入HDFS然后进行复制来可靠地提交s3a。EMR s3通过使用DynamoDB提供一致的清单来解决此问题