Snowflake MigrationClickHouse Workshops

01 ソース環境

実際の顧客デプロイを反映した Snowflake 環境をプロビジョニングします — 5,000万行、dbt Medallion パイプライン、稼働中の trip プロデューサー、3つの Superset ダッシュボード。

開始チェックポイント

モジュール00が完了していること。ツールチェーンがインストールされ、両方のクラウドのトライアル アカウントが有効で、リポジトリがクローンされ、dbt-snowflake の仮想環境が構築されていること。 このモジュールは約45分かかり、およそ2〜4 Snowflake クレジットを消費します。

なぜ必要か

おもちゃのソースを相手にマイグレーションを計画することはできません。数行しかないフラットな テーブル1つでは、実際のマイグレーションを難しくしているあらゆる判断を回避できてしまいます。この モジュールでは、その代わりに実際の顧客デプロイの形を作ります。半構造化 JSON を保持する VARIANT カラム、CDC ストリーム、スケジュールされたタスク、増分の MERGE パイプライン、そして それらすべての上で読み取りを行う BI レイヤーです。これらのすべてが、モジュール02では具体的な マイグレーションの判断になります。このモジュールは、その判断が出てきたときに抽象論ではなく 実物を指し示せるようにするために存在します。

概念 — 内部の仕組み

インフラ(Terraform)。 setup.sh を実行すると、次がプロビジョニングされます。

  • ウェアハウス — TRANSFORM_WH(SMALL、ELT 用)と ANALYTICS_WH(MEDIUM、BI 用)、 それに月50クレジットで上限を設けたリソースモニター(ANALYTICS_WH_MONITOR)。
  • データベース — NYC_TAXI_DB、3つのスキーマ(RAW、STAGING、ANALYTICS)を持ちます。
  • ロール — TRANSFORMER_ROLE、ANALYST_ROLE、DBT_ROLE、LOADER_ROLE。

Snowflake のソース環境: 一度きりの合成ジェネレーターと継続稼働する Docker の trip プロデューサーが NYC_TAXI_DB に挿入し、3つの Superset ダッシュボードが analytics ウェアハウス経由で読み取る

Medallion の形。 データは NYC_TAXI_DB の中を3つのレイヤーを通って進みます。

  • RAW — TRIPS_RAW(5,000万行の合成 trip 行。アプリのテレメトリを模した TRIP_METADATA VARIANT カラムを含みます — これが JSON のマイグレーション課題です)と、ディメンション テーブル(DIM_TAXI_ZONES、DIM_PAYMENT_TYPE、DIM_VENDOR)。
  • STAGING — 型を整え、VARIANT カラムをフラット化する dbt の view。
  • ANALYTICS — dbt のテーブルと増分モデル: fact_trips(5,000万行、MERGE 戦略)、 4つのディメンションテーブル、そして agg_hourly_zone_trips(増分の集計)。

このパイプラインを dbt とは独立に自走させている Snowflake のオブジェクトが2つあります。

  • TRIPS_CDC_STREAM — TRIPS_RAW 上の Change Data Capture ストリーム。
  • CDC_CONSUME_TASK — そのストリームを5分ごとに読み取ります(RAW で動作し、セットアップ中に resume されます)。そして HOURLY_AGG_TASK は、時間別集計を1時間ごとにリフレッシュします (STAGING で動作し、dbt のビルド後に resume されます)。

NYC_TAXI_DB の内部: VARIANT メタデータカラムを持つ TRIPS_RAW が CDC ストリームとスケジュールされた consume タスクに供給し、一方 dbt が staging view を、続いて fact・ディメンション・時間別集計テーブルをビルドする

Superset。 3つのダッシュボードはすべて ANALYTICS_WH を通じて ANALYTICS スキーマから 読み取ります。どれも RAW や STAGING に直接触れません。この読み取り経路が、ワークショップの 後半で ClickHouse 側に再現するものです。

手順1 — 認証情報を設定する

cd "$(git rev-parse --show-toplevel)/workshop_public/snowflake_migration_lab/01-setup-snowflake"

cp .env.example .env
# Edit .env with your Snowflake credentials

cp dbt/nyc_taxi_dbt/profiles.yml.example ~/.dbt/profiles.yml
# Edit ~/.dbt/profiles.yml with your account details

.env と ~/.dbt/profiles.yml はどちらも gitignore されています。Snowflake のアカウント、 ユーザー、パスワードを保持するファイルです。どちらも決してコミットしないでください。

