Agile育成ブログ
未来を変える喜びを
未分類

スピルが発生する場合についてのユースケース

1. 「最初の集計ノード」で何が起きていたか

Snowflakeがクエリを実行する際、処理を「ノード(工程)」に分解します。2つ目のクエリでは以下の順で処理が進みます。

  1. データ読み込み: 3つのテーブルをJOINする。
  2. 【最初の集計ノード】: GROUP BY cd_gender, cs_order_number を実行。←ここで大事件が発生!
  3. 2番目の集計ノード: その結果をさらに GROUP BY cd_gender でまとめる。
-- ❌ スピル(メモリ不足)が発生するクエリ
SELECT 
    cd_gender,
    AVG(lp) average_list_price,
    AVG(sp) average_sales_price,
    AVG(qu) average_quantity
FROM (
    -- 【ここが問題!】サブクエリ
    SELECT 
        cd_gender,
        cs_order_number, -- 👈 注文番号(数百万〜数千万種類ある)
        AVG(cs_list_price) lp,
        AVG(cs_sales_price) sp,
        AVG(cs_quantity) qu
    FROM catalog_sales, date_dim, customer_demographics
    WHERE cs_sold_date_sk = d_date_sk
      AND cs_bill_cdemo_sk = cd_demo_sk
      AND d_year = 2000
    GROUP BY 
        cd_gender, 
        cs_order_number -- 👈 ここで「性別×注文番号」の数千万個のバケツを作ろうとしてメモリがパンク!
) inner_query
GROUP BY 
    cd_gender; -- 最後に数個(性別)にまとめているが、前の工程ですでにメモリが溢れている

なぜここでスピルするのか?

cs_order_number(注文番号)は非常に種類が多いため、Snowflakeはこの「最初の集計ノード」で、数百万〜数千万件のユニークな組み合わせをメモリ上に保持しようとします。 しかし、ウェアハウスのメモリ容量を超えてしまうため、データがディスクに溢れ(スピル)、処理が極端に遅くなっていました。


2. 「書き直し」による修正の正体

説明文にある「cs_order_number を削除して実行するだけ」という修正は、**「最初の集計ノードでの負担を 100万分の1 以下にする」**という劇的な改善策です。

  • 修正前: 数千万件の「注文 × 性別」のペアを管理する。
  • 修正後: 数件の「性別」のグループだけを管理する。
-- ✅ メモリ内で完結し、高速に終わるクエリ
SELECT 
    cd_gender, -- 👈 最初から「性別」だけを見る
    AVG(cs_list_price) lp,
    AVG(cs_sales_price) sp,
    AVG(cs_quantity) qu
FROM catalog_sales, date_dim, customer_demographics
WHERE cs_sold_date_sk = d_date_sk
  AND cs_bill_cdemo_sk = cd_demo_sk
  AND d_year = 2000
GROUP BY 
    cd_gender; -- 👈 グループは「男・女・不明」の数個だけ。メモリに余裕で収まる!

これにより、すべての処理がメモリ内で完結(インメモリ処理)できるようになり、スピルが解消されるため、実行時間が半分(あるいはそれ以上)に短縮されるのです。


3. この事例から学べる「Snowflake運用の鉄則」

この説明文が教えてくれている最も重要な教訓は以下の通りです。

  1. 不必要なグループ化を避ける: 最終的に「性別ごと」の集計が見たいだけなら、途中で「注文番号ごと」に細かく分ける必要はありません。
  2. サブクエリ(ネスト)の罠: 「一度中間集計したほうが速くなるかも?」という良かれと思った工夫が、分散データベースでは逆に「データ移動とメモリ消費」を増やして仇となることがあります。
  3. 集計ノードを意識する: クエリプロファイルを見て「Aggregate(集計)」のステップで時間がかかっていたり、スピルが発生していたら、**「そのグループ化、本当にその粒度(細かさ)でやる必要がある?」**と疑うのが高速化の近道です。