Carpe Diem

備忘録

BigQueryからBigtableへアクセスしてデータ分析

概要

Bigtableは数十億行、数千列規模に拡張可能な分散型NoSQLですが、

  • 特定のカラムファミリのみ持つ行を全て抽出する

といった時にcbt(CLIツール)やSDKではiterateしてデータをハンドリングするため、大規模データ分析の用途では使いづらさがあります。

そこでBigQueryの外部テーブルとして扱うことで、SQLを用いて簡単に条件に基づいたデータのみ抽出することが可能になります。

外部テーブルの作成

環境

以下の環境であると仮定して進めます。

項目 設定値
GCPプロジェクト project-a
Bigtableインスタンス bigquery-access-test
Bigtableテーブル sensor
Bigtableリージョン asia-northeast1
BigQueryデータセット my_dataset
BigQueryデータセットロケーション asia-northeast1

Bigtableには

  • daily
  • temp

といったカラムファミリが存在しており、次のような縦長のテーブルになっています。

行キー 列データ
garden#20150301 daily:temp:20.4
garden#20150302 daily:temp:21.2
garden#20150303 daily:temp:21.0
garden#20150304 daily:temp:25.1
garden#20150305 daily:temp:22.2
... ...
garden#20150331 daily:temp:20.4

外部テーブルの作成

例えばmy_bigtableという外部テーブルを作成するとします。
BigQueryで次のクエリを実行します。

CREATE EXTERNAL TABLE my_dataset.my_bigtable
OPTIONS (
  format = 'CLOUD_BIGTABLE',
  uris = ['https://googleapis.com/bigtable/projects/gcp-abema-playground/instances/bigquery-access-test/tables/sensor'],
  bigtable_options =
    """
    {
      columnFamilies: [
        {
          "familyId": "daily",
          "type": "STRING"
        }
      ],
      readRowkeyAsString: true
    }
    """
);

uris

urisは次のフォーマットで用意します。

https://googleapis.com/bigtable/projects/project_id/instances/instance_id[/appProfiles/app_profile]/tables/table_name

ref: https://cloud.google.com/bigquery/docs/create-bigtable-external-table?hl=ja#bigtable-uri

bigtable_options

bigtable_optionsはカラムファミリやカラム修飾子の設定などを行います。
詳細はBigtable Optionsに書いてあります。

typeは以下の値が設定可能です。

  • BYTES
  • STRING
  • INTEGER
  • FLOAT
  • BOOLEAN
  • JSON

指定しない場合デフォルトでBYTES型として設定されます。

ref: https://cloud.google.com/bigquery/docs/reference/rest/v2/tables#bigtablecolumnfamily

作成された外部テーブル

クエリが成功すると次のようなスキーマのテーブルが作成されます。

今回dailyカラムファミリは指定しましたが、tempカラムファミリは未指定だったので先程の説明通りBYTESになっていることが分かります。

注意点

環境のところで書きましたが、

は同じである必要があります。異なる場合次のようなエラーが出てBigQueryでクエリが実行できません。

Cannot read and write in different locations: source: asia-northeast1, destination: US

これはマルチリージョンとシングルリージョンで違う場合も発生するので注意して下さい。

ref: BigQuery の 外部テーブルに GCS 使おうとして location でダメだった

データ分析

縦長のクエリであれば基本的に1カラムファミリに1データになるので、次のようにクエリを書きます。

SELECT *
FROM `my_dataset.my_bigtable`
WHERE daily.column[0].cell[0].value IS NOT NULL

必要な条件を設定してクエリを投げれます。

SELECT *
FROM `my_dataset.my_bigtable`
WHERE daily.column[0].cell[0].value > "20"

その他

パフォーマンス上の考慮

BigQuery から Bigtable に対してクエリを実行すると、Bigtable の CPU サイクルが消費されます。
なので大規模なデータを分析対象にすると、BigtableをOLTPに利用している場合悪影響を与えてしまいます。

なので

ref: パフォーマンスに関する注意事項

まとめ

BigtableをBigQueryの外部テーブルとして扱うことで、大規模なBigtableデータを分析可能な形にすることができるようになります。

参考