BigQueryの課金、
節約しませんか
玉川竜司 @ Sky
Agenda
自己紹介
BigQueryの紹介
基本
上級
Tips & Tricks
Agenda
自己紹介
BigQueryの紹介
基本
上級
Tips & Tricks
BigQueryの課金体系
BigQueryのクエリの実行
Agenda
自己紹介
BigQueryの紹介
基本
上級
Tips & Tricks
列の選択
テーブルデコレータ
テーブルの分割
クエリキャッシュの動作
Agenda
自己紹介
BigQueryの紹介
基本
上級
Tips & Tricks
CPUとネットワークは
無料!
サブクエリの利用
リピートフィールド
自己紹介
新大阪のソフト会社勤務。

設計からフィールド対応まで
何でもあり
オライリージャパンで翻訳し
てます
‘Google BigQuery Analytics’
でたぶん25冊目くらい
家では猫のベッド
今後の予定
7月 8月 年内
BigQueryの紹介
フルマネージドな構造化データスト
アで、SQLでアクセスできる
非常に簡単に使えます
高速。特に、データサイズが大きく
なっても速度がほとんど低下しない
安価
Googleのインフラストラクチャの
様々なサービス上で構築されている
BigQueryの紹介
基本的な操作はWeb UIで可能
‘dryrun’すればスキャンされ
るデータの量も分かる
コマンドラインインターフェー
ス(bq)を使ってBigQueryを
ワークフローに組み込むこと
も可能
Python, Java用にAPIあり
BigQueryは分析用
データモデルは基本的にRDBと同じ
ただしトランザクション処理用ではなく、分析用
行の挿入(バッチもしくはストリーミング)はできるが、削除
や更新はできない
インデックスはなく、常にテーブルフルスキャン
GCSから、あるいはHTTP経由で、CSVもしくはJSONフォー
マットのデータを挿入
基本
You might be paying too much for BigQuery
課金の対象
ストレージ - $0.020 per GB / month
クエリ - $5 per TB processed (scanned)
ストリーミングインサート - $0.01 per 100,000 rows
until July 20, 2015. After July 20, 2015, $0.01 per 200
MB, with individual rows calculated using a 1 KB
minimum size.
注目すべきはストレージ
簡単な例
1TBのテーブルを毎日ロード、それぞれを一ヶ月間保持
日々のデータを毎日5回スキャンして集計
ストレージ : 

1TB * 30 (tables) = $0.020 * 1000 * 30 = $600
クエリ:

