動的テーブルを作成する¶
このトピックでは、動的テーブルを作成するためのキーの概念について概説します。
開始する前に、 動的テーブルを作成するための権限 があり、動的テーブルクエリで使用されるすべてのオブジェクトで 変更追跡 が有効になっていることを確認してください。
動的テーブルの作成にはいくつかの制限があります。包括的なリストについては、 動的テーブルの制限 をご参照ください。
変更の追跡を有効にする¶
増分リフレッシュモードで動的テーブルを作成する際、クエリするテーブルで変更追跡が有効になっていない場合、Snowflakeは自動的にそれらのテーブルで変更追跡を有効にしようとします。増分リフレッシュをサポートするには、動的テーブルで使用されるすべての基本オブジェクトに対して、 ゼロ以外のTime Travel保持期間 で変更追跡を有効にする必要があります。
ベースオブジェクトが変われば、動的テーブルも変わります。ベースオブジェクトを再作成する場合は、変更トラッキングを再度有効にする必要があります。
注釈
Snowflakeは、フルリフレッシュモードで作成された動的テーブルの変更追跡を自動的に有効化しようとしません。
特定のデータベースオブジェクトで変更追跡を有効にするには、そのオブジェクトで ALTER TABLE や ALTER VIEW などのコマンドを使用します。動的テーブルを作成するユーザーには、基になるすべてのオブジェクトの変更追跡を有効化する OWNERSHIP 権限が必要です。
変更追跡が有効かどうかを確認するには、基になるオブジェクトに対して SHOW VIEWS、 SHOW TABLES などのコマンドを使用し、 change_tracking
列を調べます。
サポートされるベースオブジェクト¶
動的テーブルは以下のベースオブジェクトをサポートします。
テーブル
Snowflake管理 Apache Iceberg™ テーブル
外部管理 Apache Iceberg™ テーブル
例: 単純な動的テーブルを作成する¶
staging_table
という名前のテーブルから product_id
列と product_name
列を含む動的テーブルを作成し、次を決定するとします。
作成した動的テーブル内のデータは、
staging_table
のデータより最大で20分の遅延に設定します。mywh
リフレッシュ :ref:`<label-dynamic_tables_intro_refresh_modes> に必要なコンピューティングリソースには、ウェアハウス ` を使用します。リフレッシュモードが自動的に選択されるようにします。
Snowflakeでは、開発中のみ自動リフレッシュモードを使用することを推奨しています。詳細については、 動的なテーブル更新モードを選択するためのベストプラクティス をご参照ください。
動的テーブルを作成時に同期的にリフレッシュしたいと思っています。
リフレッシュタイプが自動的に選択され、動的テーブルが作成時に同期的にリフレッシュされるようにします。
この動的テーブルを作成するには、次の CREATE DYNAMIC TABLE SQL ステートメントを実行します。
CREATE OR REPLACE DYNAMIC TABLE my_dynamic_table
TARGET_LAG = '20 minutes'
WAREHOUSE = mywh
REFRESH_MODE = auto
INITIALIZE = on_create
AS
SELECT product_id, product_name FROM staging_table;
パラメーターの完全なリストとバリアント構文については、 CREATE DYNAMIC TABLE リファレンスをご参照ください。
Snowflake管理または外部管理の Apache Iceberg™ テーブルから読み込む動的テーブルを作成する¶
Icebergテーブルから動的テーブルを作成するのは、通常のテーブルから動的テーブルを作成するのと似ています。Snowflake管理テーブルまたは外部カタログ管理テーブルをベースオブジェクトとして使用し、通常のテーブルの場合と同様に :doc:`/sql-reference/sql/create-dynamic-table`SQL ステートメントを実行します。
Snowflakeが管理するIcebergテーブルをベーステーブルとして読み込む動的テーブルは、Snowflakeが管理するIcebergテーブルのデータをパイプラインに操作させたい場合や、他のエンジンで書き込まれたIcebergテーブルをパイプラインに操作させたい場合に便利です。外部エンジンは、Snowflake管理のIcebergテーブルに書き込めません。Snowflakeでは読み取り/書き込み、外部エンジンでは読み取り専用であることにご注意ください。
AWS GlueやApache Sparkなどのエンジンによって記述された 外部(非Snowflake)カタログ が管理するIcebergテーブルから読み込む動的テーブルは、外部データレイクからのデータを処理するのに役立ちます。外部で管理されたデータの上に動的テーブルを作成し、データを複製したり取り込んだりすることなく、Snowflakeで継続的に処理することができます。
Icebergテーブルを使用する際の制限と考慮事項¶
通常の動的テーブル および 動的Icebergテーブル のすべての制限は引き続き適用されます。
その他の情報は次のとおりです。
Icebergベーステーブルのすべての制限が適用されます。詳細については、 考慮事項と制約 をご参照ください。
Snowflakeネイティブテーブル、Snowflake管理Icebergテーブル、外部管理Icebergテーブルから読み込む動的テーブルを作成できます。
動的テーブルは、行レベルで変更を追跡する他のベーステーブルとは異なり、外部で管理されるIcebergベーステーブルの変更をファイルレベルで追跡します。外部で管理されるIcebergテーブルに対する頻繁なコピーオンライト操作(更新や削除など)は、増分リフレッシュのパフォーマンスに影響を与える可能性があります。
不変性制約を持つ動的テーブルを作成する¶
不変性制約により、動的テーブルの更新方法とタイミングをより細かく制御できます。制約により、テーブル全体が常に最新のクエリ結果を反映するのではなく、テーブルの一部が静的なままになります。
動的テーブルの特定の部分を不変としてマークすると、以下のタスクを実行できます。
既存データへの更新または削除の伝播を防止します。
条件を満たす行の挿入、更新、削除を制限します。
テーブルの他の部分の増分更新を有効にしながら、将来の変更を制限します。
テーブルの残りの部分(つまり、不変性の条件に一致しない行)は不変のままであり、リフレッシュ中に更新することができます。
不変性の制約を強制するには、CREATE DYNAMIC TABLE または ALTER DYNAMIC TABLE コマンド実行時に IMMUTABLE WHERE パラメーターを指定します。行が可変かどうかを確認するには、METADATA$IS_IMMUTABLE
列を使用します。例: SELECT * , METADATA$IS_IMMUTABLE FROM my_dynamic_table
。
IMMUTABLE WHERE 述語 は最初の更新中に無視されますが、後続のすべての更新には適用されます。フルリフレッシュモードでは、条件に一致しない行のみに再計算を制限します。増分リフレッシュモードのストリームおよび動的テーブルは、これらのフルリフレッシュテーブルから読み取ることができます。
不変性制約の使用例¶
次の例では、動的テーブルを作成し、IMMUTABLE WHERE パラメーターを使用して不変に設定します。
CREATE DYNAMIC TABLE my_dynamic_table (id1 INT)
TARGET_LAG = '20 minutes'
WAREHOUSE = mywh
IMMUTABLE WHERE ( <expr> )
AS
SELECT id AS id1 FROM staging_table;
IMMUTABLE WHERE 条件で参照される列はベーステーブルの列ではなく、動的テーブルの列である必要があります。たとえば、上記の例の IMMUTABLEWHERE 式では、id
ではなく id1
のみを使用できます。
設定できるのは動的テーブルの単一の IMMUTABLE WHERE 条件のみです。既存の述語を置き換えるには、次の例に示すように ALTER DYNAMIC TABLE コマンドを使用します。
-- Set or replace an existing predicate:
ALTER DYNAMIC TABLE my_dynamic_table SET IMMUTABLE WHERE ( <expr> );
-- Remove an existing predicate:
ALTER DYNAMIC TABLE my_dynamic_table UNSET IMMUTABLE;
動的テーブルの不変性制約を表示するには、SHOW DYNAMIC TABLES コマンドを実行します。immutable_where
列は、テーブルに設定された IMMUTABLE WHERE 制約、または何も設定されていない場合は NULL を表示します。
コンピューティングコストについては、不変性制約のコンピューティングコスト をご参照ください。
例:IMMUTABLE WHERE を使用して、ディメンションテーブルが変更された場合に古いデータの再計算を防ぐ¶
次の例では、ディメンションテーブルの行を更新すると、すべての履歴ファクトではなく、その行と結合する最終日のファクトが再処理されます。
CREATE DYNAMIC TABLE joined_data
TARGET_LAG = '1 minute'
WAREHOUSE = mywh
IMMUTABLE WHERE (timestamp_col < CURRENT_TIMESTAMP() - INTERVAL '1 day')
AS
SELECT F.primary_key primary_key, F.timestamp_col timestamp_col, D.value dim_value
FROM fact_table F
LEFT OUTER JOIN dimension_table D USING (primary_key);
例:無制限の保持動的テーブルおよび制限付き保持ベーステーブル¶
次の例では、最近追加されたデータの限定ウィンドウを持つステージングテーブルと、解析およびフィルター処理されたすべてのデータを格納する動的テーブルを作成します。
CREATE TABLE staging_data (raw TEXT, ts TIMESTAMP);
CREATE DYNAMIC TABLE parsed_data
TARGET_LAG = '1 minute'
WAREHOUSE = mywh
IMMUTABLE WHERE (ts < CURRENT_TIMESTAMP() - INTERVAL '7 days')
AS
SELECT parse_json(raw):event_id::string event_id, parse_json(raw):name::string name, parse_json(raw):region::string region, ts
FROM staging_data WHERE region = 'US';
-- Delete old staging data using Task
CREATE TASK delete_old_staging_data
WAREHOUSE = mywh
SCHEDULE = '24 hours'
AS
DELETE FROM staging_data WHERE ts < CURRENT_TIMESTAMP() - INTERVAL '30 days';
例:IMMUTABLE WHERE でフルリフレッシュする¶
Python UDTF の使用などクエリ構築の制限のために、動的テーブルがフルリフレッシュモードになっているとします。これにより通常は増分処理が妨げられますが、IMMUTABLE WHERE 句で不変リージョンを定義すると、クエリ構築制限のために上流のテーブルを完全に更新する必要がある場合でも、下流の動的テーブルが増分のままになり、パフォーマンス最適化の恩恵を受けられるようになります。
次の例は、Python UDTF を使用して増分不可能になる動的テーブルを示しています。
CREATE FUNCTION my_udtf(x varchar)
RETURNS TABLE (output VARCHAR)
LANGUAGE PYTHON
AS $$ ... $$;
CREATE DYNAMIC TABLE udtf_dt
TARGET_LAG = '1 hour'
WAREHOUSE = mywh
REFRESH_MODE = FULL
IMMUTABLE WHERE (ts < current_timestamp() - interval '1 day')
AS
SELECT ts, data, output, join_key FROM input_table, TABLE(my_udtf(data));
CREATE DYNAMIC TABLE incremental_join_dt
TARGET_LAG = '1 hour'
WAREHOUSE = mywh
REFRESH_MODE = INCREMENTAL
IMMUTABLE WHERE (ts < current_timestamp() - interval '1 day')
AS
SELECT * FROM udtf_dt JOIN dim_table USING (join_key);
不変性制約を設定する際の制限と考慮事項¶
通常の動的テーブルの制限 はすべて、引き続き適用されます。
その他の情報は次のとおりです。
存在できるのは動的テーブルの単一の IMMUTABLE WHERE 述語のみです。ALTER DYNAMIC TABLE ... SET IMMUTABLE WHERE コマンドを使った別のものの設定が、既存の述語を置き換えます。
IMMUTABLE WHERE 制約には次の項目を含めることはできません。
サブクエリ。
CURRENT_TIMESTAMP()または CURRENT_DATE() のようなタイムスタンプ関数を除く非決定性関数。タイムスタンプ関数を使用する場合は、不変領域が時間の経過とともに大きくなるように使用する必要があります。例:
TIMESTAMP_COL< CURRENT_TIMESTAMP()
is allowed butTIMESTAMP_COL >CURRENT_TIMESTAMP()
ではない。ユーザー定義関数または外部関数。
メタデータ列。たとえば
METADATA$
で始まるもの。集計の結果である列、ウィンドウ関数または非決定性関数、あるいはウィンドウ関数演算子を介して渡される列。以下の動的テーブルでは、
col3
だけが IMMUTABLE WHERE 述語で使用できます。CREATE DYNAMIC TABLE aggregates TARGET_LAG = '1 minute' WAREHOUSE = mywh AS SELECT col1, SUM(col2) AS col2 FROM input_table GROUP BY col3; CREATE DYNAMIC TABLE window_fns TARGET_LAG = '1 minute' WAREHOUSE = mywh AS SELECT col3, SUM(col4) OVER (PARTITION BY col3 ORDER BY col4) AS col2, col5 FROM input_table;
IMMUTABLE WHERE 制約は制限なしでクローニング中および複製中にコピーされます。
バックフィルを使用して動的テーブルを作成する¶
バックフィルは、動的テーブルでソースデータをすぐに利用できるようにするゼロコピーの低コスト操作です。将来の更新のためにカスタム更新クエリを定義しながら、通常のテーブルから初期データをバックフィルする動的テーブルを作成することができます。
不変性制約を使用すると、不変リージョンのみがバックフィルされ、不変リージョンがソースと一致しなくなっても変更されません。可変リージョンは、通常通り動的テーブルの定義とベーステーブルから計算されます。
アップストリームソースと異なる場合でも、バックフィルデータは変更されないようにする必要があるため、IMMUTABLEWHERE 不変性制約 によって定義されたデータのみをバックフィルできます。
バックフィルの使用例¶
以下の例では、バックフィルされたデータを持つテーブルから新しい動的テーブルを作成する方法を示します。
各列名は、互換性のあるデータ型を持つバックフィルテーブル内で見つかる必要があり、バックフィルテーブルと同じ順序で表示する必要があります。バックフィルテーブルのテーブルプロパティや権限はコピーされません。
Time Travelパラメーター AT | BEFORE
が指定されている場合は、指定された時間にバックフィルテーブルからのデータがコピーされます。
例:テーブルの一部からのバックフィル¶
次の例では、my_backfill_table
から my_dynamic_table
の不変リージョンを、さらに動的テーブルの定義から可変リージョンをバックフィルします。
このシナリオでは、動的テーブルが増分リフレッシュモードで作成された場合、再初期化によって可変のすべての行が削除され、可変のリージョンのみが再入力されます。動的テーブルがフルリフレッシュモードで作成された場合、フルリフレッシュは同じ効果でトリガーされます。
CREATE DYNAMIC TABLE my_dynamic_table (day TIMESTAMP, totalSales NUMBER)
IMMUTABLE WHERE (day < '2025-01-01')
BACKFILL FROM my_backfill_table
TARGET_LAG = '20 minutes'
WAREHOUSE = 'mywh'
AS SELECT DATE_TRUNC('day', ts) AS day, sum(price)
FROM my_base_table
GROUP BY day;
例:バックフィルを使用して、動的テーブルのデータを回復または変更する¶
動的テーブルのデータや定義を直接編集することはできません。データを回復または修正するには、次の回避策の手順を完了します。
動的テーブルを通常のテーブルにクローンします。
必要に応じて、クローンされたテーブルを変更します。
編集されたテーブルから新しい動的テーブルにバックフィルします。
次の例では my_dynamic_table
が sales
ベーステーブルから日次販売データを集計します。
CREATE OR REPLACE TABLE sales(item_id INT, ts TIMESTAMP, sales_price FLOAT);
INSERT INTO sales VALUES (1, '2025-05-01 01:00:00', 10.0), (1, '2025-05-01 02:00:00', 15.0), (1, '2025-05-01 03:00:00', 11.0);
INSERT INTO sales VALUES (1, '2025-05-02 00:00:00', 11.0), (1, '2025-05-02 05:00:00', 13.0);
CREATE DYNAMIC TABLE my_dynamic_table
TARGET_LAG = 'DOWNSTREAM'
WAREHOUSE = mywh
INITIALIZE = on_create
IMMUTABLE WHERE (day <= '2025-05-01')
AS
SELECT item_id, date_trunc('DAY', ts) day, count(sales_price) AS sales_count FROM sales
GROUP BY item_id, day;
SELECT item_id, to_char(day, 'YYYY-MM-DD') AS day, sales_count FROM my_dynamic_table;
+---------+------------+-------------+
| ITEM_ID | DAY | SALES_COUNT |
|---------+------------+-------------|
| 1 | 2025-05-01 | 3 |
| 1 | 2025-05-02 | 2 |
|---------+-------------+------------|
オプションで、古いデータをアーカイブしてストレージコストを節約できます。
DELETE FROM sales WHERE ts < '2025-05-02';
ALTER DYNAMIC TABLE my_dynamic_table REFRESH;
SELECT item_id, to_char(day, 'YYYY-MM-DD') AS day, sales_count FROM my_dynamic_table;
その後、2025-05-01
で販売エラーを見つけます。条件: sales_count
は2である必要があります。これを修正するには
my_dynamic_table
を通常のテーブルにクローンします。CREATE OR REPLACE TABLE my_dt_clone_table CLONE my_dynamic_table;
クローンされたテーブルを更新します。
UPDATE my_dt_clone_table SET sales_count = 2 WHERE day = '2025-05-01'; SELECT item_id, to_char(day, 'YYYY-MM-DD') AS day, sales_count FROM my_dt_clone_table;
+---------+------------+-------------+ | ITEM_ID | DAY | SALES_COUNT | |---------+------------+-------------| | 1 | 2025-05-01 | 2 | | 1 | 2025-05-02 | 2 | |---------+-------------+------------|
編集されたクローンをバックフィルのソースとして使用し、動的テーブルを再作成します。
CREATE OR REPLACE DYNAMIC TABLE my_dynamic_table BACKFILL FROM my_dt_clone_table IMMUTABLE WHERE (day <= '2025-05-01') TARGET_LAG = 'DOWNSTREAM' WAREHOUSE = mywh INITIALIZE = on_create AS SELECT item_id, date_trunc('DAY', ts) day, count(sales_price) AS sales_count FROM sales GROUP BY item_id, day;
このアプローチにより、ベーステーブルを変更することなく、動的テーブルのデータを回復または修正できます。
SELECT item_id, to_char(day, 'YYYY-MM-DD') AS day, sales_count FROM my_dynamic_table;
+---------+------------+-------------+ | ITEM_ID | DAY | SALES_COUNT | |---------+------------+-------------| | 1 | 2025-05-01 | 2 | | 1 | 2025-05-02 | 2 | |---------+-------------+------------|
例:バックフィルを使用して動的テーブルのスキーマを変更する¶
動的テーブルのスキーマを直接変更することはできません。スキーマを更新する場合(たとえば、列を追加するなど)は、次のステップに従います。
動的テーブルを通常のテーブルにクローンします。次の例では、
sales`(:ref:`上記 <label-data-surgery-example>
)から作成したmy_dynamic_table
を使用します。CREATE OR REPLACE TABLE my_dt_clone_table CLONE my_dynamic_table;
クローンされたテーブルのスキーマを変更します。
ALTER TABLE my_dt_clone_table ADD COLUMN sales_avg FLOAT; SELECT item_id, to_char(day, 'YYYY-MM-DD') as DAY, SALES_COUNT, SALES_AVG FROM my_dt_clone_table;
オプションで、新しい列にデータを入力します。
編集されたクローンをバックフィルのソースとして使用し、動的テーブルを再作成します。
CREATE OR REPLACE DYNAMIC TABLE my_dynamic_table BACKFILL FROM my_dt_clone_table IMMUTABLE WHERE (day <= '2025-05-01') TARGET_LAG = 'DOWNSTREAM' WAREHOUSE = mywh INITIALIZE = on_create AS SELECT item_id, date_trunc('DAY', ts) day, count(sales_price) AS sales_count, avg(sales_price) as sales_avg FROM sales GROUP BY item_id, day;
このアプローチにより、ベーステーブルを変更することなく、動的テーブルのデータを回復または修正できます。
SELECT item_id, to_char(day, 'YYYY-MM-DD') as DAY, SALES_COUNT, SALES_AVG, metadata$is_immutable as IMMUTABLE from my_dynamic_table ORDER BY ITEM_ID, DAY;
+---------+------------+-------------+-----------+-----------+ | ITEM_ID | DAY | SALES_COUNT | SALES_AVG | IMMUTABLE | |---------+------------+-------------|-----------|-----------| | 1 | 2025-05-01 | 3 | NULL | TRUE | | 1 | 2025-05-02 | 2 | 12 | FALSE | |---------+-------------+------------+-----------|-----------+
バックフィルされたデータで動的テーブルを作成する際の制限と考慮事項¶
通常の動的テーブルの制限 および 不変性制約の制限 はすべて、引き続き適用されます。
次の追加制限と考慮事項が適用されます。
現在、バックフィルに使用できるのは通常のテーブルのみです。
ポリシーやタグはバックフィルテーブルからコピーされるため、新しい動的テーブルでは指定できません。
新しい動的テーブルとバックフィルテーブルのクラスタリングキーは同じである必要があります。
動的テーブル作成のベストプラクティス¶
動的テーブルのパイプラインのチェーン¶
新しい動的テーブルを定義する場合、多くの入れ子ステートメントを持つ大きな動的テーブルを定義するのではなく、パイプラインを持つ小さな動的テーブルを使用します。
動的テーブルを設定して、他の動的テーブルをクエリできます。たとえば、データパイプラインがステージングテーブルからデータを抽出して、さまざまなディメンションテーブル(customer
、product
、date
、および:code:time`など)を更新するシナリオを想像してください。さらに、パイプラインはこれらのディメンションテーブルの情報に基づいて、:code:`sales
集計テーブルを更新します。ディメンションテーブルがステージングテーブルにクエリし、sales
集計テーブルがディメンションテーブルにクエリするように構成することで、タスクグラフと同様のカスケード効果が得られます。
この設定では、sales
集計テーブルのリフレッシュは、ディメンションテーブルのリフレッシュが正常に完了した後にのみ実行されます。これにより、データの一貫性が確保され、ラグターゲットが達成されます。自動化されたリフレッシュプロセスにより、ソーステーブルの変更は適切なタイミングですべての従属テーブルのリフレッシュをトリガーします。

複雑なタスクグラフに「コントローラー」動的テーブルを使用する¶
多くのルートとリーフを持つ動的テーブルの複雑なグラフがあり、1つのコマンドでタスクグラフ全体に対して操作(ラグ変更、手動リフレッシュ、中断など)を実行したい場合、以下を実行します。
すべての動的テーブルの
TARGET_LAG
の値をDOWNSTREAM
に設定してください。タスクグラフのすべてのリーフから読み取る「コントローラー」動的テーブルを作成します。このコントローラーがリソースを消費しないようにするには、以下を実行します。
CREATE DYNAMIC TABLE controller TARGET_LAG = <target_lag> WAREHOUSE = <warehouse> AS SELECT 1 A FROM <leaf1>, …, <leafN> LIMIT 0;
コントローラーを使用してグラフ全体を制御します。例:
タスクグラフの新しいターゲットラグを設定します。
ALTER DYNAMIC TABLE controller SET TARGET_LAG = <new_target_lag>;タスクグラフを手動でリフレッシュします。
ALTER DYNAMIC TABLE controller REFRESH;
一時動的テーブルを使用してストレージコストを削減する¶
一時 動的テーブルは、データ保持期間内はデータを確実に保持し、Time Travelをサポートしますが、フェイルセーフ期間を超えてデータを保持することはありません。デフォルトでは、動的テーブルデータは fail-safe ストレージに7日間保持されます。
リフレッシュスループットが高い動的テーブルでは、ストレージの消費量が大幅に増加する可能性があります。したがって、動的テーブルを一時的に使用するのは、そのデータが永続テーブルと同じレベルのデータ保護とリカバリを必要としない場合に限ります。
一時動的テーブルを作成したり、既存の動的テーブルを一時的な動的テーブルにクローンするには、 CREATE DYNAMIC TABLE ステートメントを使用します。
動的テーブル作成のトラブルシューティング¶
動的テーブルを作成すると、初期リフレッシュはスケジュール(ON_SCHEDULE
)または作成時すぐに(ON_CREATE
)発生します。初期データ入力、つまり 初期化 は、この初期リフレッシュがいつ発生するかによって決まります。たとえば ON_CREATE
では、初期化が上流の動的テーブルのリフレッシュをトリガーする場合、初期化に時間がかかる可能性があります。
スキャンされるデータの量に応じて、初期化に時間がかかる場合があります。進行状況を表示するには、以下を実行します。
Snowsight にサインインします。
ナビゲーションメニューで Monitoring » Query History を選択します。
Filters ドロップダウンで、 SQL Text フィルターに CREATE DYNAMIC TABLE と入力し、 Warehouse フィルターにウェアハウス名を入力します。
SQL text で動的テーブルを含むクエリを選択し、 Query Details と Query Profile タブを使用して進行状況を追跡します。