「二度手間」を避ける賢い仕事術。PostgreSQLの「サブクエリ平坦化」ってなに?
こんにちは!データベースの世界に足を踏み入れたばかりのみなさん、日々SQLと格闘していますか?
今日は、PostgreSQLが裏側でやってくれている「実はめちゃくちゃ優秀な気配り」についてお話ししたいと思います。タイトルにある「サブクエリの平坦化(Subquery Flattening)」。なんだか難しそうな名前ですよね。でも、これ、実は私たちの日常の「仕事の効率化」と全く同じ考え方なんです。
—
「伝言ゲーム」は時間がかかる
想像してみてください。あなたは今、上司から「A部署のメンバーの中で、先月の売上が100万円を超えた人の名前をリストアップして」と頼まれました。
もし、あなたがこんなふうに動いたらどうでしょう?
1. まず別の作業員に頼む: 「とりあえず、先月の売上が100万円超えた人たちだけを別の紙に書き出して!」
2. その紙を受け取る: 「はい、リストができました」
3. それを見てから探す: 「じゃあ、このリストに載っている人のうち、A部署に所属している人を調べよう……」
これ、二段階に分かれていますよね。でも、もし最初から「A部署にいて、かつ先月の売上が100万円を超えた人」という条件がわかっていれば、一度の確認で済みます。
データベースの世界でも、SQLが「サブクエリ(入れ子構造)」になっていると、PostgreSQLはまさにこの「二度手間」を強いられることがあるんです。
PostgreSQLの「賢い気配り」:サブクエリの平坦化
PostgreSQLのプランナ(SQLをどう実行するか考える司令塔)は、とても優秀です。
もしあなたがサブクエリを使って「まず抽出して、次に絞り込む」ような複雑な書き方をしても、PostgreSQLはこう考えます。
「あ、わざわざリストを一度作らなくても、最初から『A部署かつ売上100万』で検索したほうが、結果は同じだし圧倒的に速いよね!」
そして、内部的にSQLを書き換えて、最初から効率の良い「JOIN(結合)」の形に直して実行してくれるんです。これが「サブクエリの平坦化」です。
わざわざ「やり方を変えて」と指示しなくても、データベース側が「もっといい方法があるよ」と気を利かせてくれるなんて、頼もしいですよね。
—
「せっかくの気配り」ができなくなってしまう時
でも、この優秀なプランナも、時には「お手上げ」になってしまうことがあります。どんな時だと思いますか?
それは、「後から変更できない条件」がついている時です。
例えば、こんなケースです。
- 「とりあえず100万以上のリストを作ってから、その中からランダムに5人選ぶ」 というような指示がある場合。
- 「グループごとに集計した結果に対して、さらに処理を加える」 というような、先に計算を確定させないと次のステップに進めない場合。
これらは、いわば「完成した料理の盛り付けを変える」ようなもので、元々の材料(テーブル)を直接いじることはできません。
具体的には、以下のようなキーワードが含まれていると、PostgreSQLは「あ、これは勝手に平坦化しちゃダメなやつだ」と判断して、律儀にサブクエリを先に実行してしまいます。
- `DISTINCT` (重複を除去する)
- `GROUP BY` (グループ化する)
- `LIMIT` (件数を制限する)
- `UNION` (結果を合体させる)
これらが入っていると、データベースは「先に計算を済ませてからじゃないと、正確な答えが出せない」と判断するため、平坦化の魔法は使えなくなってしまうんです。
—
最後に:私たちはどう付き合えばいい?
もちろん、サブクエリを使うことが悪いわけではありません。コードの可読性(読みやすさ)を考えると、あえてサブクエリにした方が誰が見てもわかりやすい場合もあります。
でも、もしデータベースが「なんだか最近、動きが重いな?」と感じたときは、少しだけ思い出してみてください。
「もしかして、このサブクエリ、PostgreSQLに平坦化を諦めさせてしまっているかな?」と。
もしそうなら、サブクエリを使わずにJOINだけで書けないか工夫してみる。たったそれだけで、実行スピードが劇的に改善することもありますよ。
データベースは、私たちが思っている以上に「空気」を読んで動いてくれています。ぜひ、彼ら(データベース)が一番働きやすい書き方を探してあげてくださいね。
それでは、また次回の記事でお会いしましょう!Happy Querying!
コメント