第3章 データロード・アンロードと接続(Loading, Unloading & Connectivity, 18%)
🎯 この節の学習目標
3-4 の Streams+Tasks では、「差分を捕捉する Stream を作り、MERGE を書き、タスクをスケジュールして RESUME する」という手続きを自分で組み立てました。Dynamic Table(ダイナミックテーブル)は、この発想を逆転させます。「欲しい結果(SELECT)」と「どれくらい新鮮であってほしいか(TARGET_LAG)」だけを宣言すれば、リフレッシュの段取りは Snowflake が自動で管理する——これが宣言的パイプラインです。
-- 「この SELECT の結果を、5分以内の鮮度で保ち続けてほしい」と宣言する
CREATE DYNAMIC TABLE sales_clean
TARGET_LAG = '5 minutes'
WAREHOUSE = etl_wh
AS
SELECT sale_id,
CAST(amount AS NUMBER(10,2)) AS amount,
sale_date
FROM raw_sales
WHERE amount IS NOT NULL;
作成後は、ソースの raw_sales が変化すると、Snowflake が TARGET_LAG を満たすように自動でリフレッシュします。Stream の作成も、MERGE 文も、タスクのスケジュール管理も不要です。
Dynamic Table の鮮度はラグ(lag)=「ソースの変更が反映されるまでの遅れの目標値」で指定します。指定方法は2つあります。
| 指定 | 意味 | 使いどころ |
|---|---|---|
| TARGET_LAG = '5 minutes' など | 「ソースから最大でもこの時間以内の遅れに保つ」という鮮度目標。Snowflake がこれを満たすようにリフレッシュ間隔を調整する | パイプラインの最終段(消費者に鮮度を約束するテーブル) |
| TARGET_LAG = DOWNSTREAM | 自分では具体的な時間を持たず、下流の Dynamic Table のラグ要求に合わせて必要なときだけリフレッシュする | パイプラインの中間段。下流が必要とする頻度でだけ動くため無駄がない |
図:Dynamic Table を連ねた宣言的パイプライン。中間段は DOWNSTREAM、最終段に具体的な TARGET_LAG を置くのが定石
📝 試験のポイント
TARGET_LAG は「必ずこの間隔でリフレッシュする」というスケジュールではなく、鮮度の目標値です。また、パイプラインを連ねる場合に中間テーブルへ DOWNSTREAM を指定すると、下流の必要に応じてだけリフレッシュされるという趣旨の出題がされやすいので、2つの指定の役割分担を押さえましょう。
Dynamic Table のリフレッシュは Snowflake が自動で実行します。このとき、クエリの内容に応じて2つの方式が使い分けられます。
どちらを使うかはクエリの内容から Snowflake が自動判定します。ユーザーが MERGE 文や差分ロジックを書く必要はありませんが、「増分で処理できるクエリの方がコスト効率が良い」という感覚は持っておきましょう。なお、Dynamic Table の定義クエリには一部使えない構文があります(たとえば外部関数など)。細かい一覧を暗記する必要はありませんが、「どんな SELECT でも増分化できるわけではなく、制約もある」という点は覚えておいてください。
同じ「継続的な変換パイプライン」を作るにも、Streams+Tasks(手続き的)と Dynamic Tables(宣言的)では発想が異なります。
| Streams + Tasks(手続き的) | Dynamic Tables(宣言的) | |
|---|---|---|
| 何を書くか | Stream の作成、MERGE などの変換ロジック、タスクのスケジュールと依存関係(AFTER)を自分で書く | 結果の SELECT と TARGET_LAG だけを書く |
| リフレッシュ制御 | SCHEDULE / WHEN 句で自分で制御する | Snowflake が鮮度目標から自動で調整する |
| 差分処理 | Stream のメタデータ列を使って自分で実装 | 可能なら自動で増分リフレッシュ |
| 向いている場面 | ストアドプロシージャ呼び出しや通知などSQL 変換以外の処理を挟みたい、実行タイミングを厳密に制御したい | SQL で表現できる変換の連鎖を、シンプルに・少ないコードで保ちたい |
💡 具体例:同じ要件を2通りで考える
「raw_sales の変更を5分以内に集計テーブルへ反映したい」という要件を考えます。Streams+Tasks なら、CREATE STREAM → MERGE 文の作成 → SCHEDULE = '5 MINUTE' と WHEN SYSTEM$STREAM_HAS_DATA(...) のタスク作成 → ALTER TASK ... RESUME、という4段階の構築が必要です。Dynamic Tables なら CREATE DYNAMIC TABLE ... TARGET_LAG = '5 minutes' AS SELECT ... の1文で完結します。変換が SQL で書き切れるなら Dynamic Tables の方がはるかにシンプルです。
Dynamic Table のリフレッシュ状況は、次の方法で確認できます。
-- リフレッシュ履歴の確認
SELECT name, refresh_start_time, refresh_action, state
FROM TABLE(INFORMATION_SCHEMA.DYNAMIC_TABLE_REFRESH_HISTORY())
WHERE name = 'SALES_CLEAN'
ORDER BY refresh_start_time DESC;
✅ この節のまとめ
問1. Dynamic Table の TARGET_LAG = '5 minutes' の意味として最も適切なものはどれか。
正解:B
TARGET_LAG は「ソースの変更が反映されるまでの遅れをこの範囲に保ちたい」という鮮度目標で、Snowflake がそれを満たすようにリフレッシュのタイミングを自動調整します。Aのような固定スケジュールではなく、変更がなければリフレッシュを省くこともできます。Cのタイムアウトや、Dの Time Travel 保持期間とは無関係です。
問2. Dynamic Table を連鎖させたパイプラインで、中間段のテーブルに TARGET_LAG = DOWNSTREAM を指定した場合の動作はどれか。
正解:B
DOWNSTREAM を指定した Dynamic Table は自分自身の時間目標を持たず、下流の Dynamic Table が鮮度を満たすために必要なタイミングでだけリフレッシュされます。中間段の無駄なリフレッシュを避けられる仕組みです。Aのような固定間隔ではありません。Cのようにリフレッシュが止まるわけでも、Dのようにオブジェクトの種類が変わるわけでもありません。
問3. Dynamic Table のリフレッシュに関する説明として正しいものはどれか。
正解:C
Dynamic Table のリフレッシュ方式は Snowflake がクエリ内容から自動判定し、可能なら効率的な増分リフレッシュ、難しければフルリフレッシュになります。Aの差分ロジックの実装が不要である点こそが宣言的パイプラインの利点です。Bは誤りで、増分リフレッシュも存在します。Dのタスク操作は Streams+Tasks 方式の話で、Dynamic Table には不要です。
問4. Streams+Tasks ではなく Dynamic Tables を選ぶ理由として適切なものはどれか(2つ選べ)。
正解:A・B
Dynamic Tables は「結果の SELECT と鮮度目標だけを書けば、差分処理や依存関係の管理を Snowflake が自動化する」仕組みなので、AとBがそのまま利点です。CとDは逆に手続き的な制御が必要な場面であり、ストアドプロシージャの呼び出しや厳密なスケジュール制御をしたい場合は Streams+Tasks の方が適しています。