Pysparkを使用して、AmazonS3の寄木細工のファイルからデータフレームを読み取っています。
dataS3 = sql.read.parquet("s3a://" + s3_bucket_in)
これは問題なく機能します。しかし、それから私はデータを書き込もうとします
dataS3.write.parquet("s3a://" + s3_bucket_out)
次の例外が発生します
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
Sparkは、指定されたバケットに書き込むために書き込む前に、最初に_temporary
フォルダーを作成しようとしているようです。これを何らかの方法で防ぐことができるので、sparkは指定された出力バケットに直接書き込んでいますか?
クエリの中間作業が完了するまで非表示に保つために使用される_temporaryファイルを削除することはできません。
しかし、これは問題ではないので、それは問題ありません。問題は、出力コミッターがルートディレクトリに書き込もうとすると少し混乱することです(削除できません。を参照)。
完全なプレフィックスを付けて、バケットの下のサブディレクトリに書き込む必要があります。例えば_s3a://mybucket/work/out
_。
S3Aにデータをコミットしようとすることは信頼できないことを付け加えておきます。これは、_ls -rlf src | xargs -p8 -I% "cp % dst/% && rm %"
_のようなものによってrename()
を模倣する方法のためです。 ls
はS3での整合性を遅らせているため、新しく作成されたファイルを見逃す可能性があるため、それらをコピーしないでください。
詳細については、 Apache Sparkの改善 を参照してください。
現時点では、HDFSに書き込んでからコピーすることによってのみ、s3aに確実にコミットできます。 EMR s3は、DynamoDBを使用してこれを回避し、一貫したリストを提供します
S3バケットのルートを作成するときに同じ問題が発生しました:
df.save("s3://bucketname")
バケット名の後に/
を追加して解決しました。
df.save("s3://bucketname/")