PostgreSQLの「無駄な結合」を勝手に消してくれる話、知ってる?
やあ。最近、コードレビューで「このJOIN、本当に必要?」って聞く機会が増えたんだよね。
「いや、外部結合してるし、念のためデータ取っておこうと思って……」なんて返ってくるんだけど、実はPostgreSQLのオプティマイザって、僕らが思うよりずっと賢いんだ。「結果に影響を与えない結合なら、そもそも実行計画から消しちゃえばいいじゃん」っていう、いわゆる「結合の除去(Join Removal)」という最適化を裏でやってくれている。
これを知っていると、クエリの意図がより明確になるし、パフォーマンスのボトルネックを未然に防ぐことにもつながる。今日はその仕組みを、現場目線でサクッと解説するよ。
—
そもそも「結合の除去」って何?
ざっくり言うと、「わざわざJOINしているけど、結局そのテーブルの列を一つも使っていないし、結合条件も主キー(PK)やユニーク制約で1対1が保証されているなら、JOINしなくてよくない?」という賢い判断のことだ。
PostgreSQLは、クエリを最適化する過程で「このJOIN、実行しても結果に影響ないな」と判断すると、そのテーブルへのアクセスそのものをバッサリ切り落とす。これによって、無駄なI/OやCPUリソースを節約できるわけだ。
具体的なコードで見てみよう
例えば、ECサイトの注文管理システムを想像してみて。`orders`(注文テーブル)と、その詳細情報が入っている `order_details`(注文詳細テーブル)があるとする。
SELECT
o.order_id,
o.customer_id
FROM
orders o
LEFT JOIN
order_details od ON o.order_id = od.order_id;
もし、`order_details` テーブルに `order_id` が主キー(またはユニーク制約)として定義されていて、かつ `SELECT` 句で `od` のカラムを一つも参照していなかったら……PostgreSQLはどうすると思う?
そう、`order_details` への結合を完全に無視して実行するんだ。
なぜこれが可能なのか?
ここが重要なポイントなんだけど、この最適化が発動するには条件がある。
1. 外部結合(LEFT/RIGHT JOIN)であること:内部結合(INNER JOIN)だと、結合先が存在しないレコード自体が消えてしまうから、結合自体を削除することはできないよね。
2. 結合先テーブルの列を参照していないこと:まあ、当然だよね。
3. 結合条件が「1対1」であること:ここが一番大事。`orders.order_id` と `order_details.order_id` がユニークであることを、PostgreSQLが制約(Primary KeyやUnique Constraint)として知っている必要がある。
もし制約がないと、オプティマイザは「もしかしたら同じ `order_id` が `order_details` に複数あるかも……」と疑ってしまう。そうなると、結合を削除すると行数が増えたり減ったりして結果が変わってしまうから、最適化は行われないんだ。
実務で意識してほしいこと
「じゃあ、とりあえず全部のテーブルを結合しておけば、賢いPostgreSQLが勝手に最適化してくれるから楽だね!」……なんて思ったら大間違いだよ。
この最適化はあくまで「ミスや冗長な記述をカバーする安全装置」であって、最初からクエリを汚く書いていい理由にはならない。
- オプティマイザを信じすぎない:複雑なクエリになればなるほど、オプティマイザが「結合の除去」を判断できないケースも増える。不要なJOINは、書かないのが一番のパフォーマンスチューニングだ。
- 制約の重要性:PostgreSQLに「このテーブルとこのテーブルは1対1の関係ですよ」と教えるために、外部キーやユニーク制約は必ず貼っておこう。これが適切に定義されているだけで、データベースはより賢く動けるようになるんだから。
最後に:確認の仕方は?
もし「このクエリ、本当に結合が消えてるかな?」と気になったら、`EXPLAIN` を使ってみれば一発だ。
EXPLAIN SELECT o.order_id FROM orders o LEFT JOIN order_details od ON o.order_id = od.order_id;
出力結果を見て、`order_details` テーブルへのスキャン(`Seq Scan` や `Index Scan`)が出てこなければ、無事に除去されている証拠だ。
パフォーマンス改善の基本は、「無駄なことをしないこと」。PostgreSQLという強力な相棒に頼りつつも、僕らエンジニア側も「本当にこのデータが必要か?」と問いかける姿勢は忘れないようにしたいね。
それじゃ、また現場で!
コメント