手順2 — セットアップを実行する

cd "$(git rev-parse --show-toplevel)/workshop_public/snowflake_migration_lab/01-setup-snowflake"
source .env && ./setup.sh

これには 5〜10分 かかります。その大半は TABLE(GENERATOR) で5,000万行の合成 trip データを 生成する時間です。setup.sh は Terraform のインフラをプロビジョニングし、TRIPS_RAW に シードを投入し、dbt のビルドを実行し、Docker Compose(trip プロデューサーと Superset)を 一気に立ち上げます。

手順3 — プロデューサーと Superset を起動する

setup.sh は正しい環境で Docker Compose を立ち上げ、Superset に Snowflake 接続を登録し、 3つのダッシュボードすべてを自動的にインポートします。

superset/dashboards/ にコミットされているダッシュボードの ZIP は、sqlalchemy_uri が プレースホルダー(LAB_USER、MYORG-MYACCOUNT)に置き換えられています。自動インポートは あなたの .env から URI を再設定するので、setup.sh を実行する場合はこれが透過的に処理されます。 代わりに Superset の UI から ZIP を手動でインポートすると、作成される接続はそれらの プレースホルダーを使うため接続できません。その場合は、あとから接続を編集して実際の Snowflake アカウントを指すようにしてください。

Superset を手動で再起動する必要がある場合は次のようにします。

cd "$(git rev-parse --show-toplevel)/workshop_public/snowflake_migration_lab/01-setup-snowflake/superset"
docker-compose --env-file ../.env up -d

--env-file ../.env フラグは、親ディレクトリから環境変数を読み込みます。

Superset ダッシュボードのデータソース: 3つの運用ダッシュボードが analytics ウェアハウス経由で analytics スキーマを読み取る

3つのダッシュボードは Operations Command Center、Executive Weekly Report、Driver & Quality Analytics です(最後のものは意図的に遅くしてあります。ワークショップ後半での ClickHouse ベンチマークのターゲットです)。データソース、チャート、フィルターを含むダッシュボードの 完全な構築については、 Superset on Snowflake を参照してください。

手順4 — dbt を最新に保つ

trip プロデューサーは TRIPS_RAW に毎分約60件の trip を継続的に挿入します。作業中も fact_trips と agg_hourly_zone_trips を最新に保つため、別のターミナルで dbt のリフレッシュ ループを実行してください。

cd "$(git rev-parse --show-toplevel)/workshop_public/snowflake_migration_lab/01-setup-snowflake"

# Default: refresh every 5 minutes (auto-sources .env)
./scripts/run_dbt.sh

# Custom interval
./scripts/run_dbt.sh --interval 15m

# Run once and exit
./scripts/run_dbt.sh --once

# Include dbt tests after each run
./scripts/run_dbt.sh --test
フラグ効果
--interval <n>実行間隔: 30s、5m、1h、または秒数のみ(デフォルト: 5m)
--onceリフレッシュを1回だけ実行して終了する
--test各 dbt run の後に dbt test を実行する

このスクリプトは常に 増分で 実行されます。--full-refresh は決して行わないため、 プロデューサーが挿入した行は保持されます。停止したいときはいつでも Ctrl-C を押してください。 ラボの残りの間は専用のターミナルで動かし続けてください。モジュール03でもこれに依存しています。

手順5 — クエリライブラリを見てみる

cd "$(git rev-parse --show-toplevel)/workshop_public/snowflake_migration_lab/01-setup-snowflake"

クエリのディレクトリ(workshop_public/snowflake_migration_lab/01-setup-snowflake/queries/)には、 注釈付きの SQL ファイルが7本入っています。どれもいま構築した Snowflake 環境に対して実行できます。 そしてそれぞれに、モジュール02で ClickHouse へ変換することになる、意図的なマイグレーション課題が 仕込まれています。

クエリ構文マイグレーション課題
Q1DATE_TRUNC、DATEADD構文の細かな差異
Q2ウィンドウ関数の ROWS BETWEENClickHouse でもほぼ同一
Q3QUALIFYClickHouse では v24.5 以降ネイティブ対応 — ここでは移植性のためサブクエリに書き換える
Q4LATERAL FLATTEN対応物なし — JSONExtract を使う、または事前にフラット化する
Q5VARIANT のコロンパスJSONExtractFloat/JSONExtractString に置き換える
Q6MERGE INTO対応物なし — ReplacingMergeTree を使う
Q7Snowflake Streamsカットオーバー時に廃止 — ライブ書き込みはプロデューサー経由で直接 ClickHouse へ

