はじめに:大規模テーブルの「遅い…」を解決するカギ
Snowflakeを使っていると、テーブルが数億行・数TBになってきた頃から「同じクエリなのに前より遅くなった気がする」と感じることがあります。原因の多くは、データが物理的にバラバラに散らばっていて、目的の行を見つけるまでに大量のデータを読み込んでしまっていることです。
そこで登場するのが クラスタリングキー(Clustering Key) です。この記事では、以下のような疑問を一通り解決できる構成でやさしく解説します。
- クラスタリングキーとは何か / プルーニングの仕組み
- どのカラムを選べばいいのか(判断基準)
- CLUSTER BYの具体的な設定方法
- 効果が出ているかを確認するSQL
- Automatic Clusteringが消費する コストの監視方法
- Search Optimization / マテリアライズドビュー など 代替手段との使い分け

前提:マイクロパーティションとプルーニング
クラスタリングキーを理解するには、まず マイクロパーティション を押さえておく必要があります。Snowflakeはテーブルのデータを、内部的に 圧縮後16〜500MB程度の小さな塊(マイクロパーティション)に分割して保存しています。
クエリ実行時、Snowflakeは各マイクロパーティションのメタデータ(カラムごとの最小値・最大値など)を見て「このパーティションには目的の値が含まれるか?」を判定し、関係ないパーティションをスキップします。これが プルーニング(枝刈り) です。プルーニングがよく効くほど、読み込むデータ量が減って高速化します。
クラスタリングキーは、この プルーニングを最大限効かせるためにデータの並びを最適化する指定 です。マイクロパーティションそのものの仕組みは マイクロパーティションの記事 をご覧ください。
クラスタリングキーの仕組み
クラスタリングキーは「このカラムで似た値同士を同じパーティションに集めておいてね」とSnowflakeに伝える指定です。たとえば order_date をクラスタリングキーにすると、同じ日付の注文データが同じパーティションに固まりやすくなります。
WHERE order_date = '2026-05-01' で検索したとき、
クラスタリング前は「2026-05-01のデータが入っているかもしれないパーティション」が
テーブル全体に散らばっているのに対し、クラスタリング後は数個のパーティションに固まっているため、
読み込み量が劇的に減ります。
クラスタリングキーの選び方(判断基準)
クラスタリングキーは 選ぶ列で効果が大きく変わります。次のチェックリストで判断してください。
選ぶべき条件
- 大規模テーブル(目安1TB以上 / 数億行以上)である
- そのカラムが
WHERE・JOIN・ORDER BYで頻繁に使われる - カーディナリティが中〜高(=ユニーク値が多すぎず少なすぎない)
- 自然なロード順とアクセス順がズレている
選ぶべきでないカラム
- ユニーク値が極端に多い(主キー / GUID など)→ ほぼ全パーティションに散る
- カーディナリティが極端に低い(true/false / 性別 など)→ プルーニング効果なし
- ほとんどクエリで使われない
- 頻繁に更新される(再クラスタリングコストが増大)
複数カラム指定のコツ
キーは複数列指定できます。粒度の粗いカラムを先頭、細かいカラムを後 に書くのが定石です。たとえば「日付 → リージョン → 顧客ID」のような順。逆にすると先頭列のカーディナリティが高すぎてプルーニングが効きません。
| 候補カラム | カーディナリティ | クエリ頻度 | 推奨 |
|---|---|---|---|
| order_date | 中 | 高 | ◎ |
| region | 低〜中 | 高 | ◯(複合キーで補助) |
| customer_id | 高 | 高 | ◯(複合キーの末尾) |
| order_id (PK) | 超高 | 中 | ✗ |
| is_active (bool) | 超低 | 中 | ✗ |
カーディナリティが高すぎる列をどうしても使いたい場合は、CLUSTER BY (TO_DATE(created_at), customer_id) のように 関数で粒度を粗くする式クラスタリング も有効です。
実際に設定してみよう
クラスタリングキーは CLUSTER BY 句で指定します。テーブル作成時にも、後から ALTER TABLE でも設定できます。
-- テーブル作成時に指定
CREATE TABLE sales (
order_id NUMBER,
order_date DATE,
region STRING,
amount NUMBER
)
CLUSTER BY (order_date, region);
-- 既存テーブルに後から追加
ALTER TABLE sales CLUSTER BY (order_date, region);
-- クラスタリングキーを変更
ALTER TABLE sales CLUSTER BY (order_date, customer_id);
-- クラスタリングキーを解除
ALTER TABLE sales DROP CLUSTERING KEY;
-- 現在のクラスタリングキーを確認
SHOW TABLES LIKE 'sales';
-- もしくは
SELECT GET_DDL('TABLE', 'sales');
クラスタリングの状態を確認する
「ちゃんと整列されているの?」を確認するには、SYSTEM$CLUSTERING_INFORMATION 関数を使います。
-- 全体のクラスタリング状態
SELECT SYSTEM$CLUSTERING_INFORMATION('sales', '(order_date, region)');
-- 深さ(=重なり度合い)だけ取りたい場合
SELECT SYSTEM$CLUSTERING_DEPTH('sales', '(order_date, region)');
返ってきたJSONの主要項目は次のとおりです。
| フィールド | 意味 | 読み方 |
|---|---|---|
average_depth |
パーティションの平均重なり度合い | 小さいほど良い(1に近いほど整列済) |
average_overlaps |
1パーティションが平均何個と重なっているか | 小さいほど良い |
total_partition_count |
テーブル全体のパーティション数 | サイズ感の把握に |
partition_depth_histogram |
深さの分布 | 浅いバケットに偏っていれば良好 |

