[新機能] Snowflakeでクエリの特性に応じてコンピュートリソースが自動でスケールするAdaptive Warehouseを試してみた

[新機能] Snowflakeでクエリの特性に応じてコンピュートリソースが自動でスケールするAdaptive Warehouseを試してみた

2026.04.16

さがらです。

これまでSnowflakeのウェアハウスはサイズ(XS・S・M・Lなど)を自分で選んで管理する必要がありましたが、Adaptive Warehouseにより、クエリの特性に応じてコンピュートリソースが自動でスケールするようになります。手動でのウェアハウスサイジングや、スケールアップ・スケールアウトの設定が不要になる機能です。

@tshowisさんの以下の投稿で知りました。

https://x.com/tshowis/status/2044446136556282293

リリースノートはまだ公開されていませんが、公式Docに詳細が掲載されています。Public Previewの対応リージョンにはAWS東京リージョン(AP Northeast 1)も含まれているため、AWS東京リージョンで利用している方はすぐに試せます。TPC-Hサンプルデータを使って実際にどのように動くか確認してみましたので、手順と確認結果をまとめます。

https://docs.snowflake.com/en/user-guide/warehouses-adaptive

機能概要

Adaptive Warehouseは、ワークロードを認識してリソースを自動的に割り当てるコンピュートサービスです。アカウント専用の共有コンピュートプールを持ち、クエリの特性に応じて最適なリソースを自動で決定します。

主な特徴は以下のとおりです:

  • ウェアハウスサイジング不要:手動でのサイズ選択・変更が不要
  • クエリ単位の自動スケール:小さいクエリは少ないリソース、大きいクエリは多くのリソースを自動的に使用
  • オンライン変換:既存の標準ウェアハウスからAdaptive Warehouseへの変換はダウンタイムなし
  • 2つのパラメータで挙動を制御可能

制御できるパラメータは以下の2つです:

パラメータ デフォルト値 説明
MAX_QUERY_PERFORMANCE_LEVEL XLARGE 1クエリあたりの上限パフォーマンス(XSMALL〜X4LARGE)
QUERY_THROUGHPUT_MULTIPLIER 2 並行実行のスケール係数(0で無制限、正の整数で上限設定)

QUERY_THROUGHPUT_MULTIPLIERNに設定すると、MAX_QUERY_PERFORMANCE_LEVELのリソースでN件のクエリを同時実行できる容量が確保されます。

制限事項

  • 2026年4月16日時点ではPublic Previewの機能です。GAまでに仕様が変わる可能性があります
  • 利用可能リージョン(Public Preview時点):US West 2(Oregon)、EU West 1(Ireland)、AP Northeast 1(Tokyo)
  • 必要なエディション:Enterprise Edition以上
  • X5Large・X6LargeウェアハウスからAdaptive Warehouseへの変換はサポートされていません
  • Snowpark-optimizedウェアハウス・Interactiveウェアハウスとの相互変換もサポートされていません

コスト

Adaptive Warehouseはクエリベースの課金モデルを採用しています。各クエリのコストは、そのクエリが使用したコンピュートリソース量とソフトウェアリソース量に基づいて計算されます。ウェアハウス全体のコストは、実行されたすべてのクエリのコストの合計になります。

なお、ウェアハウスの作成自体にはコストは発生せず、クエリが実行された時点から課金が始まります。コスト管理にはBudgets・リソースモニターの活用、またSNOWFLAKE.ACCOUNT_USAGEのビューを使ったモニタリングが可能です。

前提条件

  • Snowflake:AWS USオレゴンリージョン、Enterprise Edition
    • ちょうどトライアルアカウントを持っていたので、USオレゴンリージョンで検証しています

事前準備

TPC-Hサンプルデータの確認

今回の検証では、Snowflakeに標準で提供されているTPC-Hサンプルデータを使います。TPC-Hは意思決定支援ベンチマーク用のデータセットで、複雑な結合や集計を含むクエリで大量データ処理を評価するのに適しています。

https://docs.snowflake.com/ja/user-guide/sample-data-tpch

SNOWFLAKE_SAMPLE_DATAデータベース内に、スケールファクター(SF)の異なる複数のスキーマが用意されています:

スキーマ データ規模の目安
TPCH_SF1 数百万レコード
TPCH_SF10 数千万レコード
TPCH_SF100 数億レコード
TPCH_SF1000 数十億レコード

