TROCCOで同じカスタム変数ループ（文字列展開）を複数のジョブで使い回す方法

## どんな方法？

TROCCOで、文字列展開で行なっているカスタム変数ループについて、文字列展開している内容を一度テーブル化（＝永続化）しておくことで別のジョブでも使いまわせるようにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489030/d84221b9-fe59-4dd6-806b-4875c1557ae3.png)

## どんな時に使える？

### サンプルケース

今回、次のような状況を考えます。

GA360のデータ[^1]を使って、ユーザ毎のPV数を月次で集計しているデータパイプラインがあります。集計テーブルはデータ提供先の都合で国ごとに別テーブルとなっています。

[^1]: 今回はBigQueryの[一般公開データセットのデータ](https://console.cloud.google.com/marketplace/product/obfuscated-ga360-data/obfuscated-ga360-data?inv=1&invt=Abqbyg)を使います

```mermaid
graph LR
    GA360
    job([集計ジョブ])
    united_states_table[集計テーブル<br />（United States）]
    india_table[集計テーブル<br />（India）]
    etc_table[...]

    GA360 --> job
    job --> united_states_table
    job --> india_table
    job --> etc_table
```

```sql:集計クエリ
CREATE OR REPLACE TABLE 
  `YOUR_PJ_ID.YOUR_DATASET.user_pv_by_country___$iso_country_code$` -- $iso_country_code$の値はパイプライン側から与えられる
AS

SELECT
  geoNetwork.country,
  fullVisitorId,
  COUNT(totals.pageviews) AS pageviews
FROM
  `bigquery-public-data.google_analytics_sample.ga_sessions_*`,
  UNNEST(hits) AS hits
WHERE
  _TABLE_SUFFIX BETWEEN '$start_date$' AND '$end_date' -- $start_date$, $end_date$の値はパイプライン側から与えられる
  AND hits.type = 'PAGE'
  AND geoNetwork.country = '$country$' -- $country$の値はパイプライン側から与えられる
GROUP BY
  1,2
```

このデータパイプラインに対して、集計ジョブのクエリをリファクタリングしました（以下、リファクタリング前のクエリを「既存クエリ」、後のクエリを「新クエリ」と呼ぶこととします）。実際に本番のジョブへ適用する前に既存クエリから差分が出ないことを確認したいです。

ただし、全テーブルに対して差分チェックを行うのはデータ量やテーブル数の多さから物理的に困難だったため、特定の1ヶ月について、特にデータ量の多い（＝差分が出てしまった場合に影響が大きい）上位5テーブルに絞って差分チェックを行うことになりました。

:::note

**補足：理想としては…**

今回挙げた状況の場合、事前に下記の改修を入れておくのが理想かと思います。

* 元々の集計ジョブの責務を「集計ジョブ」「データ提供ジョブ」へ分割
* 集計ジョブにて全国での集計テーブルを作成し、そこから国ごとにデータ提供を行う形式へ変更

```mermaid
graph LR
    GA360
    agg_job([集計ジョブ])
    delivery_job([データ提供ジョブ])
    all_table[集計テーブル<br />（全国）]
    united_states_table[集計テーブル<br />（United States）]
    india_table[集計テーブル<br />（India）]
    etc_table[...]

    GA360 --> agg_job --> all_table --> delivery_job
    delivery_job --> united_states_table
    delivery_job --> india_table
    delivery_job --> etc_table
```

全国での集計テーブルが存在していることで、今回のような差分チェックがやりやすくなります。

とはいえ、改修工数や優先度の問題で理想通りにはいかないこともあるかと思います。そういった場合に本記事の方法が役に立てば幸いです。
:::

### 差分チェック用TROCCOワークフロー

1テーブルずつ差分チェックを行うのは大変なため、専用のワークフローをTROCCOで組んでみます。

単純に組むと次のようなワークフローになるかと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489030/00b0023c-55dd-4dca-a577-2f66e469852d.png)

3つのジョブのカスタム変数ループにはデータ量の多い上位5テーブル（＝5カ国）を指定しています。期間については適当な1ヶ月[^2]を指定しています。

[^2]: 今回は一般公開データセットにて公開されている2017年8月の1ヶ月間を使用しています

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489030/17fdb6a8-335c-4562-816e-ee7347acc486.png)

…が、3つのジョブに全く同じカスタム変数ループを設定する作業は少し面倒です。設定ミスを起こしやすいですし、比較対象を変更したくなった（5テーブル→10テーブルへ増やす、別の国へ変更する、など）際に面倒が増えてしまいます。

### 本記事の方法を使ってみる

そこで、カスタム変数ループで文字列展開している内容を一度テーブル化します。すると、これまで文字列展開で指定していた部分をBigQueryのクエリ結果で指定できるようになり、前述の課題を解消できます。

ワークフローは次のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489030/bd8b9da8-f187-4adb-8dd0-79cc98abe240.png)

カスタム変数指定用のジョブでは次のクエリを実行します。

```sql
CREATE OR REPLACE TABLE 
  `YOUR_PJ_ID.YOUR_DATASET.user_pv_by_country___diff_target`
AS

SELECT "us" AS iso_country_code, "United States" AS country
UNION ALL
SELECT "in", "India"
UNION ALL
SELECT "ca", "Canada"
UNION ALL
SELECT "uk", "United Kingdom"
UNION ALL
SELECT "de", "Germany"
```

カスタム変数ループの設定は次のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489030/e81efaa9-d61b-4e27-97f1-15cf39e7e15e.png)

これで、差分チェックの対象を増やしたり変更したりしたい場合はカスタム変数指定用ジョブのクエリを変更するだけで簡単に対応できるようになりました。

## まとめ

この記事では、文字列展開されたカスタム変数ループを複数のジョブで使い回す方法とそれが有用なサンプルケースについて紹介しました。

TROCCOは定期実行するデータパイプラインの構築だけでなく、本記事のようなデータパイプラインへのスポット検証にもサクッと使えるので、とても重宝しています。すでに動いているデータパイプラインだと柔軟な対応が中々難しいことも多いかなと思いますので、そういった部分をTROCCOでカバーできると良いのかなと思っています。

フリープランも用意されているので、検証用途での利用でも始めやすいかなと思います。

サービスページ:

https://primenumber.com/trocco

フリープラン申込ページ:

https://primenumber.com/trocco/contact/free-plan

ここまでお読みいただきありがとうございました！