効果が出ているかを確認する(クエリプロファイル)
クラスタリングキー設定の 本当の効果 は、実クエリでのスキャン量で測ります。クエリプロファイル の TableScan ノードで「Partitions scanned / Partitions total」を確認しましょう。
- クラスタリング前: 100,000 / 100,000(=ほぼ全スキャン)
- クラスタリング後: 1,200 / 100,000(=99%スキップ)
このように scanned / total の比率が大幅に下がれば成功 です。逆に比率が変わらない場合は、選んだ列がアクセスパターンに合っていない可能性が高いので見直しが必要です。
Automatic Clusteringとコスト監視
Snowflakeはクラスタリングキーが設定されたテーブルを 自動で再クラスタリング してくれます(Automatic Clustering)。手作業で並び替える必要はありません。
ただし再クラスタリングは Serverlessクレジットを消費 します。頻繁な大量更新が走るテーブルに無造作にキーを付けると、思わぬコスト増になることも。ACCOUNT_USAGE のビューで定期的に確認するのがおすすめです。
-- ① 直近30日のテーブル別 Automatic Clustering コスト
SELECT TABLE_NAME,
SUM(CREDITS_USED) AS TOTAL_CREDITS
FROM SNOWFLAKE.ACCOUNT_USAGE.AUTOMATIC_CLUSTERING_HISTORY
WHERE START_TIME >= DATEADD('day', -30, CURRENT_TIMESTAMP())
GROUP BY TABLE_NAME
ORDER BY TOTAL_CREDITS DESC
LIMIT 20;
-- ② 自動クラスタリングを一時停止
ALTER TABLE sales SUSPEND RECLUSTER;
-- ③ 自動クラスタリングを再開
ALTER TABLE sales RESUME RECLUSTER;
コスト面で気になるテーブルは、いったん SUSPEND RECLUSTER でクラスタリングだけ止めて、クエリ性能と再開のタイミングを観察するのが安全です。
代替手段との使い分け
クラスタリングキーは強力ですが、ベストな高速化手段とは限りません。テーブル特性とクエリ特性に応じて使い分けましょう。
| 手段 | 得意なケース | 苦手なケース | コスト |
|---|---|---|---|
| クラスタリングキー | 日付など範囲スキャンが多い大規模テーブル | 小規模 / 高頻度更新 / ピンポイント検索 | 再クラスタリング(Serverless) |
| Search Optimization | 高カーディナリティ列のピンポイント検索(=文字列・ID検索) | 範囲スキャン / 集計 | テーブルサイズ比例のServerless |
| マテリアライズドビュー | 同じ集計を何度も繰り返す | アドホックな探索 / 高頻度更新元テーブル | 自動再計算のServerless |
| 適正サイズのウェアハウス | 短時間で確実に大きなワークロードを処理 | アクセスパターンの根本問題 | 通常のクレジット消費 |
詳細はそれぞれの個別記事を参照してください。SEARCH OPTIMIZATION / ビューとマテリアライズドビュー
よくある質問(FAQ)
Q. クラスタリングキーは1テーブルにいくつ設定できますか?
1テーブルにつき 1つ のクラスタリングキー(複数カラム指定は可能)です。複数キーを切り替えたい場合は ALTER TABLE ... CLUSTER BY (...) で上書きします。
Q. PRIMARY KEYやUNIQUEと違いはありますか?
はい、別物です。Snowflakeでは PRIMARY KEY や UNIQUE 制約は 強制されない 情報のみの制約です。一方、CLUSTER BY は 実際に物理データの並びを最適化する 仕組みです。
Q. 小さいテーブルにも付けた方がいいですか?
いいえ、目安1TB未満なら不要 です。プルーニングの恩恵より再クラスタリングのコストが上回るケースが多いので、まずはクエリプロファイルで実際のスキャン量を確認してから判断しましょう。
Q. クラスタリングキーを設定したのに速くなりません
次の3点をチェックしてください。
1. クエリの WHERE句が キー列を直接参照 しているか(関数や型変換を挟むとプルーニングが効きません)
2. SYSTEM$CLUSTERING_DEPTH の値が下がっているか(下がっていなければ再クラスタリングがまだ進行中)
3. クエリプロファイルの Partitions scanned / total が下がっているか
Q. Automatic Clusteringを止めても問題ありませんか?
SUSPEND RECLUSTER はクラスタリング設定自体は残したまま再編成だけ停止します。新規ロードでデータの並びが乱れていくので、長期間止めるとプルーニング効果が落ちます。あくまでコスト調査用の一時措置と考えてください。
まとめ
クラスタリングキーは大規模テーブルのプルーニングを効かせて高速化する強力な仕組みです。本記事のポイントをおさらいすると次のとおりです。
- クラスタリングキーは マイクロパーティション内のデータ配置を最適化する指定
- 選ぶカラムは カーディナリティ中〜高 × クエリ頻度高が基本
- 複数列指定は 粒度の粗い順 に書く
- 効果確認は SYSTEM$CLUSTERING_INFORMATION + クエリプロファイル
- Automatic Clusteringの コストをACCOUNT_USAGEで監視する
- 用途に合わなければ Search Optimization / マテリアライズドビュー も検討
「とりあえず付ける」のではなく、テーブルサイズ・アクセスパターン・更新頻度を見極めて選びましょう。
参考リンク
- クラスタリングキーとクラスタ化テーブル | Snowflake Documentation
- マイクロパーティションとデータクラスタリング | Snowflake Documentation
- 自動クラスタリング | Snowflake Documentation
関連記事
- Snowflakeのマイクロパーティションとは?自動最適化の仕組みを解説 – クラスタリングキーの土台となるパーティションの仕組み
- Snowflakeクエリプロファイル入門|遅いクエリのボトルネックを見抜く方法 – クラスタリングキーの効果を確認するときに必須のツール
- SEARCH OPTIMIZATIONで爆速化!Snowflakeイテレーティブテーブル活用術 – ピンポイント検索向けのもう一つの高速化機能
- Snowflakeビューとマテリアライズドビューの違い|初心者向け使い分けガイド – 集計クエリの高速化ならこちらも検討