今回はAutomatic Scalingの挙動をより明確に確認するために、TPCH_SF1000(数十億レコード規模)を使います。

まず、サンプルデータにアクセスできることを確認しておきます。

-- サンプルデータの確認
USE SCHEMA SNOWFLAKE_SAMPLE_DATA.TPCH_SF1000;

-- テーブル一覧の確認
SHOW TABLES;

8つのテーブルが表示されればOKです(LINEITEMORDERSCUSTOMERSUPPLIERPARTPARTSUPPNATIONREGION)。

2026-04-16_08h10_03

アカウントレベルのキャッシュを無効化

パラメータのチューニング前後で実行時間を正しく比較するため、クエリ結果キャッシュを無効化しておきます。キャッシュが有効な状態だと、2回目以降の同じクエリがキャッシュから返されてしまい、実行時間の比較ができません。

https://docs.snowflake.com/en/sql-reference/parameters#use-cached-result

アカウントレベルでキャッシュを無効化します。

USE ROLE ACCOUNTADMIN;

-- アカウントレベルでクエリ結果キャッシュを無効化
ALTER ACCOUNT SET USE_CACHED_RESULT = false;

以下のクエリでパラメータを確認し、falseになっていればOKです。

-- 設定変更後の確認
SHOW PARAMETERS LIKE '%USE_CACHED_RESULT%';

2026-04-16_07h45_15

試してみた

1. Adaptive Warehouseの作成(XLARGE設定)

まず、MAX_QUERY_PERFORMANCE_LEVEL = XLARGEのAdaptive Warehouseを新規作成します。

USE ROLE SYSADMIN;

-- XLARGE設定のAdaptive Warehouseを新規作成
CREATE ADAPTIVE WAREHOUSE adaptive_wh_xlarge
  WITH MAX_QUERY_PERFORMANCE_LEVEL = XLARGE
       QUERY_THROUGHPUT_MULTIPLIER = 2;

作成後、設定を確認します。

-- ウェアハウスの設定を確認
SHOW WAREHOUSES LIKE 'adaptive_wh_xlarge';

type列がADAPTIVEになっていればOKです。

2026-04-16_08h52_02

2. XLARGE設定でTPC-Hクエリを実行

作成したadaptive_wh_xlargeを使って、TPC-Hの代表的なクエリを実行してみます。

後で実行時間を比較できるように QUERY_TAG を設定します。

-- セッションにQUERY_TAGを設定(後で比較のラベルとして使用)
ALTER SESSION SET QUERY_TAG = 'adaptive_xlarge_m2';

USE WAREHOUSE adaptive_wh_xlarge;
USE SCHEMA SNOWFLAKE_SAMPLE_DATA.TPCH_SF1000;

TPC-H Q1:集計クエリ(LINEITEMテーブル全体を集計)

最初に、TPC-Hの中でも最も単純なQ1(Pricing Summary Report)を実行します。LINEITEMテーブル(SF1000では約60億レコード)を全件スキャンして集計するクエリです。

-- TPC-H Q1: Pricing Summary Report
-- SF1000のLINEITEMテーブル(約60億レコード)を集計
SELECT
    L_RETURNFLAG,
    L_LINESTATUS,
    SUM(L_QUANTITY)                                       AS SUM_QTY,
    SUM(L_EXTENDEDPRICE)                                  AS SUM_BASE_PRICE,
    SUM(L_EXTENDEDPRICE * (1 - L_DISCOUNT))               AS SUM_DISC_PRICE,
    SUM(L_EXTENDEDPRICE * (1 - L_DISCOUNT) * (1 + L_TAX)) AS SUM_CHARGE,
    AVG(L_QUANTITY)                                       AS AVG_QTY,
    AVG(L_EXTENDEDPRICE)                                  AS AVG_PRICE,
    AVG(L_DISCOUNT)                                       AS AVG_DISC,
    COUNT(*)                                              AS COUNT_ORDER
FROM
    LINEITEM
WHERE
    L_SHIPDATE <= DATEADD(DAY, -90, TO_DATE('1998-12-01'))
GROUP BY
    L_RETURNFLAG,
    L_LINESTATUS
ORDER BY
    L_RETURNFLAG,
    L_LINESTATUS;

