Jupyter上でPandasを使ってBigQueryをクエリする時のコスト上限を指定する
課題
Jupyter上でインタラクティブにコードを書きながらBigQueryにクエリを投げたりしていると、typoが思わぬ高額課金を引き起します。例えば3日分のデータを取得したい時に TABLE_DATE_RANGE
に渡す日付を
- (正)
TABLE_DATE_RANGE(xxx_, TIMESTAMP('2017-05-01'), TIMETAMP('2017-05-03'))
- (誤)
TABLE_DATE_RANGE(xxx_, TIMESTAMP('2016-05-01'), TIMETAMP('2017-05-03'))
とtypoすると1年と3日分のテーブルがスキャン対象になる。これに気づくのは、クエリジョブを投入後、なかなか結果が帰ってこないので不信に思ってクエリを見直した時だったりします。
対策
書いて即時に実行していけるインタラクティブ環境の魅力を損なわずにこれを防ぐには、実行時にチェックがかかれば良い。幸いPandasのv0.20からオプションで指定できるようになった。
次の様な pd.read_gbq
のラッパーを用意して1クエリあたりのコスト上限を指定可能にすると良い。
COST_LIMIT_PER_QUERY = 1 # USD
GBYTE = 1000000000
maximum_bytes_billed = int(COST_LIMIT_PER_QUERY * 200 * GBYTE)
def read_gbq(query):
return pd.read_gbq(
query, project_id=PROJECT_ID, verbose=False,
configuration={'query':{
'maximumBytesBilled': maximum_bytes_billed,
'maximumBillingTier': 1 # 2になるのを見た事が無いので1固定
}})
maximumBytesBilled
の上限に引っかかると、クエリの実行に必要な値がエラーメッセージに入ってくる。
例
GenericGBQException: Reason: bytesBilledLimitExceeded, Message: Query exceeded limit for bytes billed: 2000000. 20971520 or higher required.