Meguro.es #17 @ Drecom
2018年10月4日
自己紹介
ちきさん
GitHub/Twitter/Qiita: @ovrmrw
市ヶ谷のオプトという会社で働いています
(話すこと)
BigQueryのクエリ結果がデカいときに簡単にローカルにダウンロードする方法
BigQuery は Web UI で使いたいじゃないですか
Web UI を使うメリット・デメリット
- 
メリット - クエリを書いてすぐに実行できるのでさくさく試せる。
- クエリを保存する機能が便利。
- エンジニアじゃなくても使える。例えばビジネスの人とか。
 
- 
デメリット - 16000行を超える結果を簡単にダウンロードできない。
 
16000行で切られてしまう選択肢
 
- JSON としてダウンロード
- CSV 形式でダウンロード
- スプレッドシートに保存
たとえクエリ結果が100万行でも勝手に切られてしまう。かなしい。
かなしい例
 
ではどうすればいいのか
- クエリ結果を別テーブルに保存
- テーブルをCSVとしてGCSにエクスポート
- GCSからダウンロード
何が問題なのか
- とてもめんどくさい
- 10パターンぐらいこの流れをやるとうんざりする
- テーブル作成やGCSのファイル作成権限を作業者に付与する必要がある
BigQueryのリードオンリー権限のみでデカい結果をダウンロードしたい!
なので TypeScript で書いた
概要
BigQuery のインスタンスを生成する。
import * as BigQuery from '@google-cloud/bigquery';
const bigquery = new BigQuery();
createQueryJob() メソッドで Job を生成する。
  const job = await bigquery.createQueryJob(queryOption).then(data => {
    const [job, apiResponse] = data;
    return job;
  });
Job の getQueryResults() メソッドで結果を取得する。全件取得するまで繰り返す。
  let option = { location: 'US', maxResults: 5000 };
  const fileWriter = new FileWriter();
  do {
    const [rows, _option] = await job.getQueryResults(option);
    option = _option;
    rows.forEach(row => {
      fileWriter.writeRow(row); // 最終的にWriteStreamのwriteメソッドに渡している。
    });
  } while (option);
実行前に概算コストを表示するので思わぬ課金を防げるぞ
statistics: {
  "計算MB": 34.02571105957031,
  "計算GB": 0.03322823345661163,
  "キャッシュヒット": false,
  "コスト(円)": 0.01833393740525935
}
!! The query will be executed after 5 seconds...
まとめ
- Web UI を使うとデカい結果をダウンロードするのはとてもめんどくさい。
- API を叩いてダウンロードしよう。
- ダウンロードは複数回に分けて、ファイルへの書き込みはストリームを使おう。
- ストリームと RxJS を組み合わせるととっても簡単だ。


