🔍

BigQuery のデータセットを US から東京リージョンに引っ越しした話

2022/12/22に公開

はじめに

どうも、Happy Elements 株式会社 カカリアスタジオ 分析チーム データエンジニア の K.M. です。

この会社に来てもう少しで3年になります。
その間には、既存タイトルの超大型アップデート、新規タイトルリリース、既存タイトルのオンプレからクラウド移行などビッグイベントを見てきました。

わたしが担当しているログ配信基盤では、2022年のお正月に大きな障害がありました。
完全復旧まで相当な時間を要しましたが、インフラチームと一緒に見事な連携を発揮して対応したのは、地獄のようないい思い出です。
普段は、ログ配信基盤の構築・運用、Looker の運用などをやっております。

本題

既存のデータセットの抱える課題

弊社アプリのログデータは BigQuery に入っています。
一番古いデータセットは2018年8月に作られたもので、US マルチリージョンにありました。
東京リージョンのサービス開始が2018年4月のようなので、ギリギリの時期だったんですね。

それより後に作成されたデータセットはすべて東京リージョンにあります。
リージョンが違うと、クエリで JOIN を使ってテーブル同士を結合することが出来ない等、他のデータセットとの連携に難がありました。

この課題を解決するため、US マルチリージョンのデータセットを東京リージョンに引っ越す事にしました。
その時のデータセットのサイズは 数十TB となかなかのサイズに成長していました。

データセット移行に求めること

  • ログデータは絶え間なく出力されており、既存の運営に影響を与えることは出来ない
  • 新しいログデータだけが参照できれば良いわけではなく、過去分含めてすべてのログデータを参照できる必要がある
  • ログデータの重複は許されない

これらの要件を満たすため、大方針として

  • 既に新しいログが入力されないことが自明な過去分のデータは事前に時間をかけて移動させる
  • 定期メンテナンスのウィンドウで、直近に出力されたログをコピーし、完全に同期した状態を作る

という方針を立てました。
その上で、具体的にデータをUSリージョンから東京リージョンに動かす方法について複数の方法を検討しました。

BigQuery Data Transfer Service (DTS) を使う方法

試しに、BigQuery Data Transfer Service (DTS) を使ってデータセットコピーしてみたところ、ざっくり10GB転送に1分かかりました。
数十TB だと数日かかる計算です。

BigQuery のコンソール画面のデータ転送から、簡単にデータセットをコピーすることができて、
DTSはベータ版(2022年11月現在)のため、DTS使用料金、ネットワーク転送料金(egress) が無料です。

今なら無料!なんですが DTS は、期間を指定したり差分コピーをすることができません。
今回はこの機能だけでは移行することができません。

BigQuery Data Transfer Service とは

US マルチリージョンのデータセットを東京の GCS に出力する方法

US マルチリージョンのデータセットは任意のリージョンの GCS バケットにエクスポートできます。
これを利用して、直接東京リージョンの GCS バケットにエクスポートしロードすることでデータセットのコピーができます。

エクスポートは、bq query コマンドの EXPORT DATA OPTIONS ステートメントを使用すれば、クエリの WHERE 句で期間を指定することができます。

ロードは bq load コマンドで行えます。

エクスポートの bq query コマンドで数十TB分のクエリの料金が発生します。
BigQuery と GCS 間のネットワーク料金は無料でした。BigQuery の料金 データ取り込みの料金
あと GCS の料金がかかります。

ちなみに、bq extract でもエクスポートすることができ、エクスポート自体に料金は発生しませんが、期間を指定することができません。

クエリ料金が発生しますが、シンプルに GCS にエクスポートしてロードするこの方法を採用することにしました。

注意が必要なクオータ

クオータ 上限 備考
読み込みジョブあたりの最大サイズ 15 TB CSV、JSON、Avro、Parquet、ORC の各入力ファイルの合計サイズは 15 TB 以下にする必要があります。
割り当てと上限 読み込みジョブ※1
1 日の取り込み時間パーティション分割テーブルあたりのパーティションの変更回数 5,000 回の変更 1つのパーティション分割テーブルに1日5,000回以上の変更ができません。
割り当てと上限 パーティション分割テーブル※2

移行手順

1. 東京リージョンにデータセットと空のテーブル、GCS バケットを作成

INFORMATION_SCHEMA.TABLES の ddl カラムに入っている値をもとにテーブルを作成します。

2. US マルチリージョンのデータを東京リージョン GCS へエクスポート

bq query コマンドの EXPORT DATA OPTIONS ステートメントを使用して、クエリの WHERE 句で期間指定しデータをエクスポートします。

フォーマットは、AVRO 形式が一番速いと Google ドキュメントに書いてあったので AVRO 形式にしたのですが、ロード時にスキーマ情報のモードが変わっているとエラーになりました。

{カラム名} has changed mode from REQUIRED to NULLABLE

AVRO 形式は各列のモードを保持する機能が無いため、再読み込みの際にデフォルトで NULLABLE が補われるそうです。
ということで JSON 形式でエクスポートしました。

エクスポートコマンド例

# エクスポート  
$sql = "SELECT * FROM {table} WHERE {期間指定する}"  
bq query --nouse_legacy_sql --project_id=${PROJECT_ID} "  
EXPORT DATA OPTIONS(  
    uri='gs://${BUCKET_NAME}/${table_name}/${YMD}/*.gz',  
    format='JSON',  
    compression='GZIP') AS $sql"  

3. 東京リージョン GCS から東京リージョン BigQuery へロード

bq load コマンドを使用します。

ロードコマンド例

bq load \  
--location=asia-northeast1 \  
--project_id=${PROJECT_ID} \  
--source_format=NEWLINE_DELIMITED_JSON \  
${TARGET_DATASET_ID}.${table_name} \  
gs://${BUCKET_NAME}/${table_name}/${YMD}/*.gz  

4. アプリのメンテナンス時に最終エクスポートとロード

アプリのメンテナンス時に差分データを、手順3, 4 と同様のコマンドでエクスポート・ロードします。
そして、ログ配信基盤の連携先データセットを東京リージョンのデータセットに変更します。

5. ログ連携の確認

ログが正しく連携されていることを確認して終了です。

おわりに

検証では、これ何日かかんねんという感じでしたが最終的にかかった時間は、エクスポート延べ時間 7時間22分、ロード延べ時間 5時間17分でした。

アプリのメンテナンスでこのための作業に割り当てられた時間は2時間で、その時間内に作業を無事に終えるのかドキドキでしたが、大きな問題もなく引っ越し作業を終えることができました。

地味な変更ですが、1つ1つ改善して使いやすくシンプルに運用出来るログ基盤を目指していきたいと思います。

GitHubで編集を提案
Happy Elements

Discussion