BigQueryのクエリでテーブル名を書くときに末尾に*
を書いておくと、その部分が_TABLE_SUFFIX
というカラムに入っていてWHERE
の条件に書いて使うテーブルを絞り込むことができます
BigQueryではテーブル名の末尾に日付を書いておいて、_TABLE_SUFFIX
で絞り込むのがよく使われています
参照したバイト数によって課金されるので、できるだけ余分なテーブルを参照するのを避けるとコストを節約できます
以下の画像のように_TABLE_SUFFIX
の条件を外すと処理されるバイト数が増えています
BigQueryではパラメータ付きのViewやWITH句が書けないので、ビューの外側からパラメータとして_TABLE_SUFFIX
の絞り込みを書くのはできないかと思っていたのですが、やる方法を教えてもらったので詳しい挙動を調べてブログに書いておきます
ビューとWITH句でだいたい同じ挙動のようなので以下ではWITH句で説明していきます
方法
必要なのは、_TABLE_SUFFIX
をカラムとして外側に渡すことです
ただし_TABLE_
で始まるカラムをユーザーが作るのは許されていないのでなんらかの適当な名前にしておく必要があります
外側に渡した_TABLE_SUFFIX
のカラムに対して条件をかけることで参照されるテーブルを絞ることができます
制約
いくつか試したところ、ビューやWITH句のクエリの中にLIMIT
があったり_TABLE_SUFFIX
をPARTITION BY
の条件に含まないウィンドウ関数を書いたりすると、外側から条件で絞っても全部使われてしまうようです(他にもダメなものはありそう)
当然かも知れませんが、ビューやWITH句のクエリの時点で全テーブルのデータが影響してくる場合はダメみたいです
利用例
単純にSELECT
してそれぞれの行のデータを取ってくる
カラムを絞ったり追加したり、値に演算をしたり、UNNEST()
したりするだけの場合この記事の方法が役に立ちそうです
GROUP BY
やウィンドウ関数で集計する場合
ビューやWITH句の外側に_TABLE_SUFFIX
を出さなければならない都合上、GROUP BY
に_TABLE_SUFFIX
のカラムを含める必要があってクエリが制限されます
同様にウィンドウ関数を使う場合にはPARTITION BY
に_TABLE_SUFFIX
を含める必要があります
テーブルをJOIN
する場合
個人的には少し意外だったのですが、テーブルをJOIN
する場合でもJOIN
したビューやWITH句の外側で_TABLE_SUFFIX
による絞り込みが効くようです
以下は同じ月と日のデータをJOINしているだけの特に意味のないクエリですが、_TABLE_SUFFIX
による絞り込みでバイト数が抑えられているのがわかります
まとめ
試してみたところ意外といろいろなタイプのクエリでビューの外側からでも_TABLE_SUFFIX
の指定ができました
試してはいませんがパーティションで分けられたテーブルの_PARTITIONTIME
でも同じようなことはできそうです
一つ注意点としては、ビューで*
を使って大量のテーブルをまとめた場合_TABLE_SUFFIX
を指定し忘れると意図せず大量のテーブルにアクセスしてしまうので実行前にどれぐらいのバイト数か確認したほうがよさそうです。
あらかじめ一ヶ月や一年以内のテーブルに_TABLE_SUFFIX
を絞る条件を書いておいたり、クエリを実行するときの最大のバイト数に制限を書けたほうが安全かもしれません
上で出てきたクエリ例
SELECT
してくるだけ
#standardSQL WITH data AS ( SELECT *, _TABLE_SUFFIX AS table_suffix FROM `bigquery-public-data.noaa_gsod.gsod*` ) SELECT * FROM data WHERE table_suffix = '2018'
GROUP BY
で集計
#standardSQL WITH data AS ( SELECT _TABLE_SUFFIX AS table_suffix, mo AS month, COUNT(*) AS count FROM `bigquery-public-data.noaa_gsod.gsod*` GROUP BY table_suffix, month ) SELECT month, count FROM data WHERE table_suffix = '2018'
ウィンドウ関数で集計
#standardSQL WITH data AS ( SELECT _TABLE_SUFFIX AS table_suffix, *, COUNT(*) OVER (PARTITION BY _TABLE_SUFFIX, mo) FROM `bigquery-public-data.noaa_gsod.gsod*` ) SELECT * FROM data WHERE table_suffix = '2018'
JOIN
が含まれるクエリ
#standardSQL WITH data AS ( SELECT *, _TABLE_SUFFIX AS table_suffix FROM `bigquery-public-data.noaa_gsod.gsod*` ), join_test AS ( SELECT data1.*, data2.year AS year2, data2.table_suffix AS table_suffix2 FROM data AS data1 JOIN data AS data2 ON data1.mo = data2.mo AND data1.da = data2.da ) SELECT * FROM join_test WHERE table_suffix = '2018' AND table_suffix2 = '2017'