5回実行して、以下の結果となりました。

実行回 実行時間 (秒)
1 4.47
2 4.55
3 3.68
4 3.85
5 3.77

TPC-H Q5:複数テーブルの結合クエリ

次に、複数テーブルをJOINするQ5(Local Supplier Volume)を実行します。

-- TPC-H Q5: Local Supplier Volume
-- 6テーブルをJOINする複雑なクエリ
SELECT
    N.N_NAME,
    SUM(L.L_EXTENDEDPRICE * (1 - L.L_DISCOUNT)) AS REVENUE
FROM
    CUSTOMER   C,
    ORDERS     O,
    LINEITEM   L,
    SUPPLIER   S,
    NATION     N,
    REGION     R
WHERE
    C.C_CUSTKEY    = O.O_CUSTKEY
    AND L.L_ORDERKEY  = O.O_ORDERKEY
    AND L.L_SUPPKEY   = S.S_SUPPKEY
    AND C.C_NATIONKEY = S.S_NATIONKEY
    AND S.S_NATIONKEY = N.N_NATIONKEY
    AND N.N_REGIONKEY = R.R_REGIONKEY
    AND R.R_NAME      = 'ASIA'
    AND O.O_ORDERDATE >= TO_DATE('1994-01-01')
    AND O.O_ORDERDATE <  DATEADD(YEAR, 1, TO_DATE('1994-01-01'))
GROUP BY
    N.N_NAME
ORDER BY
    REVENUE DESC;

5回実行して、以下の結果となりました。

実行回 実行時間 (秒)
1 5.74
2 3.17
3 3.03
4 3.03
5 2.83

3. 比較用のAdaptive Warehouseを新規作成(SMALL設定)

MAX_QUERY_PERFORMANCE_LEVEL = SMALLに設定した新しいAdaptive Warehouseを別途作成します。

USE ROLE SYSADMIN;

-- SMALL設定のAdaptive Warehouseを新規作成
CREATE ADAPTIVE WAREHOUSE adaptive_wh_small
  WITH MAX_QUERY_PERFORMANCE_LEVEL = SMALL
       QUERY_THROUGHPUT_MULTIPLIER = 2;
-- ウェアハウスの設定を確認
SHOW WAREHOUSES LIKE 'adaptive_wh_small';

type列がADAPTIVEになっていればOKです。

2026-04-16_08h58_26

4. SMALL設定でTPC-Hクエリを実行

作成したadaptive_wh_smallを使って、同じQ1・Q5を実行します。

-- QUERY_TAGを設定(SMALL設定での実行であることをラベル付け)
ALTER SESSION SET QUERY_TAG = 'adaptive_small_m2';

USE WAREHOUSE adaptive_wh_small;
USE SCHEMA SNOWFLAKE_SAMPLE_DATA.TPCH_SF1000;

TPC-H Q1:集計クエリ

-- Q1を実行(MAX_QUERY_PERFORMANCE_LEVEL = SMALL)
SELECT
    L_RETURNFLAG,
    L_LINESTATUS,
    SUM(L_QUANTITY)                                       AS SUM_QTY,
    SUM(L_EXTENDEDPRICE)                                  AS SUM_BASE_PRICE,
    SUM(L_EXTENDEDPRICE * (1 - L_DISCOUNT))               AS SUM_DISC_PRICE,
    SUM(L_EXTENDEDPRICE * (1 - L_DISCOUNT) * (1 + L_TAX)) AS SUM_CHARGE,
    AVG(L_QUANTITY)                                       AS AVG_QTY,
    AVG(L_EXTENDEDPRICE)                                  AS AVG_PRICE,
    AVG(L_DISCOUNT)                                       AS AVG_DISC,
    COUNT(*)                                              AS COUNT_ORDER
FROM
    LINEITEM
WHERE
    L_SHIPDATE <= DATEADD(DAY, -90, TO_DATE('1998-12-01'))
GROUP BY
    L_RETURNFLAG,
    L_LINESTATUS
ORDER BY
    L_RETURNFLAG,
    L_LINESTATUS;

5回実行して、以下の結果となりました。

実行回 実行時間 (秒)
1 21.57
2 31.73
3 27.73
4 21.74
5 34.35

TPC-H Q5:複数テーブルの結合クエリ

