LoginSignup
3
0

More than 3 years have passed since last update.

bqコマンドでschema_update_optionを指定すると、カラム追加の運用が楽な話

Last updated at Posted at 2020-06-16

サマリ

  • schema_update_option に ALLOW_FIELD_ADDITION を指定すると、 カラムが追加された場合でも、別途tableのschema update作業をしなくても良いという話。
  • 日付別パーティショニングテーブルに、日次でCSVデータを投入していくようなシステムを想定している。
  • 公式ドキュメントの記載はこちら
  • 今回BQコマンドでやっているが、当然APIとして提供されているので、各種SDKを使ったLoadでも同じことができます(Embulkとかでも)

実験した環境

テーブル名

  • foobar

テーブル作成コマンド

bq mk --table --require_partition_filter --time_partitioning_type=DAY 'project_id:dataset_id.foobar'

Day 1

通常以下のようにLoadされているとします。

テーブルスキーマ

foobar.schema1.json
[
  {
    "mode": "NULLABLE",
    "name": "a",
    "type": "STRING"
  },
  {
    "mode": "NULLABLE",
    "name": "b",
    "type": "INTEGER"
  }
]

投入データ

foobar1.csv

"a","b"
"abc",1
"xyz",9

Loadコマンド

bq load \
--source_format=CSV --skip_leading_rows 1 \
'project_id:dataset_id.foobar$20200610' ./foobar1.csv ./foobar.schema1.json

途中からカラムが増える

途中から読み込むCSVのカラムが増えたと想定します。
この場合、

  • schemaファイルの変更
  • bq update(table schemaのupdate)

の2つが必要に思いますが、schema_update_option に ALLOW_FIELD_ADDITION を指定することによって、 bq update(table schemaのupdate) が不要になります。

Day 2

テーブルスキーマ

  • cというカラムが追加されている
foobar.schema2.json
[
  {
    "mode": "NULLABLE",
    "name": "a",
    "type": "STRING"
  },
  {
    "mode": "NULLABLE",
    "name": "b",
    "type": "INTEGER"
  },
  {
    "mode": "NULLABLE",
    "name": "c",
    "type": "STRING"
  }
]

投入データ

  • cというカラムが追加されている
foobar2.csv
"a","b","c"
"abc",1,"zzz"
"xyz",9,"zzz"

Loadコマンド

  • 新スキーマを指定している
bq load \
--source_format=CSV --skip_leading_rows 1 \
--schema_update_option ALLOW_FIELD_ADDITION \
'project_id:dataset_id.foobar$20200611' ./foobar2.csv ./foobar.schema2.json

load結果

スクリーンショット.png

期待したとおり、Day2で増えたカラムに、過去分にはnullが入っています。

再実行時の注意点

rerunする場合、loadする前にパーティションを削除しないと2重にデータが入ってしまうので注意

再実行前にパーティションを消す

bq rm --force 'project_id:dataset_id.foobar$20200611'

と、これを書いたとに、 --replace オプションで同様のことができることがわかりました。Day2のクエリに --replace をつけるだけで良さそうです。

bq load \
--replace \
--source_format=CSV --skip_leading_rows 1 \
--schema_update_option ALLOW_FIELD_ADDITION \
'project_id:dataset_id.foobar$20200611' ./foobar2.csv ./foobar.schema2.json

まとめ

というわけで、実際の運用上は、日次で以下のようなbqコマンドを回せばやりたいことができそうです。

export LOAD_FILE="./foobar2.csv"
export TARGET_TABLE="'project_id:dataset_id.foobar$20200611'"
export SCHEMA="./foobar.schema2.json"
bq load \
--replace \
--source_format=CSV --skip_leading_rows 1 \
--schema_update_option ALLOW_FIELD_ADDITION \
${TARGET_TABLE} ${LOAD_FILE} ${SCHEMA}
3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0