「遅いクエリ」に立ち向かう君へ。EXPLAIN ANALYZEは怖くない!
現場で働いていると、必ず一度は遭遇するよね。「さっきまでサクサク動いていたはずの検索画面が、急に重くなった」とか、「数万件のデータでこのレスポンスはさすがにマズい」といったトラブル。
そんな時、とりあえず `SELECT FROM …` を眺めて悩むのはもう終わりにしよう。PostgreSQLには、「なぜそのクエリが遅いのか」を白日の下に晒す最強の武器がある。それが `EXPLAIN ANALYZE` だ。
今日は、僕が実務でどうやってこのツールと付き合っているか、その「現場の勘所」を伝授するよ。
—
EXPLAIN ANALYZE って結局なんなの?
一言で言うと、「クエリの健康診断」だ。
ただの `EXPLAIN` は「どう動く予定か」という計画書を出すだけ。でも、`EXPLAIN ANALYZE` は実際にクエリを実行して、「計画と現実にどれくらいのギャップがあったか」まで教えてくれる。
大事なのは、「計画(見積もり)と現実(実績)のズレ」を見つけること。これがチューニングの第一歩なんだ。
実践!こんな風に使ってみよう
例えば、ユーザーのアクセスログを検索するこんなクエリが遅いとするよ。
EXPLAIN (ANALYZE, BUFFERS)
SELECT FROM access_logs
WHERE user_id = 12345
AND created_at > ‘2023-01-01’;
ここで一つコツ。`BUFFERS` オプションを必ず付けること。「ディスクから読んだのか、メモリ(キャッシュ)から読んだのか」が分かるだけで、問題の深刻さが全然違って見えるからね。
結果が返ってきたら、特に以下のポイントをチェックするんだ。
- actual time: 実際に何ミリ秒かかったか。
- rows: 実際に何行ヒットしたか。
- loops: 何回その処理を繰り返したか(ここが予想より多いと要注意)。
- Shared Hit/Read: キャッシュヒット率の指標。ここが多いとI/O負荷が高い証拠。
「あれ?計画と違うぞ?」がチューニングのサイン
よくある「罠」がこれだ。
PostgreSQLのオプティマイザは、テーブルの統計情報をもとに「この検索ならインデックスを使うのが速いな」と判断する。でも、統計情報が古かったり、データが偏っていたりすると、「全件スキャン(Sequential Scan)したほうがマシ」という誤った判断を下すことがある。
もし `EXPLAIN ANALYZE` の結果で、本来インデックスが効くはずの場所で `Seq Scan` が走っていたら、まずは `ANALYZE` コマンドを叩いて統計情報を更新してみよう。これだけで解決することも案外多いんだ。
それでも直らないなら、インデックスの設計を見直すタイミングだね。
現場で気をつけるべき「注意点」
これだけは絶対に忘れないでほしい。
「`EXPLAIN ANALYZE` はクエリを実際に実行する」ということ。
つまり、`UPDATE` や `DELETE` 文に `ANALYZE` を付けたら、本当にデータが書き換わってしまう。 これをやって青ざめたエンジニアを何人も見てきたよ。本番環境で実行する時は、必ず `BEGIN;` でトランザクションを張ってから実行して、最後に `ROLLBACK;` する癖をつけておこう。
最後に:道具に振り回されないために
`EXPLAIN ANALYZE` の結果は、最初は呪文のように見えるかもしれない。でも、何度も見ていると「あ、ここはループが多すぎるな」「結合の順序が不自然だな」と、直感的にわかるようになる。
ツールはあくまで補助輪だ。一番大事なのは、「データがどう格納され、どう検索されるのが理想か」を想像する力だよ。
もしクエリの実行計画で詰まったら、いつでも相談してくれ。一緒にコードを読み解こう。君が書いたクエリが、明日から少しでも速く、美しく動くことを願っているよ!
コメント