データ変換パイプラインを組むとき、これまでは Stream で変更を捉え、Task で順序を並べ、MERGE で反映し……と手続きを積み上げてきました。テーブルが増えるほど、その依存グラフ(DAG)の保守自体がコストになります。Snowflake の Dynamic Tables は発想を反転させ、「最終的にこの SELECT の結果になっていてほしい」とだけ宣言すれば、変更検知・増分反映・依存順序を Snowflake が引き受けます。本稿では TARGET_LAG と自動増分リフレッシュの挙動、Streams / Tasks との使い分け、AWS(S3・Iceberg)との接点、そして検証段階で先に踏み抜いておくべきコストの落とし穴を、現場目線で整理します。
01なぜ「宣言的」なのか — 手続き的パイプラインの負債
Streams & Tasks は強力で柔軟ですが、運用の主語が常に「人」になります。どの Stream を消費し、Task を AFTER でどう連結し、MERGE でどう反映し、失敗時にどこから再実行するか——これらを設計・保守し続ける必要があります。ソース層・整形層・ディメンション・ファクト・マートと段が増えるほど、Task の依存グラフそのものが技術的負債になっていきます。Dynamic Tables はこの関係を反転させます。中間状態の手続きではなく「望ましい最終結果」を SELECT として宣言し、そこへ至る変更検知・増分適用・更新順序の決定は Snowflake に委ねる、という考え方です。
02Dynamic Table の基本 — SELECT が唯一の真実
CREATE DYNAMIC TABLE ... TARGET_LAG = '...' WAREHOUSE = ... AS SELECT ... の形で定義します。テーブルにデータを INSERT していくのではなく、クエリの結果がテーブルの中身になる、という点がすべての起点です。ある Dynamic Table が別の Dynamic Table を参照すれば、Snowflake はその参照関係から依存グラフを構成し、上流から下流へ順序付けてリフレッシュします。Task のように「AFTER」で連結を手書きする必要はありません。下図のように、整形層とディメンションが更新され、それらに依存するファクト、さらにマートへと、スナップショット整合を保ちながら伝播します。
03TARGET_LAG — 「更新間隔」ではなく「鮮度の目標」
TARGET_LAG は「データがベーステーブルからどれだけ遅れてよいか」という鮮度目標であって、固定の更新間隔ではありません。'10 minutes' のように期間で指定すると、Snowflake はベース更新から概ね10分以内に収まるようリフレッシュを自律的にスケジュールします。指定できる最小値は60秒です。もう一つの指定が DOWNSTREAM で、これは「自分では独立したスケジュールを持たず、下流の Dynamic Table が必要とするタイミングにのみ更新する」という意味です。中間層を DOWNSTREAM にしておくと、鮮度要件はマート側の一点だけを管理すればよくなります。ただし TARGET_LAG はあくまでベストエフォートで、ウェアハウスの容量やデータ量、クエリの複雑さ、パイプラインの深さによっては実ラグが目標を超えることもあります。上流に、下流より短いラグを設定しないのが原則です。
04リフレッシュモード — AUTO / INCREMENTAL / FULL
リフレッシュには増分(INCREMENTAL)と全量(FULL)、そして既定の AUTO があります。INCREMENTAL は前回リフレッシュ以降に変わった行だけを解析してマージするため、最もコスト効率が良い一方、対応する構文でクエリが書かれていることが条件になります。中央値や厳密パーセンタイル、EXCEPT / INTERSECT のような集合演算、UUID_STRING・RANDOM・SEQ 系といった非決定的な関数は、その性質上「全行を見ないと答えが変わりうる」ため増分では扱えません。重要なのは AUTO の挙動です。AUTO は作成時に一度だけ増分か全量かを解決して固定し、以後のリフレッシュで再評価しません。上流の変化で後から増分が成立しなくなった場合、モードが自動で切り替わるのではなくリフレッシュが失敗します。さらにリフレッシュモードは ALTER では変更できず、変えるには CREATE OR REPLACE / CREATE OR ALTER が必要で、当該テーブルと下流の再初期化を伴います。
SHOW DYNAMIC TABLES や INFORMATION_SCHEMA / ACCOUNT_USAGE の refresh_mode / refresh_mode_reason を見て、意図せず FULL に落ちていないかを検証環境で潰しておくのが安全です。
05Streams & Tasks / マテビューとの使い分け
Dynamic Tables は万能ではありません。INSERT / UPDATE / DELETE / TRUNCATE といった DML を直接は実行できず、業務キーで既存行を更新する MERGE(UPSERT)や、履歴を残す SCD Type 2、ストアドプロシージャや外部関数の呼び出し、条件分岐や独自リトライ、CRON による明示的スケジュール、60秒未満のニアリアルタイムが必要なケースでは、依然として Streams & Tasks が適します。逆に、結合・集計・ウィンドウ関数を含む多段の SQL パイプラインで、依存順序と増分反映を任せたいなら Dynamic Tables が定石です。単一テーブルのクエリ高速化だけならマテリアライズドビューが噛み合います。次図に判断軸を整理します。
06AWS との接点 — Dynamic Iceberg Tables と S3
Snowflake は AWS 上で動くため、Dynamic Tables はレイクハウス構成とも噛み合います。External Volume で Amazon S3 を指し示した Dynamic Iceberg Table を使えば、TARGET_LAG による自動リフレッシュの結果を Apache Iceberg 形式で S3 に書き戻せます。External Volume は IAM ロールの信頼関係で Snowflake からのアクセスを許可し、S3 側はバケットポリシーと SSE-KMS(KMS 鍵)で保護、通信経路は AWS PrivateLink で閉域化する、という AWS 側の定石をそのまま持ち込めます。これにより、生データ→整形→集計といった多層のレイクハウスを、Iceberg テーブル上で宣言的に構築できます。一点だけ設計上の注意として、Dynamic Table の定義からは外部関数やストアドを呼び出せません。Amazon Bedrock による推論や Lambda での加工といった副作用を伴う処理は、Dynamic Table の外側(別ステップ)に切り出すのが基本設計になります。
07コスト設計の落とし穴 — 検証段階で先に踏み抜く
Dynamic Tables のコストは、大きく「仮想ウェアハウスの計算」「クラウドサービス層(変更検知・コンパイル等のメタデータ処理)」「ストレージ」の三つで構成されます。上流に変化がなければウェアハウスはサスペンドしたままクレジットを消費しませんが、変更検知はデータが変わらなくてもリフレッシュ判定のたびに走ります。私たちが検証環境で先に確認したのはこの点でした。すべての Dynamic Table の TARGET_LAG を安易に一律1分へ揃えると、たとえ実データがまったく変わらなくても変更検知のチェックが積み上がり、クラウドサービス層のクレジット(日次のウェアハウス消費の一定割合を超えると課金対象)がじわじわ膨らむと分かったのです。多数の Dynamic Table を1分ラグで並べれば、1日あたりの変更検知回数は容易に数十万回規模に達します。本番ではこの結果を踏まえ、鮮度が本当に必要なマート層だけに短いラグを与え、中間層は DOWNSTREAM に寄せてチェック頻度を集約し、専用ウェアハウスの AUTO_SUSPEND を短め(例:60秒)に設定、業務時間外はパイプラインをサスペンドする——という設計にして、想定外のクレジット消費を未然に防ぎました。
08導入前チェックリスト — まとめ
Dynamic Tables は「手続きを書く」から「結果を宣言する」への移行であり、正しく使えば運用する DAG を確実に減らせます。導入前に次の観点を検証環境で押さえておくと事故を防げます。(1)その変換は本当に SELECT だけで表現できるか、MERGE や SCD2・外部関数が要らないか。(2)狙った通り INCREMENTAL に解決されるか(AUTO は作成時に固定される点に注意)。(3)TARGET_LAG は層ごとに設計し、下流に鮮度要件を集約して上流は DOWNSTREAM にしたか。(4)ウェアハウスのサイズと AUTO_SUSPEND、業務時間外のサスペンド方針。(5)DYNAMIC_TABLE_REFRESH_HISTORY 等で実ラグとリフレッシュ状況を監視できているか。この順で詰めていけば、宣言的パイプラインの手軽さと、予測可能なコストを両立できます。
参考情報(一次情報)
- Dynamic tables | Snowflake Documentation
- Set the target lag for a dynamic table | Snowflake Documentation
- Dynamic table refresh modes | Snowflake Documentation
- Dynamic tables compared to streams and tasks, and materialized views | Snowflake Documentation
- Understanding costs for dynamic tables | Snowflake Documentation
- Create a dynamic Apache Iceberg table | Snowflake Documentation
EMW は AWS 上の Snowflake で、Dynamic Tables を用いた宣言的パイプラインの設計からコスト最適化・運用監視までを一貫してご支援します。まずはお気軽にご相談ください。
相談する