0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Snowflake ― クラスタリングキーについて 〜物理配置の違いがスキャン量に与える影響〜

0
Last updated at Posted at 2026-02-10

目次

  1. はじめに
  2. Snowflakeにおける最適化の前提
  3. クラスタリングキーとは何か
  4. クラスタリングキーとインデックスの違い
  5. 効果が出る条件と出ない条件
  6. クラスタリングキーと物理配置の関係
  7. 検証
  8. 実務でどう使うか
  9. まとめ

1. はじめに

Snowflakeでは
「クラスタリングキーを指定すればクエリは速くなる」
と思われがちです。

しかし実務では、次のように感じるケースが少なくありません。

  • 効果がよく分からない
  • 指定しても、すぐに変化が出ない
  • 期待したほど速くならない

この原因は、
クラスタリングキーの指定方法が間違っているから ではありません。

多くの場合、
クラスタリングキーの「役割の理解」がずれている ことが原因です。

本スライドでは、

  • クラスタリングキーの正体
  • Snowflake における正しい最適化の考え方

を整理し、
「なぜ効かないように見えるのか」 を構造的に説明していきます。

📝 クラスタリングキーは
「即効性のある高速化スイッチ」ではなく、
物理配置を“整えていくための仕組み” である点が重要です。

⬆ 目次へ戻る

2. Snowflakeにおける最適化の前提

Snowflakeの最適化を理解するうえで、
まず押さえておくべき前提があります。

Snowflake は「行単位」でデータを探さない

Snowflake では、
PostgreSQL や Oracle のように 行単位でデータを探しにいく ことはしません。

データは常に
micro-partition 単位 で読み込まれます。

最適化の中心は「探す速さ」ではない

Snowflake における最適化の本質は以下にあります。

  • 「速く探す」こと ではない
  • 読まないデータをいかに増やすか

micro-partition は事前にふるい落とされる

各 micro-partition には、以下の メタデータ が保持されています。

  • MIN / MAX
  • NULL の有無
  • 行数 など

クエリ実行時、
条件に合わない micro-partition は 実データを読む前に除外 されます。

実行時間とコストは「読んだ量」で決まる

Snowflake では、実行時間 、クエリコスト
のどちらも、どれだけの micro-partition / Bytes を読んだか
に強く依存します。

そのため Snowflake では
「実行時間が短いか」よりも
「どれだけ読まれているか」 を見ることが重要になります。

⬆ 目次へ戻る

3. クラスタリングキーとは何か

Snowflakeにおけるクラスタリングキー は、

データの並び方に関する「方針」を指定する仕組み です。

クラスタリングキーを指定すると、
指定した列の値が近いデータ同士が
近い micro-partition に集まりやすく なります。

インデックスではない

クラスタリングキーとは、

  • インデックスではない
  • 行を高速に検索する仕組みではない

そのため、
指定直後に効果が出るものではありません。

Snowflake における位置づけ

Snowflake は、
クラスタリングキーを

物理配置を自動調整するためのヒント

として扱います。

目的

クラスタリングキーの目的は、
micro-partition のプルーニングが効きやすい状態を維持すること
です。

📝 「速く探す」ための仕組みではなく、
「読まないデータを増やす」ための仕組み です。

⬆ 目次へ戻る

4. クラスタリングキーとインデックスの違い

観点 クラスタリングキー(Snowflake) インデックス(PostgreSQL など)
目的 データの物理配置を整えやすくする 行に高速に到達する
対象単位 micro-partition 行(タプル)
即効性 なし(徐々に効く) あり(作成直後から)
効果の出方 プルーニングが効きやすくなる 検索・結合が直接速くなる
指定の意味 配置に関する方針 検索用のデータ構造
管理主体 Snowflake が自動管理 利用者が設計・管理
期待値 将来のスキャン量削減 即時の実行時間短縮

⬆ 目次へ戻る

5. 効果が出る条件と出ない条件

Snowflake のクラスタリングキーは、
即座にデータを並べ替える仕組みではありません。

指定しても、すぐには変わらない

クラスタリングキーを指定しても、
既存データの配置が すぐに再配置されるわけではありません
Snowflake は、常に並び替えを行うわけではないためです。

データの並びは時間とともに崩れる

実務では、INSERT 、UPDATE
によって、データの並びは 時間とともに自然に崩れていきます。
クラスタリングキーは、その状況に対して
常に即応する仕組みではありません。

クラスタリングキーの扱われ方

クラスタリングキーは以下の点が重要です。

  • 命令ではない
  • 方針として扱われる

効果が出るかどうかは条件次第

クラスタリングキーの効果は以下に依存します。

  • データ量
  • データの増え方
  • クエリ条件

そのため、
「指定したのに速くならない」
という状況は、珍しいことではありません。

⬆ 目次へ戻る

6. クラスタリングキーと物理配置の関係

Snowflakeでは、
データは micro-partition 単位 で読み込まれます。

micro-partition と物理配置

各 micro-partition には以下が保持されています。

  • 列ごとの MIN / MAX
  • その他のメタデータ

