Snowflake

【Snowflake】クエリの実行速度が遅い!ウェアハウスを大きくしても改善されない!のときどうするか?

yokochanです!久々にブログ書きます!

Snowflakeを使っていると「クエリが遅い」という問題に突き当たることがあります。多くの場合、まず試みるのが「ウェアハウスサイズを大きくする」という対処ですが、それで解決しないケースが実は少なくありません。

この記事では、Snowflakeのクエリが遅いと判明したときに何をどの順番で確認すべきかを、Query Profileの読み方とあわせて解説します。ETLツール(Matillionなど)を使っている方にも参考になる内容です。

なぜ「ウェアハウスを大きくしても速くならない」のか?

ウェアハウスのサイズを上げると追加されるのはCPUとメモリです。しかし、クエリの遅さがCPUやメモリの不足以外が原因の場合、サイズを上げても効果がありません。

ウェアハウスサイズアップが有効なのは、メモリ不足によるスピル(一時ディスクへの書き込み)が発生しているときに限られます。それ以外の原因には別のアプローチが必要です。

代表的な「サイズアップが効かない原因」は以下の4つです。

Snowflakeクエリ遅延の主な原因マップ

 

  • スキャン量が多い:WHERE句がパーティションキーを使っておらず、不要なデータまで読み込んでいる
  • データ転送量が多い:大量のカラムの引き回しや、同一テーブルへの複数回JOINが発生している
  • クエリ設計の問題:深いネスト構造や早期フィルタリングの未実施
  • 同時実行数の問題:クエリがキューに溜まっており、サイズよりもクラスタ数を増やす必要がある

まず確認する:Query Profile

SnowflakeにはQuery Profileという標準搭載の診断ツールがあります。クエリが遅い原因を特定するための最初の手がかりです。

Query Profile の開き方

Query Profileの開き方手順
  1. Snowsight にログイン
  2. 左メニューの Activity をクリック
  3. Query History を選択
  4. 遅いクエリをクリック
  5. Query Profile タブを選択

 

Query Profile で確認できる主な指標

確認項目 意味 問題のサイン
Processing % 計算処理にかかった時間の割合 大部分を占めていたら計算が重い
Network communication % ノード間データ転送の割合 高い = JOINや集計でデータが大量移動
Bytes Spilled to Remote リモートディスクに流出したデータの量 0以外 = メモリ不足。大きいと特に深刻
Partitions Scanned / Total 実際に読んだパーティションの割合 比率が高い = プルーニングが効いていない
Bytes sent over network ネットワーク越しに転送されたデータ量 数GB以上 = JOIN・集計の設計を見直す
Percentage scanned from cache キャッシュから読んだ割合 高い = 実は再計算していない(問題なし)

診断フローチャート:原因の特定手順

Query Profileを開いたら、以下の順番で確認していきます。上位のチェックで原因が特定できたら、それ以降は確認不要です。
Snowflakeクエリ遅延 診断フローチャート

各原因と対策の詳細

① パーティションプルーニングが効いていない

Snowflakeはデータを「マイクロパーティション」という単位で保存しています。クエリのWHERE条件がパーティションキー列と一致すると、不要な部分を読み飛ばせます(プルーニング)。これが機能していないと大量のデータを無駄に読み込みます。

パーティションプルーニングの効果(改善前後の比較)

確認方法:Query ProfileのStatisticsで Partitions Scanned / Partitions Total の比率を確認します。

対策:

  • WHERE句に日付や区分など、パーティションキーとなる列を含める
  • テーブルにCluster Keyを設定する(よく絞り込みに使う列を指定)
-- クラスタリングキーの設定例
ALTER TABLE sales_data CLUSTER BY (sale_date, region_id);

② Bytes Spilled to Remote が大きい(メモリ不足)

処理するデータがウェアハウスのメモリに収まらないと、一時的にストレージへの書き出し(スピル)が発生します。ディスクアクセスはメモリより桁違いに遅いため、クエリが大幅に遅くなります。

Bytes Spilled to Remoteが大きい場合の対処

この場合に限り、ウェアハウスサイズアップが有効です。XSをMやLにするなど、メモリを増やすことでスピルがなくなり、大幅な改善が見込めます。

③ Bytes sent over network が大きい(データ転送過多)

Snowflakeは複数のノードで並列処理します。JOINやGROUP BYでノード間をデータが行き来するとき、転送量が多いと時間がかかります。ウェアハウスを大きくしてもノード間転送量は変わらないため、サイズアップでは解決しません。

対策:

  • JOINの前に不要な行をWHEREで絞り込む
  • SELECT * をやめて必要な列だけ取得する
  • 大きいテーブル同士のJOINは結合キーやフィルタ条件を見直す
  • 複雑な処理は中間テーブルに分割して段階的に処理する

④ キュー待ちが発生している(同時実行数の問題)

Query ProfileでQueued %が高い場合、クエリ自体は速くても順番待ちで時間がかかっている状態です。この場合はウェアハウスサイズアップではなく、マルチクラスタウェアハウス(同じウェアハウスを複数のクラスタで並列稼働させる設定)で解消できます。

ETLツールを使っている場合の注意点

MatillionやdbtなどのETLツール、TableauやLookerなどのBIツールからクエリが発行される場合、自動生成されたSQLが非効率なパターンを含むことがあります。

ツール側の設定やコンポーネント構成を見直すことで、発行されるSQLを改善できることが多くあります。Query Profileで原因を特定した上で、ツール側の設定に立ち返って確認してみてください。

まとめ:対策の選び方チートシート

原因 主な対策 ウェアハウス変更は有効?
スキャン量が多い プルーニング改善・クラスタリング ❌ 無効
メモリ不足(スピル) ウェアハウスサイズアップ ✅ 有効
ネットワーク転送過多 クエリ設計の見直し ❌ 無効
計算ロジックが重い クエリ分割・最適化 △ 限定的に有効
同時実行数が多い マルチクラスタウェアハウス △ サイズより数を増やす
キャッシュが効いている 対処不要 — 問題なし

Query Profileを習慣的に確認するだけで、多くのパフォーマンス問題の原因を素早く特定できるようになります。「遅い→サイズアップ」の前に、まずQuery Profileを開くことを習慣にしてみてください。

yokochan
データサイエンス事業部マネージャー データ基盤構築やデータ可視化をやっています。 夏は沖縄の海、冬は北海道の山、年がら年中ももクロのライブ会場。
データサイエンス・AI領域の専門集団 GRI
GRIへのお問い合わせはこちらから