BigQueryの課金についてざっくり5分で理解する

#はじめに

BigQueryは従量課金が基本のため、クエリ実行する機会があるならば課金の仕組みを知っておいた方が安心して利用できます。

今回はデータの活用者、クエリ実行者の視点で必要な内容を中心に説明します。
データ挿入、変更にかかる費用については割愛します。

#課金の種類 （主に2種類）

##ストレージ料金
保存しているデータ量について課金される料金です

<table>
<tr>
 <th>操作
 <th>料金
 <th>詳細
<tr>
 <td>アクティブ
 <td>GBあたり $0.02/月
 <td>毎月10GBまで無料。過去 90 日間で変更されたデータに対する保存料金。</th>
</tr>
<tr>
 <td>長期保存
 <td>GB あたり $0.01/月
 <td>テーブル毎、パーティション毎に編集有無を自動計測。<br>過去 90 日以上データが編集(追加・削除)されていない場合に適用。
</tr>
</table>
<font color='red'>クエリを実行する側は特に気にすることはない</font>
そもそも<font color='red'>かなり安い</font>。S3のデータ保存料金並に安いのでバイナリでなければとりあえずBigQueryに突っ込んどいていいレベルで安い。

##データ操作料金（クエリ）
<table>
<tr>
 <th>プラン
 <th>料金
 <th>詳細
<tr>
 <td>オンデマンド
 <td>TB あたり $5
 <td>最も一般的な利用方法。クエリの実行時に処理されたデータ量に応じて課金される。実行に用いる仮想CPUはプロジェクトごとに2,000スロット割り当てられており、十分高速な処理を期待できる。

<tr>
 <td>定額利用
 <td>1時間 $4 
     <br>月額 $2,000
 <td>100スロットの料金。100スロット単位で購入可能。
  <br> さらに年間契約でディカウント有り。
  <br> 割り当てるスロットを確保できるのでパフォーマンスは安定する。
  <br>アイドル時間も課金されるので注意。
  <br>2000スロット以上購入しないとオンデマンド以上のパフォーマンスは出ない。
</table>
多くの場合は<font color="red">オンデマンドでの利用が一般的</font>です。
TB単位のスキャンが頻繁に発生したり、SLAを確保したい場合は定額利用（フラットレート）を検討しましょう。

オンデマンド利用でのポイントは、課金対象となるのは<font color="red">クエリ実行後の取得レコードのデータ容量ではない</font>こと。
<font color="red">データ処理量に対して課金</font>されます。

###オンデマンドでのデータ処理対象とは
クエリ実行時のデータ処理容量に対して課金されます。
データ処理容量の考え方、絞り方についてみていきます。

#### 1.select句に含まれたフィールド のデータは全てデータ処理対象になる
<table>
 <tr>
  <th>id
  <th>name
  <th>value
 <tr>
  <td>1
  <td>inoue
  <td>10
 <tr>
  <td>2
  <td>kimura
  <td>10
 <tr>
  <td>3
  <td>saito
  <td>10
</table>
例えば、上記のpersonテーブルがあった時、
select * from person where id=1; 
を実行すると課金データ量は赤い文字部分のデータ

<table>
 <tr>
  <th>id
  <th>name
  <th>value
 <tr>
  <td><font color="red">1
  <td><font color="red">inoue
  <td><font color="red">10
 <tr>
  <td><font color="red">2
  <td><font color="red">kimura
  <td><font color="red">10
 <tr>
  <td><font color="red">3
  <td><font color="red">saito
  <td><font color="red">10
</table>
ポイント：where句で抽出対象を絞ってもデータ処理対象は減らない

--

同様に
select id, name from person where id=1; 
を実行すると課金データ量は赤い文字のデータ

<table>
 <tr>
  <th>id
  <th>name
  <th>value
 <tr>
  <td><font color="red">1
  <td><font color="red">inoue
  <td>10
 <tr>
  <td><font color="red">2
  <td><font color="red">kimura
  <td>10
 <tr>
  <td><font color="red">3
  <td><font color="red">saito
  <td>10
