新機能 BigQuery Omni を使ってみた part 1 ～導入編～

## はじめに

本記事は Location Tech Advent Calendar 2021 by LBMA Japan 4日目の投稿です。
[unerry, Inc.](https://www.unerry.co.jp/) にてデータサイエンティストを務めます、Mario です。

unerry ではデータに強い会社であることを掲げ、全社員が BigQuery を使えます。
Google Cloud と位置情報データの親和性は非常に高く、また使いやすさと拡張性も相まって当社のコア基盤として広く深く活用しています。
ただ、一部の業務や社外とのデータ連携においては AWS も利用しており、マルチクラウドへの対応は年々重要性を増しています。

## BigQuery Omni とは

2021月10月12日、毎年恒例の Google Cloud Next で BigQuery Omni の一般提供を開始したとの発表がありました。

BigQuery はビッグデータを超高速で分析できるデータウェアハウスとして有名ですが、分析するには Google Cloud 上にデータを置く必要がありました。
BigQuery Omni はこの課題を解決する機能で、__AWS や Azure （以下、外部ストレージ）に置いたデータも転送する必要なく、使い慣れたインターフェースで直接 BigQuery から分析することができる__ようになります。また、クエリの結果を直接外部ストレージに書き込むこともできます。
つまり、組織内で複数のクラウド環境を利用していても、一ヵ所でデータを高速に分析できるようになりました。

裏側の仕組みとしては、Google Cloud 上の Anthos Cluster に BigQuery 同様の Dremel エンジンが実装され、直接外部ストレージを参照して演算、リターンします。


## 使い方

使い始めるにあたって結構苦労したので記事にまとめることにしました。
本記事は、AWS S3 に置かれたデータを分析対象とし、言語はいずれも英語環境の前提でご説明します。

大まかなステップは以下です。

- [はじめに](#はじめに)
- [BigQuery Omni とは](#bigquery-omni-とは)
- [使い方](#使い方)
  - [1. BigQuery 側のプロジェクト作成 ＆ API の有効化](#1-bigquery-側のプロジェクト作成--api-の有効化)
  - [2. データの用意 on AWS s3](#2-データの用意-on-aws-s3)
  - [3. AWS Policy 作成](#3-aws-policy-作成)
  - [4. AWS Role 作成](#4-aws-role-作成)
  - [5. BigQuery Data Source からコネクターを作成](#5-bigquery-data-source-からコネクターを作成)
  - [6. 生成された Identity で AWS Role Trust Relationship の External ID を更新](#6-生成された-identity-で-aws-role-trust-relationship-の-external-id-を更新)
  - [7. BigQuery で External Data Table を作成](#7-bigquery-で-external-data-table-を作成)
  - [8. Slot Commitment を購入＆割り当て](#8-slot-commitment-を購入割り当て)
  - [9. クエリ実行](#9-クエリ実行)
- [さいごに](#さいごに)
- [Reference](#reference)


### 1. BigQuery 側のプロジェクト作成 ＆ API の有効化

前提ですが、BigQuery のプロジェクトが無ければ始まりませんので、ここでは割愛します。

また、[BigQuery Connection API](https://console.cloud.google.com/apis/library/bigqueryconnection.googleapis.com) および [BigQuery Reservation API](https://console.cloud.google.com/apis/library/bigqueryreservation.googleapis.com) (Slot Commitment を使うため) を有効にする必要があります。

### 2. データの用意 on AWS s3

こちらも詳細は割愛しますが、データを AWS S3 に保存します。現状、BigQuery で利用できる S3 バケットのリージョンは `aws-us-east-1` のみのようです。

### 3. AWS Policy 作成

[AWS IAM ページ](https://console.aws.amazon.com/iam) の左のメニューから、`Access Mnagement` -> `Policies` -> 右側の `Create Policy` -> `JSON` タブを開く。

以下のJSONコードの内、`BUCKET_NAME` を分析対象のデータが保存されている S3 バケットの名前に変えてからコピペしましょう。

```JSON
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:ListBucket"],
      "Resource": ["arn:aws:s3:::BUCKET_NAME"]
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject"
      ],
      "Resource": ["arn:aws:s3:::BUCKET_NAME/*"]
    }
  ]
}
```

`Next: Tags` （必要に応じて設定する。スキップでも問題なし。） -> `Next: Review` -> `Name` に任意のポリシー名を設定 -> `Create policy` でポリシー作成。

`arn:aws:iam::AWS_ACCOUNT_ID:policy/POLICY_NAME` が作成されるのでメモしておく。


### 4. AWS Role 作成

[AWS IAM ページ](https://console.aws.amazon.com/iam) 左のメニューから、`Access Mnagement` -> `Roles` -> 右側の `Create Role` -> `Select type of trusted entity` から `Web identity` を選択する。

下の `Choose a web identity provider` でプルダウンリストから `Google` を選択する。（日本語のマニュアルだと `Another AWS account` を選択するようにとの指示があるが、これだとうまくいかない。。。）

`Audience` に仮の数値 `00000` などを入れ、`Next: Permissions` -> 上で作成した IAM ポリシー名の左のチェックボックスにチェックを入れ、`Next: Tag` -> `Next: Review` -> `Role name` に任意のロール名を設定し、`Create role` でロールを作成する。

ロールの一覧画面に戻り、作成したロール名を押して、Summary の `Role ARN` にある `arn:aws:iam::AWS_ACCOUNT_ID:role/ROLE_NAME` をメモする。


### 5. BigQuery Data Source からコネクターを作成

[BigQuery コンソール](https://console.cloud.google.com/bigquery) の左のメニューから `+ ADD DATA` を押し、`External data source` を選択する。

`External data source` ペインが開くので、以下の情報を記入する。

- 接続タイプ | Connection type = `AWS (via BigQuery Omni)`
- 接続 ID | Connection ID = XXX（任意）
- 接続ロケーション | Conncetion location = `aws-us-east-1`
- （省略可）分かりやすい名前 | Friendly name = XXX（任意）
- （省略可）説明 | Description = XXX（任意）
- AWS ロール ID | AWS role id = `arn:aws:iam::AWS_ACCOUNT_ID:role/ROLE_NAME` (上でメモした `Role ARN` を入力)

元の画面に戻り、左のテーブルメニューから`External connections`から作成した接続IDを選び、`BigQuery Goole identity` をメモする。


### 6. 生成された Identity で AWS Role Trust Relationship の External ID を更新

[AWS IAM ページ](https://console.aws.amazon.com/iam) に戻って、先ほど作成したロールの詳細画面を開き、以下２点を設定する。

- `Maximum session duration` を `12 hours` に切り替える。
- 同画面下の `Trust relationships` -> `Edit trust relationship` を押し、以下のJSONコードの内、`IDENTITY_ID` （例通りなら0000が入っている）を先ほどでメモした `BigQuery Goole identity` に変えてからコピペする。


```JSON
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "accounts.google.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "accounts.google.com:sub": "IDENTITY_ID"
        }
      }
    }
  ]
}
```

`Update Trues Policy` を押してポリシーを更新する。


### 7. BigQuery で External Data Table を作成

[BigQuery コンソール](https://console.cloud.google.com/bigquery) 左のナビゲーションパネルから先ほどコネクターを作成したプロジェクトを展開し、右の詳細パネルから `Create table` を押し、テーブル作成ペインを開く。（データセットを作成していない場合は先にそれを行う。ここでは割愛。）
   
  - ソース | Source
    - テーブルの作成元 | Create table from = `Amazon S3`
    - S3 パスを選択 | Select  S3 path = `s3://BUCKET_NAME/PATH`
    - ファイル形式 | File format = 読込対象テーブルの形式に合わせる（任意。CSV, JSON, Avro, Parquet, ORC, Google Sheet から選択可）
  - 出力先 | Destination
    - プロジェクト名 | Project name および データセット名 | Dataset name は原則デフォルトのままでOK（必要に応じて変える）
    - テーブルタイプ | Table type = 変更不可（`External table` にセットされていることを確認）
    - テーブル名 | Table name = テーブル名（任意）
    - 接続 ID | Connection ID = 先ほどで作成した接続 ID を選択する。（選択不可の場合もある）

`Create table` を押すとテーブルが作成される。が、まだ実行できない・・・！


### 8. Slot Commitment を購入＆割り当て

現状、BigQuery Omni はデータスキャン従量のオンデマンド課金ではなく、スロット従量課金の定額プランを用いる必要がある。

[BigQuery Rerservations](https://console.cloud.google.com/bigquery/admin/reservations/capacity-commitments) のページの上のメニューから `Buy Slots` を押し、Configure にて以下を選択・記入。

  - Commitment duration = `Flex` (継続利用の場合は `Monthly` or `Annual`を推奨)
  - Location = `Amazon US East (N. Virginia)`
  - Number of slots = `100` (現状、100以外は適用できない)

`Next` を押し、 Confirm and submit に `CONFIRM` を入力して `PURCHASE`、`VIEW SLOT COMMITMENTS` を押して元の画面に戻る。

右の `Location` プルダウンリストから `Amazon US East (N. Virginia)` を選択し、`RESERVATIONS` タブから ID = `default` の Actions (3 dots) から `Create assignment` を選択する。

`Create assignment` ペインメニューが開くので、BROWSE から適用したいプロジェクトを選択（組織、フォルダ単位の選択も可）する。

### 9. クエリ実行

[BigQuery コンソール](https://console.cloud.google.com/bigquery) に戻る。その際、先ほど選択したプロジェクトがクエリ実行環境として選択されていることを確認する。

作成したテーブルを対象に、いつも通りのクエリを書く。ただし、インタラクティブクエリでの結果は 2MB と制限されているので、それ以上になる場合は外部DBへ直接エクスポートする。
詳しくは公式ドキュメントの [Exporting query results to Amazon S3 ](https://cloud.google.com/bigquery-omni/docs/aws/export-results-to-s3#google-cloud-console) を参照。


## さいごに

以上がクエリ実行までの手順となります。
Flex Slot を使っている場合、終わったら BigQuery Slot Reservation を削除することを忘れないでください。

設定のひと手間はありますが、これで外部データソースを直接BigQueryから行うことが出来るようになります。

明日は実際に使ってみてのパフォーマンスなどをレビューしていきます！

## Reference

- [BigQuery Omni 公式ドキュメント](https://cloud.google.com/bigquery-omni/docs/introduction)