![[新機能] Snowflake Dynamic TablesのAdaptive Refresh Modeがパブリックプレビューとなったので試してみた](https://images.ctfassets.net/ct0aopd36mqt/wp-refcat-img-3610e3c1ff5961bdb7b464e17f8bf06d/90b168b240005ead852ec1d474bb74fb/snowflake-logo-1200x630-1.png?w=3840&fm=webp)
[新機能] Snowflake Dynamic TablesのAdaptive Refresh Modeがパブリックプレビューとなったので試してみた
かわばたです。
2026年5月26日にSnowflake Dynamic Tablesの新機能として、Adaptive Refresh ModeがPublic Previewでリリースされました。
従来のDynamic Tablesでは、実行時のリフレッシュ方式はINCREMENTAL(差分リフレッシュ)またはFULL(全体再構築)のいずれかに固定されていました。AUTOを指定した場合も、作成時にINCREMENTALまたはFULLへ解決され、その後は自動で切り替わるものではありませんでした。
Adaptive Refresh Modeでは通常はインクリメンタルリフレッシュを実行しつつ、内部ヒューリスティックにより再初期化(REINITIALIZE)の方が効率的と判断された場合に自動的にREINITIALIZEへ切り替わります。
INSERT OVERWRITEによる一括ロードが時折発生するようなワークロードで確認した内容を記載します。
機能概要
Dynamic Tablesの従来のリフレッシュモードは以下の3つでした。
| リフレッシュモード | 動作 |
|---|---|
AUTO |
Snowflakeがクエリ定義に基づいてINCREMENTALまたはFULLを自動選択(作成時に決定) |
INCREMENTAL |
前回リフレッシュ以降の差分のみを処理 |
FULL |
毎回テーブル全体を再構築 |
今回追加されたADAPTIVEは、通常はインクリメンタルリフレッシュを実行しつつ、Snowflakeの内部ヒューリスティックにより「差分処理より再初期化の方が効率的」と判断された場合に、自動的にREINITIALIZEを実行するリフレッシュモードです。
- 通常時: インクリメンタルリフレッシュを実行(差分のみ処理)
- 大規模変更時: 内部ヒューリスティックが「インクリメンタル処理より再初期化(REINITIALIZE)の方が効率的」と判断した場合、自動的にREINITIALIZEを実行
- REINITIALIZE後: 再びインクリメンタルリフレッシュに戻る
INSERT OVERWRITEや大量のDELETE/UPDATEは、REINITIALIZEが発動しやすい代表的なケースとして挙げられます。
また、INITIALIZATION_WAREHOUSEパラメータを使うことで、通常のインクリメンタルリフレッシュ用のウェアハウスとは別に、再初期化(REINITIALIZE)用の大きいウェアハウスを指定できます。これにより、通常時は小さいウェアハウスでコストを抑えつつ、REINITIALIZE時だけ大きいウェアハウスで高速に処理するという使い分けが可能です。
REINITIALIZEが発生したかどうかは、DYNAMIC_TABLE_REFRESH_HISTORY関数でREFRESH_ACTION = 'REINITIALIZE'を確認することで監視できます。
制限事項
- 2026年5月27日時点ではPublic Previewの機能です。GAまでに仕様が変わる可能性があります
INCREMENTALモードと同じSQL構文の制限があります(INTERSECT、EXCEPT、正確なパーセンタイル関数などは使用不可)- 再初期化(REINITIALIZE)の発動タイミングはSnowflakeの内部ヒューリスティックに依存しており、利用者側で直接制御することはできません
- ADAPTIVEダイナミックテーブルは、他のADAPTIVEまたはINCREMENTALのDynamic Tableの上流・下流に配置できます
- フルリフレッシュの上流テーブルから下流にADAPTIVEダイナミックテーブルを配置する場合、上流テーブルにシステム派生のユニークキーまたは
IMMUTABLE WHERE制約が必要です
コスト
2026年5月27日時点では、公式DocにAdaptive Refresh Mode固有の追加コストに関する記載はありませんでした。ただし、再初期化(REINITIALIZE)が発動するとFULLリフレッシュ相当のコンピュートが発生するため、頻繁にINSERT OVERWRITEが行われる環境ではウェアハウスコストにご注意ください。INITIALIZATION_WAREHOUSEに大きいウェアハウスを指定した場合は、そのウェアハウスのコストが別途発生します。
検証環境
- Snowflake: AWSリージョン、Enterpriseエディションのトライアルアカウントで検証
- ウェアハウス: 通常リフレッシュ用(XSMALL)、INITIALIZATION_WAREHOUSE用(MEDIUM)の2つを使用
事前準備
検証用データベース・スキーマ・ウェアハウスの作成
検証用の環境を作成します。通常リフレッシュ用のXSMALLウェアハウスと、REINITIALIZE用のMEDIUMウェアハウスの2つを準備します。
USE ROLE SYSADMIN;
-- データベース・スキーマの作成
CREATE DATABASE IF NOT EXISTS DT_ADAPTIVE_DEMO;
USE DATABASE DT_ADAPTIVE_DEMO;
CREATE SCHEMA IF NOT EXISTS PUBLIC;
USE SCHEMA PUBLIC;
-- 通常リフレッシュ用ウェアハウス
CREATE WAREHOUSE IF NOT EXISTS WH_DT_XS
WAREHOUSE_SIZE = 'XSMALL'
AUTO_SUSPEND = 60
AUTO_RESUME = TRUE;
ベーステーブルの作成とデータ投入
検証用のベーステーブルとして、ECサイトの注文データを10万件生成します。REINITIALIZEの発動にはある程度のデータ量が必要なため、GENERATOR関数を使ってランダムデータを生成します。
USE WAREHOUSE WH_DT_XS;
-- 検証用テーブル(ECサイトの注文データ 10万件)
CREATE OR REPLACE TABLE orders AS
SELECT
SEQ4() AS order_id,
'Customer_' || UNIFORM(1, 1000, RANDOM()) AS customer_name,
ARRAY_CONSTRUCT('Laptop','Phone','Tablet','Monitor','Keyboard','Mouse','Headset','Camera')
[UNIFORM(0, 7, RANDOM())]::VARCHAR AS product_name,
DATEADD(day, -UNIFORM(0, 365, RANDOM()), '2026-05-27')::DATE AS order_date,
UNIFORM(1, 50, RANDOM()) AS quantity,
ROUND(UNIFORM(10, 500, RANDOM())::NUMERIC(10,2), 2) AS unit_price,
ROUND(quantity * unit_price, 2) AS total_amount,
ARRAY_CONSTRUCT('COMPLETED','PENDING','SHIPPED','CANCELLED')
[UNIFORM(0, 3, RANDOM())]::VARCHAR AS status,
ARRAY_CONSTRUCT('Tokyo','Osaka','Nagoya','Fukuoka','Sapporo')
[UNIFORM(0, 4, RANDOM())]::VARCHAR AS region
FROM TABLE(GENERATOR(ROWCOUNT => 100000));
10万件作成されていれば準備完了です。
SELECT COUNT(*) AS row_count FROM orders;

また、JOINで使用するリージョンマスタテーブルも作成します。
CREATE OR REPLACE TABLE region_master (
region VARCHAR,
region_name VARCHAR,
country VARCHAR
);
INSERT INTO region_master VALUES
('Tokyo', '東京', 'Japan'),
('Osaka', '大阪', 'Japan'),
('Nagoya', '名古屋', 'Japan'),
('Fukuoka', '福岡', 'Japan'),
('Sapporo', '札幌', 'Japan');
試してみた
Adaptive Refresh ModeでDynamic Tableを作成する
REFRESH_MODE = ADAPTIVEを指定してDynamic Tableを作成します。ここではベーステーブルordersにリージョンマスタテーブルregion_masterをJOINする定義にしています。
CREATE OR REPLACE DYNAMIC TABLE orders_enriched
TARGET_LAG = '1 minute'
REFRESH_MODE = ADAPTIVE
WAREHOUSE = WH_DT_XS
AS
SELECT
o.order_id,
o.customer_name,
o.product_name,
o.order_date,
o.quantity,
o.total_amount,
o.status,
o.region,
r.region_name,
r.country
FROM orders o
JOIN region_master r ON o.region = r.region;
作成後、SHOW DYNAMIC TABLESでREFRESH_MODEがADAPTIVEになっていることを確認します。
SHOW DYNAMIC TABLES LIKE 'ORDERS_ENRICHED';

refresh_mode列がADAPTIVEと表示されていれば問題ありません。
初回リフレッシュが完了するまで少し待ちます(10万行のため1分程度)。
件数が確認できれば初回リフレッシュは成功です。
SELECT COUNT(*) AS row_count FROM orders_enriched;
通常INSERT後のインクリメンタルリフレッシュを確認する
ベーステーブルに少量のデータを追加して、インクリメンタルリフレッシュが行われることを確認します。
-- 100件追加
INSERT INTO orders
SELECT
100000 + SEQ4() AS order_id,
'NewCustomer_' || UNIFORM(1, 100, RANDOM()) AS customer_name,
'Laptop' AS product_name,
'2026-05-27'::DATE AS order_date,
UNIFORM(1, 10, RANDOM()) AS quantity,
ROUND(UNIFORM(50, 200, RANDOM())::NUMERIC(10,2), 2) AS unit_price,
ROUND(quantity * unit_price, 2) AS total_amount,
'COMPLETED' AS status,
'Tokyo' AS region
FROM TABLE(GENERATOR(ROWCOUNT => 100));
TARGET_LAGに指定した1分を目安に、リフレッシュが完了するまで少し待ってから、DYNAMIC_TABLE_REFRESH_HISTORY関数でリフレッシュ履歴を確認します。
SELECT
name,
refresh_action,
refresh_trigger,
state,
data_timestamp,
statistics:numInsertedRows::INT AS inserted_rows,
statistics:numDeletedRows::INT AS deleted_rows
FROM TABLE(INFORMATION_SCHEMA.DYNAMIC_TABLE_REFRESH_HISTORY(
NAME => 'DT_ADAPTIVE_DEMO.PUBLIC.ORDERS_ENRICHED'
))
WHERE state = 'SUCCEEDED'
ORDER BY data_timestamp DESC
LIMIT 5;
REFRESH_ACTIONがINCREMENTALになっていれば問題ありません。通常のINSERTではインクリメンタルリフレッシュが実行されることが確認できました。少量の追加(100件)に対して差分処理のみで効率的に更新されています。

INSERT OVERWRITE後のREINITIALIZEを確認する
次に、INSERT OVERWRITEでベーステーブルのデータを一括で書き換え、REINITIALIZEが自動的に発動するか確認します。10万行のうち直近1ヶ月分(約7,000〜8,000件程度)のみに絞り込むことで、大幅なデータ変更を発生させます。
-- INSERT OVERWRITEで全データを書き換え(直近のデータのみに絞る)
-- 10万行 → 約7,000行への大幅削減
INSERT OVERWRITE INTO orders
SELECT * FROM orders WHERE order_date >= '2026-05-01';

TARGET_LAGに指定した1分を目安に、1〜2分ほど待ってからリフレッシュ履歴を確認します。
SELECT
name,
refresh_action,
refresh_trigger,
state,
data_timestamp,
statistics:numInsertedRows::INT AS inserted_rows,
statistics:numDeletedRows::INT AS deleted_rows
FROM TABLE(INFORMATION_SCHEMA.DYNAMIC_TABLE_REFRESH_HISTORY(
NAME => 'DT_ADAPTIVE_DEMO.PUBLIC.ORDERS_ENRICHED'
))
WHERE state = 'SUCCEEDED'
ORDER BY data_timestamp DESC
LIMIT 5;
REFRESH_ACTIONがREINITIALIZEになっていればOKです。実際の検証では、INSERT OVERWRITE実行から約1〜2分後にREINITIALIZEが発動し、inserted_rows = 8671、deleted_rows = 100,000という結果を確認しました。

最後に
Snowflake Dynamic Tablesの新機能であるAdaptive Refresh Modeを試しました。
10万行のデータで検証した結果、通常のINSERTではインクリメンタルリフレッシュが実行され、INSERT OVERWRITEで大幅なデータ変更を行った際にはREINITIALIZEが自動的に発動することを確認できました。
「普段は差分更新だけど、たまに一括ロードが走る」というワークロードでは、従来のようにリフレッシュモードを手動で切り替える必要がなくなるため、運用が楽になりそうです。
この記事が何かの参考になれば幸いです!