値が 物理的にまとまっているほど、
不要な micro-partition を事前に除外(プルーニング)しやすく なります。

クラスタリングキーの役割

クラスタリングキーは、
この 「値のまとまり」 を
維持しやすくするための仕組み です。

  • 物理配置が整っている
    → プルーニングが効き、読む量が減る
  • 物理配置が崩れている
    → クラスタリングキーを指定しても効果は出にくい

再配置(再クラスタリング)とは

Snowflake では、
データは 基本的に追加順 で物理配置されます。

クラスタリングキーが指定されている場合、
必要に応じて バックグラウンドで
再配置(再クラスタリング)が行われます。

ただし、以下の点には注意が必要です。

  • Snowflake 側の判断で実行される
  • 常時行われるわけではない
  • 即時に実行されるわけでもない

再配置の目的とコスト

再配置の目的は、
物理配置の乱れを抑え、
プルーニングが効きやすい状態を維持すること

なお、
再配置にはクレジット消費が発生します。
(必要時のみ。テーブル、変更頻度に依存)

⬆ 目次へ戻る

7. 検証

検証の目的

Snowflakeにおいて、
クラスタリングキーが実際に適用された場合 と
指定していない場合 で、
以下にどの程度の差が出るかを確認します。

  • プルーニング効率
  • スキャン量

検証の前提条件

  • 使用する SQL は同一
  • 使用するデータは同一
    • 件数・値の分布は完全に同じ
  • Warehouse サイズは同一

異なるのは 物理配置のみ です。
差が出た場合、
クラスタリングキー適用による物理配置の変化 が原因と説明できます。


クラスタリングキーに関する前提

  • クラスタリングキーは
    物理配置を制御する「命令」ではない
  • Snowflake が必要と判断した場合にのみ、
    再配置(再クラスタリング)が行われる
  • 再配置が行われた場合、
    プルーニング効率に直接影響する

今回は、
クラスタリングキーが実際に適用されたケース を扱います。


検証に使用するデータ

  • 行数:約 300 万行
  • micro-partition 数:16
  • データサイズ:数 MB 程度

列構成

  • クラスタリングキー対象列
    • category(26 種類)
  • 日付列
    • created_at
  • ペイロード列
    • 文字列

検証用テーブル構成

クラスタリングキーなし

T_RANDOM

  • ランダム順で作成
  • 同じ値が全体に散らばる
  • プルーニングが効きにくい状態

クラスタリングキーあり

T_RANDOM_CLUSTERED

  • ランダム順で作成
  • クラスタリングキー(category)を設定
  • 再配置により、
    同じ値が近くに集まった状態

① 使用するクエリ(等価条件)

SELECT COUNT(*) FROM T_RANDOM           WHERE category = 'A';
SELECT COUNT(*) FROM T_RANDOM_CLUSTERED WHERE category = 'A';
  • 等価条件の複数値指定(IN)
  • 対象データ範囲を意図的に拡張
  • プルーニング効率の変化を確認
  • キャッシュの影響を避けて実行

② 使用するクエリ(IN句)

SELECT COUNT(*) FROM T_RANDOM           WHERE category IN ('A','B','C','D','E');
SELECT COUNT(*) FROM T_RANDOM_CLUSTERED WHERE category IN ('A','B','C','D','E');
  • 等価条件の複数値指定(IN)
  • 対象データ範囲を意図的に拡張
  • プルーニング効率の変化を確認
  • キャッシュの影響を避けて実行
クリックして展開(検証用SQL一式)

-- 検証テーブルの元となるデータ
CREATE OR REPLACE TABLE BASE_DATA AS
WITH gen AS (
  SELECT
    SEQ4() AS id
  FROM TABLE(GENERATOR(ROWCOUNT => 3000000))
)
SELECT
  id,
  CHR(65 + MOD(id, 26)) AS category,
  DATEADD('day', MOD(id, 365), '2024-01-01'::DATE) AS created_at,
  RPAD(TO_VARCHAR(id), 200, 'x') AS payload
FROM gen;

-- ① 値が散らばる配置(ランダム)
CREATE OR REPLACE TABLE T_RANDOM AS
SELECT * FROM BASE_DATA
ORDER BY RANDOM();

-- ② 値が散らばる配置(ランダム)クラスタリングキー指定
CREATE OR REPLACE TABLE T_RANDOM_CLUSTERED AS
SELECT * FROM BASE_DATA
ORDER BY RANDOM();
ALTER TABLE T_RANDOM_CLUSTERED CLUSTER BY (category);

-- キャッシュ無効(必要に応じて)
-- ALTER SESSION SET USE_CACHED_RESULT = FALSE;

-- 検証クエリ(等価条件)
SELECT COUNT(*) FROM T_RANDOM            WHERE category = 'A';
SELECT COUNT(*) FROM T_RANDOM_CLUSTERED  WHERE category = 'A';

-- 検証クエリ(等価条件・複数値)
SELECT COUNT(*) FROM T_RANDOM          WHERE category IN ('A','B','C','D','E');
SELECT COUNT(*) FROM T_RANDOM_CLUSTERED WHERE category IN ('A','B','C','D','E');