次に進む前に、各ファイルを開いて自分の Snowflake 環境に対して実行してください。各クエリの コメントブロックには ClickHouse での対応方法の下書きがすでに書かれています。その側を実際に書いて 実行するのはモジュール02です。

完了の確認方法

cd "$(git rev-parse --show-toplevel)/workshop_public/snowflake_migration_lab/01-setup-snowflake"
source .env && ./scripts/verify_environment.sh

これは次の点を確認します。

  1. データベースとスキーマ — NYC_TAXI_DB が存在し、RAW、STAGING、ANALYTICS がある。
  2. テーブルとデータ — TRIPS_RAW に約5,000万行あり、FACT_TRIPS にデータが入っており、 ディメンションが存在する。
  3. CDC ストリーム — TRIPS_RAW 上に TRIPS_CDC_STREAM が存在する。
  4. スケジュールされたタスク — CDC_CONSUME_TASK と HOURLY_AGG_TASK が started 状態にある。
  5. CDC の稼働 — タスクが最近実行されている。
  6. プロデューサーの供給 — trip プロデューサーが継続的にデータを挿入している。
  7. Superset — BI ダッシュボードに http://localhost:8088 でアクセスできる。

手作業で確認したい場合は、ACCOUNTADMIN ロールで SHOW TASKS LIKE '%TASK' IN DATABASE NYC_TAXI_DB; を実行すると(タスクはそのロールが所有しています)、 両方のタスクが動いていることを確認できます。

まとめ

この環境には、これから数モジュールにわたって繰り返し戻ってきます。そして ./setup.sh のフル実行は 5〜10分かかるので、Terraform ファイルや dbt モデルを少し直すたびに毎回その時間を払いたくは ありません。setup.sh にはまさにそのためのフラグがあります。

フラグ使う場面
(なし)初回実行。すべてをプロビジョニングし、5,000万行の合成データを生成する(合計約12分)。
--skip-seedインフラがすでに存在し、TRIPS_RAW にすでにデータがある場合。合成データ生成をスキップする(約8分の節約)。
--skip-dbtSnowflake のオブジェクトは存在するが、dbt の変換を再実行する必要がない場合(例: Terraform の変更をテストするとき)。
--skip-supersetDocker が動いていない、またはまだ BI レイヤーが必要ない場合。
--full-refreshすべての増分モデルをゼロから再構築するよう dbt に強制する(例: スキーマ変更のあと)。

フラグは組み合わせられます。よく使う組み合わせは2つです。

# Re-run after a Terraform or SQL change — skip the ~10 min data load
./setup.sh --skip-seed

# Iterate on dbt models only — skip everything else
./setup.sh --skip-seed --skip-superset

コストに関する注記。 データのシード投入は約12分で2クレジット(約$6)、dbt のフルビルドは 約8分で1.5クレジット(約$5)です。8時間のパートナーラボセッションではさらに約12クレジット (約$36)加算されます。ウェアハウスはアイドル時に自動サスペンドするので、セッションの合間に コストは積み上がりません。パートナー1人あたり1日の合計はおよそ16クレジット、約$47です。

終了状態

Snowflake が稼働しています。NYC_TAXI_DB は完全に構築され、CDC ストリームと2つのスケジュール タスクが動作し、trip プロデューサーが TRIPS_RAW に毎分約60件の trip を書き込み、3つの Superset ダッシュボードすべてが http://localhost:8088 で立ち上がっています。

プロデューサーは動かし続けてください。 Docker Compose のスタックを停止してはいけません。また ./teardown.sh を実行してもいけません。モジュール02から05はこの環境が稼働し続けていることに 依存しており、モジュール05のカットオーバー手順では、マイグレーション中にプロデューサーが Snowflake と ClickHouse の間に作るギャップを正確に測定します。いま撤去すると、この手順まで 原因を追いにくい形でワークショップの残りが失敗します。撤去はここではなく、モジュール05の最後で 扱います。

このページの内容

Track your progress?

Optional. We email a link to confirm your address; progress records once you open it.

Please use your work email address, not a personal one.

Progress tracking also requires accepting the current Terms of Service in Privacy settings.

JA