まず、結論を先に書いておくと、全然解決してなくて、今も絶賛悩み中です。
bigqueryにデータをロードする時、1テーブルに全データを投入し続けていくと1クエリで読み込むデータがどんどん大きくなり課金額が上がってしまう。(bigqueryはWHERE句等に関わらず常にテーブルの全行を読み込む)
なので、日付毎や何らかのキー毎にテーブルを分けるというのが割と良くあるユースケースになっている。
それを支援するために、テーブルワイルドカード関数が用意されていたり、テーブルのUNIONが,
で区切るだけで記述できたりする。
最初勘違いがあったのだが、bigqueryはテーブルレベルでスキーマが異なっていても、クエリで利用するカラム名と型が一致していればUNIONできるという性質を持っている。
まあ、よくよく考えれば当たり前で、普通のRDBでUNION句を利用しても同じことなのだが、bigqueryのクエリ記述上、テーブルワイルド関数とか,
区切りのUNIONで、あんまりそれが可能なように見えなかった。
SELECT id, user_id FROM TABLE_DATE_RANGE(dataset.post, TIMESTAMP('2016-1-1'), TIMESTAMP('2016-1-15'))
こういうクエリの時に、post20160110辺りからスキーマが変更されていても、クエリで利用しているカラムさえ一致していれば問題無い。
まあ、当たり前っちゃ当たり前である。
ちなみに、もしカラムを減らす場合にはignoreUnknownValues
を付けておかないと、既存の余計なカラムを含んだデータをそのまま送っているとエラーになる。
問題はカラムを増やした場合の過去データの扱いである。
過去のデータ量が大量になってくるとデータを入れ直すってのは、かなり辛い仕事になりそうだ。
やるにしても、一回GCSにextractしてembulkか何かで加工しながらbigqueryに戻すって感じになるんだろうか。
後考え付くのが、テーブルを別テーブルにCOPYしてオリジナルを削除し、同じ名前でViewを作り直すという方法。
Viewの作成とCOPYジョブは割とすぐ終わるので、API叩くスクリプトを書けばそこそこの時間で終えられそう。
お金もかからない。
問題は、変更が積み重なってくるとViewの編集が辛くなりそうっていう点か。
そもそも、そんな事をするぐらいなら最初から投入後のデータを直で使うのではなく、一回Viewでラップしておくのが良いのではという気もする。見た感じのテーブル量が倍になってしまうが、将来的にカラムが増えたり減ったりした時も、クエリ文字列の編集だけでとりあえず乗り切れる気がする。
(今更そんな感じにするのはちょっと面倒なのだが……。)
もしかしたら、bigqueryはガンガンViewを活用していくのが正解なのかもしれない。
とりあえず、あるテーブルを別名のテーブルに退避して、ビューに差し替えるってのは使い道がありそうな気がする。