cross-region dataset replicationとanalytics hubを使ったリージョンをまたぐデータ共有の話

本記事は[BigQuery Advent Calendar 2023](https://qiita.com/advent-calendar/2023/bigquery "BigQuery Advent Calendar 2023")の20日目の記事になります。

:::note warn
本記事では一部プレビュー版の機能を利用しているため、動作は2023年12月19日現在のものとなります。今後挙動が変わる可能性があります。ご了承ください。
:::

## はじめに
弊社では利用している外部SaaSの機能としてBigquery連携のコネクタをいろいろ利用しています。その場合、稀に起こる問題として特定のリージョンのみ連携を行うことができるサービスが存在します。このような場合、弊社ではデータ取得用のプロジェクト(Project A)からサービスへの連携プロジェクト(Project B)にデータを送り、外部SaaSへのデータ連携を行っています。このプロジェクト間でのデータ連携方法として、[BQ Datatransfer Service](https://cloud.google.com/bigquery/docs/dts-introduction?hl=ja "BQ Datatransfer Service")を利用しています。

最近では新しく[cross-region dataset replication](https://cloud.google.com/blog/ja/products/data-analytics/introducing-bigquery-cross-region-replication "cross-region dataset replication")が利用可能となり、これによりリージョンを超えたデータセットの利用が可能になりました。この機能を見ていて上記のようなプロジェクトとリージョンを跨いだ場合にも利用できるのでは？と考え、Analytics Hubと組み合わせてDatatransfer Service以外の方法で**Project AからProject Bへリージョンを跨いでデータの転送ができないか**検証を行います。この方法で連携できるならProject Aのデータが更新されたらほぼリアルタイムにProject B側のデータも更新されてデータ転送の必要が無くお得です。

Analytics Hubに関しては同じAdvent Calendarに参加されている方が記事を書いていらっしゃるので、詳細はそちらをご参照ください。

https://qiita.com/na0/items/a9a0e374b279bc913ba1

https://qiita.com/life_long_study/items/6e827a452c1b9989109e

## やること
今回の検証では以下の図のような状態を目指します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130016/750abcbd-b4d1-e3a0-4916-e93f13e91408.png)


手順は以下のように行います。

1. Project A内でUSマルチリージョンのレプリカを作成
2. Project AのデータセットをAnalytics HubでProject Bに共有
3. Project B内でUSマルチリージョンのレプリカを作成
4. Project BのデータセットのPrimaryとSecondaryを入れ替え

最終的にUSマルチリージョンのデータと `left join` をして問題なく動作するかを確認して終了とします。

### 前準備
前準備としてデータセット、テーブル、Analytics Hubのエクスチェンジとリスティングを作成します。
作成したテーブル、データセットは結果以下のような構成になります。
| project    | dataset                    | table            | region           | 備考               |
|:----------:|:--------------------------:|:----------------:|:----------------:|:------------------:|
| Project A  | test_analytics_hub          | share_test_table | asia-northeast1  | Project Aに作成したデータ  |
| Project B  | test_analytics_hub_us_data  | us_region_valid  | US               | 結合検証用データ   |

作成したデータは以下のクエリから作成しています。
```sql
-- Project Aのデータ
CREATE OR REPLACE TABLE test_analytics_hub.share_test_table AS
SELECT *
FROM UNNEST(
  ARRAY<STRUCT<user_id STRING, price INT64>>[
    ('1', 500), ('2', 1200), ('3', 900)
  ]);
```


```sql
-- Project Bの検証用データ
CREATE OR REPLACE TABLE test_analytics_hub_us_data.us_region_valid AS
SELECT *
FROM UNNEST(
  ARRAY<STRUCT<user_id STRING, name STRING>>[
    ('1', 'aaaa'), ('2', 'bbbb'), ('3', 'cccc'), ('4', 'dddd')
  ]);
```

Project Aのリスティングデータセット名は `share_test_dataset` にしました。作成時の注意点として、Analytics Hubのエクスチェンジは共有したいデータセットのリージョンと同一である必要があります。
![add_share_dataset_in_prjb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130016/912d42b2-8aa2-5f20-2c90-0a7857514f18.png)


### 1. Project A内でUSマルチリージョンのレプリカを作成
前準備で作成した `test_analytics_hub` のsecondaryとしてUSマルチリージョンのレプリカを作成します。cross-region datasetの設定はすべてクエリで行います。

```sql
ALTER SCHEMA test_analytics_hub
ADD REPLICA `us`
OPTIONS(location='us');
```

下記の結果になれば大丈夫です。
![add_replica_prja.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130016/6ccb84b5-9b66-3c1a-3502-74c287282478.png)

この操作によって、
- primary: asia-northeast1
- secondary: US

の両方にデータが作成されます。

### 2. Project AのデータセットをAnalytics HubでProject Bに共有
作成したリスティングをProject Bへ追加します。上記リスティング画面から `データセットをプロジェクトに追加` で追加を行います。
![create_link_dataset.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130016/b9b47cce-8b21-2414-b8fc-3dba0c4a0990.jpeg)

下記のようなデータセットができていれば完了です。当然データのリージョンも `asia-northeast1` のままです。
![shared_dataset.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130016/8dcbc8f4-fa04-4462-195b-9d4e96852101.png)
![show_shared_table.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130016/815186f5-87cd-386a-ee02-b1354c69822e.jpeg)

試しにリージョンが異なるデータで結合を行いますが、エラーになることが確認できます。
![show_us_tokyo_data_join_error.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130016/371e718c-671d-eac6-84df-97c6037e71c2.jpeg)


### 3. Project B内でUSマルチリージョンのレプリカを作成
2.で作成したデータセットに対してもレプリカを作成。クエリは1.とデータセット名が違うだけで他は同一です。

```sql
ALTER SCHEMA share_test_dataset
ADD REPLICA `us`
OPTIONS(location='us');
```

ここまで行うと、Project Aにはasia-northeast1とUSの両方にデータを保持しており、Project Bにはasia-northeast1とUSの両方を参照できる状態になっています。

### 4. Project BのデータセットのPrimaryとSecondaryを入れ替え
Project Bの共有データセットのUSリージョンをprimaryにします。
```sql
ALTER SCHEMA share_test_dataset SET OPTIONS(primary_replica = 'us')
```

注意点として、プライマリにしたいリージョンに食えりエディタのロケーションを合わせる必要があります。今回の場合だとUSマルチリージョンに合わせる必要があります。

方法としては `展開>クエリ設定`
![query_location.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130016/4ebe8c0a-4642-a8e3-7b47-290083ad6965.png)

`詳細オプション` から `自動ロケーション選択` のチェックを外して、USリージョンを指定。
![query_location_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130016/a001f1f2-cbd2-4b80-8bbb-bf93bbdaca5f.png)

Project B内の `share_test_dataset` のロケーションがUSになっていれば成功です。
![show_shared_table_us-region.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130016/375e388f-53f5-351b-b2ae-e90de5c27273.jpeg)


### 5. 確認
2.でエラーになったクエリを再度実行します。
```sql
select *
from test_analytics_hub_us_data.us_region_valid as validation_table
left join share_test_dataset.share_test_table as shared_table
  using(user_id)
```

問題なく実行できていることが確認できました。:raised_hands:
![test_join.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130016/3b0690f2-d2b4-e633-25ee-312f1c3e2ab9.png)

## さいごに
本記事ではcross-region dataset replicationとAnalytics Hubを利用してプロジェクトとリージョンを跨いだデータの共有を行いました。ほぼリアルタイムでデータの同期がとられるため、データ転送などを行う必要がなく個人的には好きな方法ではあるのですが、いくつか懸念点もありそうです。
最も大きいのはcross-region dataset replicationがプレビュー版の機能であることです。加えて、そもそもこの使い方無理やりすぎてどうなんだ？？という気持ちもあります。
上記を踏まえて最低でも正式なバージョンとしてリリースされるまでは待った方がいいんだろうなと感じます。~~そもそもあんまりリージョンを跨がないほうが楽だから使うSaaSを合わせてくれというのが本音です~~
それではみなさま良いお年を。

## おまけ
検証をやっていて両方のプロジェクトでasia-northeast1とUSのデータセットを持つ必要は無いかな？と思っていましたが、以下のパターンを試した結果両方にないと上手く動かなかったです。予想が含まれていますが原因も大体これかな？というのがあります。
1. Project Aのみcross-region dataset replicationで複数リージョンデータ作成
→ Project Bでprimaryとsecondaryの入れ替えが出来ない
2. Project Bのみcross-region dataset replicationで複数リージョンデータ作成
→ Analytics Hubで共有されたデータが読み取り専用だから、Project Bだけで作成しても書き込みできない？