① 等価条件

SELECT COUNT(*) FROM T_RANDOM WHERE category = 'A';

スクリーンショット 2026-02-08 21.20.49.png

SELECT COUNT(*) FROM T_RANDOM WHERE category = 'A';

スクリーンショット 2026-02-08 21.21.09.png

検証結果(等価条件)

クラスタリングキーなし(T_RANDOM)

  • Partitions scanned:16 / 16
  • Bytes scanned:1.76 MB
  • Query insights:特になし

すべての micro-partition をスキャンしており、
等価条件でもプルーニングはほぼ効いていない 状態です。


クラスタリングキーあり(T_RANDOM_CLUSTERED)

  • Partitions scanned:2 / 3
  • Bytes scanned:0.67 MB
  • Query insights:Filter with clustering key

条件に合致する micro-partition のみがスキャンされており、
プルーニングが有効に機能 しています。


結果から分かること

Snowflakeでは以下が同じであっても、
物理配置の違い によって
スキャン対象は大きく変わります。

  • SQL
  • データ内容
  • 件数

クラスタリングキーが適用されることで、

  • 同じ値が近くの micro-partition に集約され
  • 不要な partition を読み飛ばせる

結果として、以下の差が確認できました。

  • Partitions scanned が大幅に減少
  • Bytes scanned も削減

② 等価条件・複数値

SELECT COUNT(*) FROM T_RANDOM WHERE category IN ('A','B','C','D','E');

スクリーンショット 2026-02-08 21.27.54.png

SELECT COUNT(*) FROM T_RANDOM_CLUSTERED WHERE category IN ('A','B','C','D','E');

スクリーンショット 2026-02-08 21.28.10.png

検証結果(等価条件・複数値)

クラスタリングキーなし(T_RANDOM)

  • Partitions scanned:16 / 16
  • Bytes scanned:1.76 MB
  • Query insights:特になし

IN 句で対象範囲を広げても、
すべての micro-partition をスキャン しています。

値が全体に散らばっているため、
プルーニングが機能していない 状態です。


クラスタリングキーあり(T_RANDOM_CLUSTERED)

  • Partitions scanned:2 / 3
  • Bytes scanned:0.67 MB
  • Query insights:Filter with clustering key

IN 句(複数値)であっても、
必要な micro-partition のみをスキャン しています。

クラスタリングキーにより、
対象値が 近い partition に集約 されていることが分かります。


結果から分かること

Snowflakeでは、等価条件が
単一値(=)でも
複数値(IN)でも
クラスタリングキーが適用されていれば、
プルーニングは有効に機能
します。

条件を広げても以下を確認できました。

  • 読む partition 数はほぼ増えず
  • スキャン量も抑えられている

📝 物理配置が整っていれば、
IN 句でもスキャン量は増えにくい

という点が、この検証から読み取れます。

⬆ 目次へ戻る

8. 実務でどう使うか

① クラスタリングキーを使うべき場面

以下ような条件がそろう場合、
Snowflakeのクラスタリングキーは検討対象になります。

  • 等価条件(=) / IN 条件が頻繁に使われる
  • データ量が多く、今後も増加が見込まれる
  • Query Profile で
    • Partitions
    • Bytes
      が多く読まれている

👉 「遅い」クエリではなく、
「読みすぎている」クエリを確認する
のがポイント。


② キー選定の考え方

クラスタリングキーに向いているのは以下です。

  • WHERE 句でよく使われる列
  • 値がある程度まとまる列

具体例:

  • カテゴリ系
  • 日付系
  • ID 系

👉 「並びたい列」ではなく、
「絞り込みに使われる列」
を選びます。


③ 効果確認の方法

クラスタリングキーの効果は、
実行時間だけで判断せず以下を比較します。

  • Partitions scanned
  • Bytes scanned
  • Query insights

数値に変化がなければ、
効果は出ていない と判断します。

👉 効果がなければ、無理に使う必要はありません。


④ 使わない判断も設計の一部

次のような場合、
クラスタリングキーは 使わない判断 も妥当です。

  • データ量が小さい
  • クエリ条件が多様で固定されない
  • 再配置(再クラスタリング)のコストが見合わない

👉 クラスタリングキーは万能ではありません。

⬆ 目次へ戻る

9. まとめ

Snowflakeでは、
実行時間よりも「どれだけ読んだか」 が重要です。

同じ SQL、同じデータであっても、
物理配置の違い によって
スキャン量(Partitions / Bytes)は大きく変わります。

クラスタリングキーが適用されることで以下を確認できました。

  • プルーニング効率が向上し
  • 読むデータ量を削減できる

また、以下の条件であっても、
物理配置が整っていれば効果は維持 されます。

  • 等価条件(=)
  • IN 条件

実務では、以下を意識することが重要です。

  • 「遅い」クエリではなく
  • 「読みすぎている」クエリを確認する

📝 Snowflake の最適化は、
クエリを書くことではなく
データの「置き方」を意識することから始まります。

⬆ 目次へ戻る

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?