-- Q5を実行(MAX_QUERY_PERFORMANCE_LEVEL = SMALL)
SELECT
    N.N_NAME,
    SUM(L.L_EXTENDEDPRICE * (1 - L.L_DISCOUNT)) AS REVENUE
FROM
    CUSTOMER   C,
    ORDERS     O,
    LINEITEM   L,
    SUPPLIER   S,
    NATION     N,
    REGION     R
WHERE
    C.C_CUSTKEY    = O.O_CUSTKEY
    AND L.L_ORDERKEY  = O.O_ORDERKEY
    AND L.L_SUPPKEY   = S.S_SUPPKEY
    AND C.C_NATIONKEY = S.S_NATIONKEY
    AND S.S_NATIONKEY = N.N_NATIONKEY
    AND N.N_REGIONKEY = R.R_REGIONKEY
    AND R.R_NAME      = 'ASIA'
    AND O.O_ORDERDATE >= TO_DATE('1994-01-01')
    AND O.O_ORDERDATE <  DATEADD(YEAR, 1, TO_DATE('1994-01-01'))
GROUP BY
    N.N_NAME
ORDER BY
    REVENUE DESC;

5回実行して、以下の結果となりました。

実行回 実行時間 (秒)
1 42.18
2 38.49
3 38.41
4 38.69
5 36.97

5. INFORMATION_SCHEMA.QUERY_HISTORYで実行時間を比較

両ウェアハウスでの実行が完了したら、INFORMATION_SCHEMA.QUERY_HISTORY()で2つのQUERY_TAGをまとめて比較します。ACCOUNT_USAGEビューとは異なり遅延なしで参照できます。

全20回分の実行時間を一覧で確認

まず、Q1・Q5それぞれ5回ずつ×2ウェアハウス=合計20回分の実行記録を個別に確認します。QUERY_TEXTの内容からL_RETURNFLAGを含むものをQ1、N_NAMEを含むものをQ5と区別しています。

-- 全20回分の実行履歴(実行時間のみ確認)
SELECT
    QUERY_TAG,
    WAREHOUSE_NAME,
    CASE
        WHEN QUERY_TEXT ILIKE '%L_RETURNFLAG%' THEN 'Q1'
        WHEN QUERY_TEXT ILIKE '%N_NAME%'       THEN 'Q5'
        ELSE 'OTHER'
    END                                       AS query_name,
    START_TIME,
    ROUND(EXECUTION_TIME / 1000, 2)           AS exec_sec
FROM TABLE(
    INFORMATION_SCHEMA.QUERY_HISTORY(
        END_TIME_RANGE_START => DATEADD(HOUR, -2, CURRENT_TIMESTAMP()),
        END_TIME_RANGE_END   => CURRENT_TIMESTAMP(),
        RESULT_LIMIT         => 1000
    )
)
WHERE WAREHOUSE_NAME   IN ('ADAPTIVE_WH_XLARGE', 'ADAPTIVE_WH_SMALL')
  AND QUERY_TAG        IN ('adaptive_xlarge_m2', 'adaptive_small_m2')
  AND EXECUTION_STATUS = 'SUCCESS'
  AND QUERY_TYPE       = 'SELECT'
ORDER BY QUERY_TAG, query_name, START_TIME;

2026-04-16_09h15_18

