別リージョンのGCSからBigQueryに定期的に安くデータを移す方法
はじめに
USリージョンにあるGCSバケットのデータを東京のBigQueryのデータセットに定期的に移す必要があったので、そのときに採用した方法を書いてみます。
結論
2つのスケジュールドクエリを使用して、データの移行を行いました。

- USのバケットのデータを外部テーブルにして、データをフィルタリングしつつ、東京のGCSバケットにエクスポート
- 東京のGCSバケットにエクスポートされたデータを、東京のBigQueryデータセットにインポート
1. USのバケット → 東京のバケット
まず、最もお金がかかるのがリージョン間のデータ転送料金です。できるだけ、データ量を減らしてから別リージョンにデータを移すことを考えます。
今回は元のデータ全てが必要なわけではなかったので、1つ目のスケジュールドクエリでデータをフィルタリングしました。 僕の場合はこれでデータを10分の1程度にしてから東京のバケットにエクスポートしました。
BigQueryでは、外部テーブルを作成することで、GCSのデータを参照できます。これを利用して、フィルタリング結果を東京のバケットにエクスポートしました。
-- 外部テーブルの作成(Avroファイルを指定)
CREATE OR REPLACE EXTERNAL TABLE dataset_in_us.external_avro_table
OPTIONS (
format = 'AVRO',
uris = ['gs://bucket-in-us/some-file.avro']
);
-- フィルタリング結果をParquet形式でエクスポート
EXPORT DATA OPTIONS(
uri='gs://bucket-in-tokyo/exported-data-*.parquet',
format='PARQUET'
)
AS
SELECT
*
FROM dataset_in_us.external_avro_table
WHERE
some_column = 'some_value'; -- フィルタリング条件
;
parquet形式でエクスポートすることで、jsonlやCSVよりもデータ量を削減できます。
エクスポートのオプションの詳細は公式ドキュメントを参照してください。
ポイント
大量のデータをエクスポートする際は、ワイルドカードの*
をURIに含めるのがミソです。具体的には1GBを超える場合には、*
を使って複数のファイルに分割してエクスポートしなければいけません。
2. 東京のバケット → BigQuery
こちらは比較的単純で、東京のバケットにエクスポートされたデータをBigQueryにインポートするだけです。
フォーマットや圧縮形式はエクスポート時と同じものを指定します。
LOAD DATA INTO dataset_in_tokyo.my_table
FROM FILES (
uris=['gs://bucket-in-tokyo/exported-data-*.parquet'], -- ①でエクスポートされたデータのURI
format='PARQUET'
);
ポイント
もし、データセットに入れて実体化させる必要がない場合は、先ほどと同じように外部テーブルを作成して参照するだけでもいいかもしれません。
まとめ
リージョン間のデータ移行は、転送料金を考えるとできるだけデータ量を減らすことが重要です。転送前にできるだけフィルタリングしたり、parquet形式でエクスポートすることでデータ量を削減しましょう。 また、ちゃんとやるならdataformを使ってパイプライン化した方が安全ですね。