Posted at

BigQuery のデータのロケーション移行

(追加で備忘録残したくなったら随時更新)


1. ワイルドカードテーブル


経緯


  • BigQuery 便利だけどロケーションを跨げない

  • 昔から使ってると US ロケーションだったりして

  • でも asia-northeast1 (Tokyo) とかとっくに出てるからそっち使っちゃいたいし

  • 直接コピーすらできないから GCS を介してやり取りする

  • けどワイルドカードテーブルとか日時でテーブル作ってると膨大にあってだるい


解決策


  • コマンド組んで一気にやるしかなかろう

# --- local ---

$ # gcloud / gsutil / bq コマンドが叩ける docker コンテナ
$ docker run -it --rm --name gcp-sdk google/cloud-sdk:latest

# --- container ---

% # jq を使うので追加でインストール
% apt-get install -y jq

% # 認証
% gcloud auth login

% # bq コマンドの初期起動時の stdout に流れるうるさいメッセージを出さないためのファイル用意
% touch .bigqueryrc

% project=ppp
% old_dataset=old_ddd
% new_dataset=new_ddd
% target_table=ttt
% bucket=bbb

% # bq コマンドが叩けるはず
% # e.g. bq --bigqueryrc=.bigqueryrc --project_id=${project} ...

% # とりあえず移行したいテーブルのスキーマを取得する (--autodetect は DATETIME 型とか使ってると困るのでやらない)
% last_table=$(\
bq --bigqueryrc=.bigqueryrc --format=json --project_id=${project} ls -n 10000 ${old_dataset}\
| jq -r --arg tbl_prefix ${target_table} '[.[] | select(.tableReference.tableId | startswith($tbl_prefix)).id] | last'\
)
% bq --bigqueryrc=.bigqueryrc --format=json --project_id=${project} show ${last_table} | jq '.schema.fields' > ${target_table}.schema.json

% # GCS にいっぺんに持ってくる
% bq --bigqueryrc=.bigqueryrc --format=json --project_id=${project} ls -n 10000 ${old_dataset}\
| jq -r --arg tbl_prefix ${target_table} '.[] | select(.tableReference.tableId | startswith($tbl_prefix)).id'\
| xargs -t -I {table} -P30 bash -c "bq --bigqueryrc=.bigqueryrc --project_id=${project} extract --destination_format=NEWLINE_DELIMITED_JSON {table} gs://${bucket}/backup/${target_table}/{table}/data.json"

% # GCS のデータをいっぺんにアップロードする
% bq --bigqueryrc=.bigqueryrc --format=json --project_id=${project} ls -n 10000 ${old_dataset}\
| jq -r --arg tbl_prefix ${target_table} '.[] | select(.tableReference.tableId | startswith($tbl_prefix)).id'\
| xargs -t -I {table} -P30 bash -c "bq --bigqueryrc=.bigqueryrc --project_id=${project} load --source_format=NEWLINE_DELIMITED_JSON --replace=false \$(echo {table} | sed 's/${old_dataset}/${new_dataset}/g') gs://${bucket}/backup/${target_table}/{table}/data.json ${target_table}.schema.json"