QUERY_TAG WAREHOUSE_NAME クエリ種別 試行回数 実行時間 (秒)
adaptive_xlarge_m2 ADAPTIVE_WH_XLARGE Q1 1回目 4.47
adaptive_xlarge_m2 ADAPTIVE_WH_XLARGE Q1 2回目 4.55
adaptive_xlarge_m2 ADAPTIVE_WH_XLARGE Q1 3回目 3.68
adaptive_xlarge_m2 ADAPTIVE_WH_XLARGE Q1 4回目 3.85
adaptive_xlarge_m2 ADAPTIVE_WH_XLARGE Q1 5回目 3.77
adaptive_xlarge_m2 ADAPTIVE_WH_XLARGE Q5 1回目 5.74
adaptive_xlarge_m2 ADAPTIVE_WH_XLARGE Q5 2回目 3.17
adaptive_xlarge_m2 ADAPTIVE_WH_XLARGE Q5 3回目 3.03
adaptive_xlarge_m2 ADAPTIVE_WH_XLARGE Q5 4回目 3.03
adaptive_xlarge_m2 ADAPTIVE_WH_XLARGE Q5 5回目 2.83
adaptive_small_m2 ADAPTIVE_WH_SMALL Q1 1回目 21.57
adaptive_small_m2 ADAPTIVE_WH_SMALL Q1 2回目 31.73
adaptive_small_m2 ADAPTIVE_WH_SMALL Q1 3回目 27.73
adaptive_small_m2 ADAPTIVE_WH_SMALL Q1 4回目 21.74
adaptive_small_m2 ADAPTIVE_WH_SMALL Q1 5回目 34.35
adaptive_small_m2 ADAPTIVE_WH_SMALL Q5 1回目 42.18
adaptive_small_m2 ADAPTIVE_WH_SMALL Q5 2回目 38.49
adaptive_small_m2 ADAPTIVE_WH_SMALL Q5 3回目 38.41
adaptive_small_m2 ADAPTIVE_WH_SMALL Q5 4回目 38.69
adaptive_small_m2 ADAPTIVE_WH_SMALL Q5 5回目 36.97

集計して比較

MAX_QUERY_PERFORMANCE_LEVELを下げた効果がexecution_timeに出ているかを確認します。キュー待ちの傾向も見たいためqueued_overload_timeも合わせて出します。

-- QUERY_TAG × クエリ種別ごとに実行時間を集計して比較
-- 各 QUERY_TAG × query_name の直近5件のSELECT文のみを対象にする
WITH ranked AS (
    SELECT
        QUERY_TAG,
        WAREHOUSE_NAME,
        CASE
            WHEN QUERY_TEXT ILIKE '%L_RETURNFLAG%' THEN 'Q1'
            WHEN QUERY_TEXT ILIKE '%N_NAME%'       THEN 'Q5'
            ELSE 'OTHER'
        END                  AS query_name,
        EXECUTION_TIME,
        TOTAL_ELAPSED_TIME,
        QUEUED_OVERLOAD_TIME,
        ROW_NUMBER() OVER (
            PARTITION BY QUERY_TAG,
                         CASE
                             WHEN QUERY_TEXT ILIKE '%L_RETURNFLAG%' THEN 'Q1'
                             WHEN QUERY_TEXT ILIKE '%N_NAME%'       THEN 'Q5'
                             ELSE 'OTHER'
                         END
            ORDER BY START_TIME DESC
        ) AS rn
    FROM TABLE(
        INFORMATION_SCHEMA.QUERY_HISTORY(
            END_TIME_RANGE_START => DATEADD(HOUR, -2, CURRENT_TIMESTAMP()),
            END_TIME_RANGE_END   => CURRENT_TIMESTAMP(),
            RESULT_LIMIT         => 1000
        )
    )
    WHERE WAREHOUSE_NAME   IN ('ADAPTIVE_WH_XLARGE', 'ADAPTIVE_WH_SMALL')
      AND QUERY_TAG        IN ('adaptive_xlarge_m2', 'adaptive_small_m2')
      AND EXECUTION_STATUS = 'SUCCESS'
      AND QUERY_TYPE       = 'SELECT'
)
SELECT
    QUERY_TAG,
    WAREHOUSE_NAME,
    query_name,
    COUNT(*)                                           AS run_count,
    ROUND(AVG(EXECUTION_TIME)       / 1000, 2)        AS avg_exec_sec,
    ROUND(MIN(EXECUTION_TIME)       / 1000, 2)        AS min_exec_sec,
    ROUND(MAX(EXECUTION_TIME)       / 1000, 2)        AS max_exec_sec,
    ROUND(AVG(TOTAL_ELAPSED_TIME)   / 1000, 2)        AS avg_elapsed_sec,
    ROUND(AVG(QUEUED_OVERLOAD_TIME) / 1000, 2)        AS avg_queued_overload_sec
FROM ranked
WHERE rn <= 5
GROUP BY QUERY_TAG, WAREHOUSE_NAME, query_name
ORDER BY QUERY_TAG, query_name;

2026-04-16_09h17_51

改めて表にまとめた結果が以下となります。

adaptive_xlarge_m2よりadaptive_small_m2のほうがavg_exec_secが長くなっていることがわかります。(パフォーマンス上限を下げた分、実行時間が伸びる)。