1TB * 5 (Queries) * 30 (days) = $750
データの保存形式
1. 数千台(データサイズによる)のディスクに分散保
存
2. 列指向フォーマット(ColumnIO?)
3. 列ごとに圧縮(ただし、ストレージコストは非圧縮
状態のサイズに対して課金)
BigQueryによるクエリの実行
要求されたデータが分散ファイルシステムから読まれ、コンピュートノードへ送られる
コンピュートノードは、動的にツリー構造を構成してクエリを処理する。ノード数は、
クエリやデータサイズによっては、数千台に及ぶ
クエリの結果は、分散ファイルシステムにテーブルとして書き戻される。このテーブルは
無名のこともあれば、名前付きのこともある
distributed file storage layer (tables)
compute
node
compute
node
compute
node
compute
node
compute
node
compute
node
compute
node
results
BigQueryによるクエリの実行
大きいテーブル同士のJOINや、大きいデータセットに対する GROUP BYを行う場
合、キーのハッシュを取り、関連するデータと共にキーをハッシュ値に応じたノー
ドへ送り、そのノード内でオンメモリでグループ化や結合を行う。
distributed file storage layer (tables)
compute
node
compute
node
compute
node
compute
node
compute
node
compute
node
compute
node
results
compute
node
compute
node
compute
node
compute
node
compute
node
compute
node
‘シャッフル’
上級編
You might be paying too much for BigQuery
課題:いかにスキャンを狭めるか
BigQueryにはインデックスは
なく、常にテーブル全体をフ
ルスキャン
BigQueryは列指向ストレージ
なので、必要な列だけを選択
することで、コストを下げら
れる
C1 C2 C3 C4
R1
R2
R3
R4
R5
R6
R7
R8
R8
課題:いかにスキャンを狭めるか
SELECT C1, C2, C3, C4
FROM t
赤いセルが課金対象
C1 C2 C3 C4
R1 Scaned Scaned Scaned Scaned
R2 Scaned Scaned Scaned Scaned
R3 Scaned Scaned Scaned Scaned
R4 Scaned Scaned Scaned Scaned
R5 Scaned Scaned Scaned Scaned
R6 Scaned Scaned Scaned Scaned
R7 Scaned Scaned Scaned Scaned
R8 Scaned Scaned Scaned Scaned
R8 Scaned Scaned Scaned Scaned
課題:いかにスキャンを狭めるか
SELECT C1, C3 FROM t
課金対象はC1とC3だけ
C1 C2 C3 C4
R1 Scaned Scaned
R2 Scaned Scaned
R3 Scaned Scaned
R4 Scaned Scaned
R5 Scaned Scaned
R6 Scaned Scaned
R7 Scaned Scaned
R8 Scaned Scaned
R8 Scaned Scaned
なんとなく‘SELECT *’
はだめ!
課題:いかにスキャンを狭めるか
BigQueryのテーブルには、事実上
無制限に行を保存できる
‘WHERE’節に何を書いても、テー
ブルの行はすべてスキャンされる
ので注意!
2つの回避策:
テーブルデコレータ
テーブルの分割
C1 C2 C3 C4
R1
R2
R3
R4
R5
R6
R7
R8
R9
R99999999990
R99999999991
R99999999992
R99999999993
R99999999994
課題:いかにスキャンを狭めるか
スナップショットデコレータ:
テーブルの指定した時刻のスナップショッ
トに対してアクセス 
SELECT … FROM t@1430665200000
タイムレンジデコレータ:
指定した時間の範囲内に追加された行にだ
けアクセス
SELECT … FROM t@-1430751600000
指定できるのは過去7日まで
C1 C2 C3 added
R1 4/1
R2 4/1
R3 4/1
R4 4/1
R99999999990 5/8
R99999999991 5/8
R99999999992 5/8
R69999999990 5/3
R69999999991 5/3
R69999999992 5/3
R79999999990 5/5
R79999999991 5/5
R79999999992 5/5
テーブルの編成を推測すると
バッチインサートは「ブロック」を作
る
直近7日以内に挿入されたブロック群
は、「メイン」のテーブルとは独立し
たまま置かれている
7日以上経過したブロックは、メインブ
ロックにマージされる
ストリーミングインサートされた行は、
ブロックではなくBigTableに保存される
C1 C2 C3 added
R1 4/1
R2 4/1
R3 4/1
R4 4/1
R99999999990 5/8
R99999999991 5/8
R99999999992 5/8
R69999999990 5/3
R69999999991 5/3
R69999999992 5/3
R79999999990 5/5
R79999999991 5/5
R79999999992 5/5
以上はあくまで個人的な推測です
MainBlockBlockof5/3Blockof5/5Blockof5/8
As of 2015/5/8
テーブルの編成を推測すると
バッチインサートは「ブロック」を作
る
直近7日以内に挿入されたブロック群
は、「メイン」のテーブルとは独立し
たまま置かれている
7日以上経過したブロックは、メインブ
ロックにマージされる
ストリーミングインサートされた行は、
ブロックではなくBigTableに保存される
C1 C2 C3 added
R1 4/1
R2 4/1
R3 4/1
R4 4/1
R99999999990 5/8
R99999999991 5/8
R99999999992 5/8
R69999999990 5/3
R69999999991 5/3
R69999999992 5/3
R79999999990 5/5
R79999999991 5/5
R79999999992 5/5MainBlockBlockof5/3Blockof5/5Blockof5/8
As of 2015/5/8
直近7日間に注目するのであれば、デコ
レータはコスト削減に有効!
課題:いかにスキャンを狭めるか
BigQueryでは、テーブルを日付で分割す
ることがよくある
BQ固有の表記として、FROM節内で、
テーブルをカンマ区切りで並べると簡単
にunionできる
TABLE_DATE_RANGEは便利 :
SELECT … FROM
(TABLE_DATE_RANGE(sample.T,

TIMESTAMP(‘2015-05-01’),

TIMESTAMP(‘2015-05-10’)))
T20150401
C1 C2 C3 added
R1 12:00
R2 13:23
R3 14:10
R4 14:30
T20150501
C1 C2 C3 added
R1 9:09
R2 10:12
R3 11:00
R4 13:56
T20150510
C1 C2 C3 added
R1 9:09
R2 10:12
R3 11:00
R4 13:56
課題:いかにスキャンを狭めるか
通常のRDBでは、普通はこういう分
割はやらない。エンタープライズ系の
データベースではこういった機能はあっ
ても、通常は非常に高価で、管理も面
倒
BigQueryでは、こうしてテーブルを分
割することでむしろクエリを高速化
できることがある
この違いは、数千のディスクやノード
で並行処理をするという、BigQuery
のアーキテクチャから来ている
T20150401
C1 C2 C3 added
R1 12:00
R2 13:23
R3 14:10
R4 14:30
T20150503
C1 C2 C3 added
R1 9:09
R2 10:12
R3 11:00
R4 13:56
T20150503-1
C1 C2 C3 added
R1 9:09
R2 10:12
R3 11:00
R4 13:56
課題:いかにスキャンを狭めるか
DFS Layer
compute
node
compute
node
compute
node
compute
node
compute
node
compute
node
compute
node
results
T2015
0501
T2015
0502
T2015
0503
T2015
0508
T2015
0509
T2015
0510
一つのテーブルも、実際には多くのディスクに保
存され、多くのノードによって読み込まれる.
クエリキャッシュの利用
クエリの結果は、匿名データセットに保存される。テーブ
ル名は、クエリで参照されているテーブル群の名前、それ
らの最終更新タイムスタンプ、クエリそのものから生成さ
れる名前になる。
BigQueryは、クエリを実行する際にキャッシュされた結果
があるかをまずチェックする
クエリがキャッシュされた結果を返す場合、コストはゼロ
クエリキャッシュは無料
ほぼ同じクエリを何度も実行するダッシュボードの
ようなアプリケーションの場合、クエリキャッシュ
を使うことでコストを下げることができる
クエリの結果を自分で保存して再利用することもも
ちろん可能。ただし、場合によっては同じ効果をク
エリキャッシュにお任せで得ることができる
クエリキャッシュが有効なケース
クエリが決定的(例えばNOW()があるとダメ)
テーブルがストリーミングバッファを盛っていないこと
クエリの結果が名前付きテーブルに保存されていないこと
実際には大きなクエリの結果(>128MB)はキャッシュで
きない。‘allowLargeResult’を指定して、名前付きのテー
ブルに保存しないといけない
Tips & Tricks
You might be paying too much for BigQuery
時間とコストのトレードオフ
概して、データモデルを正規化すると、
データサイズは小さくなる。すなわちBigQueryで
はコストが下がる
特に複雑なクエリを大きなテーブルで実行すると、
CPUやネットワークトラフィックは大量に消費さ
れる
時間とコストのトレードオフ
オンプレミスでは、「コスト」というとCPU、ネットワーク、ストレー
ジで考える
BigQueryを使う場合:
CPUやネットワークにはコストがかかりません
CPUやnetworkを大量に消費する、例えばEACHキーワードを使うクエ
リは、処理に時間がかかる
クエリの実行がインタラクティブでなくても良いのなら、バッチモード
を使ってバックグラウンドでクエリを実行させることができる。場合に
よっては、きっちり正規化したスキーマで時間をかけてクエリを実行さ
せ、コストを下げることもできる
distributed file storage layer (tables)
compute
node
compute
node
compute
node
compute
node
compute
node
compute
node
compute
noderesults
compute
node
compute
node
compute
node
compute
node
compute
node
compute
node
compute
node
compute
node
ここは無料
distributed file storage layer (tables)
compute
node
compute
node
compute
node
compute
node
compute
node
compute
node
compute
noderesults
compute
node
compute
node
compute
node
compute
node
compute
node
compute
node
compute
node
compute
node
サブクエリの最適化
例えば一つのテーブルに複数の種類のログを保存
していて、種類に応じて結合対象のテーブルを変
える場合でも、スキャンは1回
SELECT id, desc FROM 

(select l.id as id, s1.desc as desc

from samples.log l 

join samples.subTable1 s1 

on l.value=s1.subid 

where l.type=0) t1,

(select l.id as id, s2.desc as desc 

from samples.log l 

join samples.subTable2 s2 

on l.value=s2.subid 

where l.type=1) t2 DFS Layer
compute
node
compute
node
compute
node
subTalbe1 Log subTable2
compute
node
リピートフィールド
配列のようなデータを行に保存できる
SQLの標準的な仕様ではない
Oracleでいうところのマテリアライズドビューのようなもの。ユース
ケースによってはコンパクトかつ高速
ロジックを良く理解しておかないと、予想外の結果が変えることがある
ので要注意
スキーマはあまり複雑にしない(例えば深すぎるネスト)
リピートフィールド用の関数は便利。ただし組み合わせ爆発に注意(例
えばFLATTEN)
ご清聴ありがとうございました。
Questions?

BigQueryの課金、節約しませんか