</table>
ポイント: select句で絞るとデータ処理対象は減る

--
#### 2.where句の条件判定に用いられるフィールド もデータ処理対象
select value from person where id=1; 
を実行すると課金データ量は赤い文字のデータ

<table>
 <tr>
  <th>id
  <th>name
  <th>value
 <tr>
  <td><font color="red">1
  <td>inoue
  <td><font color="red">10
 <tr>
  <td><font color="red">2
  <td>kimura
  <td><font color="red">10
 <tr>
  <td><font color="red">3
  <td>saito
  <td><font color="red">10
</table>
ポイント: select句、where句、どちらかでも指定したフィールドは処理対象になる

--

#### 3.limit句では絞れない

select * from person where id=1 limit 1; 
を実行すると課金データ量は赤い文字部分のデータ

<table>
 <tr>
  <th>id
  <th>name
  <th>value
 <tr>
  <td><font color="red">1
  <td><font color="red">inoue
  <td><font color="red">10
 <tr>
  <td><font color="red">2
  <td><font color="red">kimura
  <td><font color="red">10
 <tr>
  <td><font color="red">3
  <td><font color="red">saito
  <td><font color="red">10
</table>
ポイント:limit句では絞れない

#### 4.日付型のカラムパーティショニングで絞ることができる
日付型のカラムを条件に絞るような
select * from person where modify_date <='2020-01-01'
を実行すると課金データ量は赤い文字のデータ

<table>
 <tr>
  <th>id
  <th>name
  <th>value
  <th>modify_date
 <tr>
  <td><font color="red">1
  <td><font color="red">inoue
  <td><font color="red">10
  <td>2020-01-01
 <tr>
  <td><font color="red">2
  <td><font color="red">kimura
  <td><font color="red">20
  <td>2020-01-01
 <tr>
  <td><font color="red">3
  <td><font color="red">saito
  <td><font color="red">30
  <td>2020-01-01
 <tr>
  <td>1
  <td>inoue
  <td>10
  <td>2020-01-02
 <tr>
  <td>2
  <td>kimura
  <td>20
  <td>2020-01-02
 <tr>
  <td>3
  <td>saito
  <td>30
  <td>2020-01-02
</table>


#### 5.クラスタリングカラムで絞ることができる
テーブル作成時にクラスタリングカラムを定義することができる。
(RDBMSのindexをイメージすると近いかもれしれない)
id列をクラスタリングカラムに指定したテーブルに対し、
select * from person where id <=3
を実行すると課金データ量は赤い文字のデータ

<table>
 <tr>
  <th>id
  <th>name
  <th>value
 <tr>
  <td><font color="red">1
  <td><font color="red">inoue
  <td><font color="red">10
 <tr>
  <td><font color="red">2
  <td><font color="red">kimura
  <td><font color="red">20
 <tr>
  <td><font color="red">3
  <td><font color="red">saito
  <td><font color="red">30
 <tr>
  <td>4
  <td>sato
  <td>10
 <tr>
  <td>5
  <td>takahashi
  <td>20
 <tr>
  <td>6
  <td>mizuno
  <td>30
</table>

###データ操作対象の例外（おまけ）
#### 全体のcountをとるだけだと課金対象外
select count(*) from person;
はデータ処理対象 0kb

####パーティション指定列は課金対象外
select distinct(modify_date) from person order by modify_date;
はデータ処理対象 0kb

##課金データ処理量の確認方法
コンソールでクエリを入力すると実行前にsyntaxチェックと同時に処理量をpreviewしてくれます。
実行前に確認しておけば安心して実行することができますね。

##利用量制限
###カスタムコスト管理
プロジェクトレベル、もしくはユーザーレベルで利用量の制限を行うことができます
https://cloud.google.com/bigquery/docs/custom-quotas?hl=ja

カスタムコストが設定しておくと、無茶な使い方したら上限に達して利用を止められます。
うっかり何百万円も利用してしまうというようなことはないので安心して使えますね。

※ カスタムコスト管理設定方法の記事も書きました
https://qiita.com/laha/items/fb9acb5794a14f9c2d89