フェデレーション
BigQueryでは外部データソース(GCSなど)のデータに対して直接クエリする機能をフェデレーションと呼びます。
以下の例ではGCSに保存したTPC-Hのデータを対象に性能などを見ていきます。
使い方
BigQueryに外部テーブルとして外部のデータソースのファイルを指定する必要があります。
bq mk --external_table_definition=${SCHEMA_DIR}/${SCHEMA_FILE}@${SOURCE_FORMAT}=${CLOUD_STORAGE_URI} ${BQTABLE}
${SCHEMA_FILE}
は以下のようなスキーマ定義を記載しているファイルを指定します。(以下はTPC-Hのlineitem表のスキーマ定義)
[
{"name": "L_ORDERKEY", "type": "INTEGER", "mode": "nullable"},
{"name": "L_PARTKEY", "type": "INTEGER", "mode": "nullable"},
{"name": "L_SUPPKEY", "type": "INTEGER", "mode": "nullable"},
{"name": "L_LINENUMBER", "type": "INTEGER", "mode": "nullable"},
{"name": "L_QUANTITY", "type": "FLOAT", "mode": "nullable"},
{"name": "L_EXTENDEDPRICE", "type": "FLOAT", "mode": "nullable"},
{"name": "L_DISCOUNT", "type": "FLOAT", "mode": "nullable"},
{"name": "L_TAX", "type": "FLOAT", "mode": "nullable"},
{"name": "L_RETURNFLAG", "type": "STRING", "mode": "nullable"},
{"name": "L_LINESTATUS", "type": "STRING", "mode": "nullable"},
{"name": "L_SHIPDATE", "type": "DATE", "mode": "nullable"},
{"name": "L_COMMITDATE", "type": "DATE", "mode": "nullable"},
{"name": "L_RECEIPTDATE", "type": "DATE", "mode": "nullable"},
{"name": "L_SHIPINSTRUCT", "type": "STRING", "mode": "nullable"},
{"name": "L_SHIPMODE", "type": "STRING", "mode": "nullable"},
{"name": "L_COMMENT", "type": "STRING", "mode": "nullable"}
]
${SOURCE_FORMAT}
にはCSV
またはJSON
を指定可能です。もちろんデータは${SOURCE_FORMAT}
で指定された形式になっている必要があります。
${CLOUD_STORAGE_URI}
には外部データソースのファイルを指定します。${dir}/*
のようにワイルドカード指定をすることで${dir}
配下の全てのファイルを1つのBQテーブルとして取り扱うことも可能です。
${BQTABLE}
はBigQueryのテーブル名を指定します。
性能
TPC-Hのlineitem表を使用して性能を見てみます。
また、lineitem表を1ファイル、10ファイル、100ファイルに分割した場合のそれぞれの性能を見てみます。
条件
- lineitem表のレコード数は600万件
- lineitem表のデータサイズは700MB(解凍後)
- ファイルはgzipで圧縮をしています。GCSの
Content-Encoding
にgzip
を設定しています。 - クエリは
SELECT COUNT(*) FROM lineitem
結果
ファイル数 | レイテンシ(秒) |
---|---|
1 | 115 |
10 | 15 |
100 | 8 |
- ファイルごとに並列に処理をしてくれるようで、100ファイル程度まで分割すれば、それなりに実用に耐えうる性能が出るようですね
コスト
- gzipで圧縮したとしても解凍後のサイズでコストがかかってきます
- BigQueryのデータのようにクエリで指定した列だけでなく、行全体のサイズでコストがかかってきます
まとめ
- ファイルを分割するとそれなりに実用的な性能が出ますが、コスト面を考えるとファイル全体のサイズでコストがかかってきてしまいます。頻繁に実行されるデータであれば、BigQueryに入れておく方が良いですね。adhocにたまに実行されるようなデータであればGCSに置いておいて、フェデレーションする価値もありそうです