「なぜ遅い?」を深掘りする。PostgreSQLの `EXPLAIN VERBOSE` を使いこなそう
現場でデータベースのパフォーマンスチューニングをしていると、必ずぶち当たる壁がありますよね。「`EXPLAIN` を叩いてみたけれど、結局どこがボトルネックなのかイマイチ読み解けない」という瞬間です。
もちろん、普通の `EXPLAIN` や `EXPLAIN ANALYZE` でも十分役には立ちます。でも、一歩踏み込んだ最適化をしたいとき、あるいは「プランナがなぜそのインデックスを選んだのか(あるいは無視したのか)」を追跡したいとき、僕が必ず使うのが `EXPLAIN VERBOSE` です。
今日は、この「VERBOSE」というオプションが、いかに現場の泥臭い調査をスマートにしてくれるか、実務的な視点で解説しますね。
—
VERBOSEが「饒舌」になる瞬間
`EXPLAIN VERBOSE` は、名前の通り「饒舌(verbose)」な情報を吐き出します。通常の実行計画に加えて、以下のような情報が追加されます。
- 出力される全カラム: 各ノードからどのカラムが読み出され、次に渡されているのか。
- 式(Expressions)の詳細: インデックスの条件でどんな計算が走っているのか。
- プランナの内部的な意図: どのインデックスがどう使われ、どうフィルタリングされているのか。
単なる「インデックススキャンをしました」という報告だけでなく、「なぜその条件でそのインデックスを選んだのか」という内情を覗き見ることができるんです。
—
具体的な活用シーン:暗黙の型変換を暴く
例えば、こんなケースを想像してみてください。ユーザーID(`user_id`)にインデックスを貼っているのに、クエリがなぜかフルスキャン(Seq Scan)になってしまう。そんなとき、`EXPLAIN VERBOSE` が真価を発揮します。
— 試しにVERBOSEを付けて実行してみる
EXPLAIN (ANALYZE, VERBOSE)
SELECT FROM orders WHERE user_id = ‘100’;
もし `user_id` が `integer` 型なのに、クエリで `’100’`(文字列)として渡していたら、VERBOSEの出力にはこんな一行が隠れているはずです。
> `Filter: (user_id = (100)::integer)`
これです。「暗黙の型変換」が起きている証拠ですね。`VERBOSE` を付けていなければ、単に `Filter: (user_id = 100)` としか見えず、なぜインデックスが効かないのか悩んで終わることも多い。でも、VERBOSEなら型変換のコストや、プランナがどう判断したかを明示的に教えてくれるんです。
—
実務で「これだけは見ておけ」というポイント
僕が `VERBOSE` を使うとき、特に注目するのは「出力カラム」の確認です。
Output: id, created_at, status
ここをチェックすることで、「不要なカラムをたくさんSELECTしていないか?」「Covering Index(インデックスだけでクエリを完結させる手法)が本当に効いているのか?」を瞬時に判断できます。
特に、`Index Only Scan` になっているはずなのに、実際にはテーブルに何度もアクセス(Heap Fetch)が発生しているようなケース。VERBOSEで見れば、どのカラムが原因でテーブル参照に戻っているのか、その「犯人」を特定できるんです。
—
先輩からのワンポイントアドバイス
`EXPLAIN (ANALYZE, VERBOSE, BUFFERS)`
現場でチューニングをするなら、この組み合わせが最強です。`BUFFERS` を足すことで、「そのクエリがメモリ(共有バッファ)から読み込まれたのか、それともディスクから読み込まれたのか」が分かります。
- VERBOSE: プランの「論理的な構造」を暴く
- ANALYZE: 「現実の実行時間」を突きつける
- BUFFERS: 「I/O負荷」を可視化する
この三種の神器を揃えておけば、たいていのパフォーマンス問題は「なぜそうなるのか」というロジックとともに解消できます。
—
まとめ
`EXPLAIN VERBOSE` は、単なるデバッグ用オプションではありません。PostgreSQLのプランナと対話するための「翻訳機」のようなものです。
「なぜSQLが遅いのか?」と悩んだとき、まずは `VERBOSE` を付けて、プランナが裏側で何を考えているのかを覗いてみてください。最初は情報の多さに圧倒されるかもしれませんが、その「饒舌さ」こそが、あなたのチューニングスキルを一段上のレベルへ引き上げてくれるはずです。
もし現場で「どうしても最適化できないクエリ」に出くわしたら、まずはVERBOSE。これ、エンジニアの鉄則ですよ!
コメント