小ネタ:BigQueryからGCSに1ファイルでデータ出力する
はじめに
BigQueryはMPP(Massive Parallel Processing)のアーキテクチャで普通にGCSに出力すると、多数のファイルに分かれて出力されてしまいます。
GCSに 1 ファイルに出力したいけどできなかった経験をされた人は多そうですが、対処法について情報が少なくあまり知られてなさそうなので記事にしてみました。
1GB以下の場合
export data options
でGCSに小さいデータを出力するとき、order by
を使うと 1 ファイルに出力できます。limit
や distinct
を使ってもできます。このように、クエリ結果をソートしたりしてGCSに書き込む処理を 1 worker で実行するように制御できれば 1 ファイルで出力できるようです (参考記事)。
export data options (
uri = 'gs://your-bucket/foo/bar/exported_file_*.csv',
format = 'csv',
field_delimiter = ',',
header = true,
overwrite = true
) as
select *
from your_dataset.your_table
order by 1 -- Force all data to be loaded into one worker/file using `order by` (if <=1GB)
なお、大きいデータの場合は 1 ファイルにならなくてもファイル数を少なくできるので、なるべくファイル数を抑えたい場合にもこの方法が有効です。
1GBを超える場合
データ量が大きいと直接 1 ファイルに出力できないので、複数ファイルに出力してから 1 ファイルにまとめるアプローチを取ります。
ちなみに、この場合 header=false
にしないとファイル数分の header を結合してしまう点に注意です。
Command Line
gsutil compose
で31ファイルまでは結合できますが、それより多い場合の方法は下記で紹介されています。
なお、gsutil が not recommended になったので、代わりに gcloud storage objects compose を使いましょう。
Programming Language
Google Cloud open tutorials のリポジトリで accumulator パターン を応用したPythonの実装例が紹介されています。
デモンストレーション目的であり production-ready でないと記載あり、オブジェクト削除が並列処理になっている辺りが怪しいので、single-thread にするか、並列処理の終了を担保する仕組みの追加が必要そうです。
Discussion