QUERY_TAG WAREHOUSE_NAME クエリ種別 実行回数 平均実行時間 (秒) 最小 (秒) 最大 (秒) 平均経過時間 (秒) 平均キュー待ち (秒)
adaptive_xlarge_m2 ADAPTIVE_WH_XLARGE Q1 5 4.06 3.68 4.55 7.17 0.00
adaptive_xlarge_m2 ADAPTIVE_WH_XLARGE Q5 5 3.56 2.83 5.74 6.86 0.00
adaptive_small_m2 ADAPTIVE_WH_SMALL Q1 5 27.42 21.57 34.35 25.82 0.00
adaptive_small_m2 ADAPTIVE_WH_SMALL Q5 5 38.95 36.97 42.18 42.72 0.00

考察

Q1・Q5ともに、XLARGEウェアハウスはSMALLウェアハウスと比較して大幅に短い実行時間になりました。

クエリ XLARGE 平均実行時間 SMALL 平均実行時間 倍率
Q1 4.06 秒 27.42 秒 約 6.8 倍
Q5 3.56 秒 38.95 秒 約 10.9 倍

Q5のほうがQ1より倍率が大きくなっています。Q5は6テーブルのJOINを含む複雑なクエリであり、リソースの差がより顕著に現れたと考えられます。

検証上の注意点:ウェアハウスのデータキャッシュ

今回の検証で押さえておきたい点があります。Snowflakeのウェアハウスにはクエリ結果キャッシュとは別に、**データキャッシュ(ローカルディスクキャッシュ)**があります。リモートストレージから読み込んだマイクロパーティションをウェアハウスのローカルSSDに保持する仕組みです。

今回はアカウントレベルでUSE_CACHED_RESULT = falseに設定してクエリ結果キャッシュを無効化しましたが、データキャッシュは無効化していません。このため、同一ウェアハウスで同じクエリを連続実行した場合、2回目以降はローカルSSDからデータを読み込むため、初回よりも高速になります。

実際のデータを見るとXLARGEウェアハウスのQ5では、1回目が5.74秒なのに対し、2〜5回目は2.83〜3.17秒に短縮されており、データキャッシュの効果が確認できます。

クエリプロファイルで確認すると、2回目ではPercentage scanned from cacheの割合が一定あることから、ウェアハウスのデータキャッシュが効いていることがわかります。

SMALLでのQ5:1回目のクエリプロファイル

2026-04-16_09h31_43

SMALLでのQ5:2回目のクエリプロファイル

2026-04-16_09h32_36

今回は「SMALLとXLARGEの相対的な差」を確認する目的だったため、両ウェアハウスとも同一条件(同じキャッシュ状態)での比較になっており、相対比較としては有効だと考えております。ただし、純粋なコールドスタート時の性能を計測したい場合は、ウェアハウスをサスペンドして再起動し、データキャッシュをクリアしてから計測する必要があることにご注意ください。

最後に

Snowflakeの新機能Adaptive WarehouseをTPC-Hサンプルデータを使って試してみました。

MAX_QUERY_PERFORMANCE_LEVELをXLARGEとSMALLで比較した結果、Q1(集計クエリ)で約6.8倍、Q5(6テーブルJOIN)で約10.9倍の実行時間差が確認できました。複雑なJOINクエリほどリソース量の差が顕著に出る傾向があり、MAX_QUERY_PERFORMANCE_LEVELの設定がパフォーマンスに直結することが実感できました。

最も印象的だったのは、ウェアハウスのサイズを一切意識せず、2つのパラメータ(MAX_QUERY_PERFORMANCE_LEVELQUERY_THROUGHPUT_MULTIPLIER)だけで「コストとパフォーマンスのバランス」をコントロールできる点です。これまでは「XLかXXLか」という具体的なサイズ選択が必要でしたが、Adaptive Warehouseではそこを自動化しつつ、上限だけ指定するシンプルな設計になっています。

本機能はEnterprise Edition以上でPublic Previewが利用でき、今回検証したUSオレゴンリージョン(US West 2)のほか、EU West 1(Ireland)とAP Northeast 1(東京) でも利用可能です。東京リージョンで利用している方も同様の手順ですぐに試せますので、ぜひ触ってみてください。

この記事をシェアする

関連記事