【実務・中級編】 pg_stat_statements拡張 – PostgreSQL

「なんとなく遅い」を卒業しよう。PostgreSQLの神ツール『pg_stat_statements』を使い倒す話

現場で働いていると、よくあるよね。「なんか最近、DBの負荷が高い気がする」「特定の処理がたまに異様に遅い」っていう相談。

こういう時、勘でインデックスを貼ったり、適当に `EXPLAIN` を眺めたりしてない? それ、実はすごく遠回りなんだ。PostgreSQLを運用する上で、「何が起きているか」を数字で語れるようになること。これがプロのエンジニアへの第一歩だ。

今日は、僕が現場で必ずと言っていいほど最初に入れる拡張機能、`pg_stat_statements` について語らせてほしい。

—

pg_stat_statements って何者?

一言で言えば、「DBがこれまで実行してきた全クエリの成績表」だよ。

どのクエリが何回実行されて、合計でどれくらい時間を食っていて、どれくらいディスクI/Oを発生させたのか。これらが全部、集計データとして保存される。これがないと、DBのチューニングは「目隠しをして迷路を歩く」ようなものだ。

まずは導入のステップ

PostgreSQLの標準機能なんだけど、有効化しないと動かない。まずは設定ファイル(`postgresql.conf`)に以下を書き込んで、再起動だ。

shared_preload_libraries = ‘pg_stat_statements’

これを入れて再起動すると、`pg_stat_statements` というビューができる。これが僕らの相棒だ。

—

実践:ボトルネックを一瞬で見つけるクエリ

入れただけで満足しちゃダメだ。大切なのは「どうやってボトルネックをあぶり出すか」。現場でよく使う、このクエリを叩いてみてほしい。

SELECT
query,
calls,
total_exec_time / calls AS avg_time,
rows,
shared_blks_hit,
shared_blks_read
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;

このクエリから何がわかるか?

  • `total_exec_time`: 全体として一番時間を食っているクエリはどれか。
  • `avg_time`: 1回あたりの平均実行時間。ここが長いと、インデックスが効いていない可能性が高い。
  • `shared_blks_read`: メモリ(キャッシュ)に載っておらず、ディスクから読み込んだブロック数。ここが多いクエリは、物理的に遅い。

もし、あるクエリが実行回数は少ないのに `total_exec_time` がぶっちぎりで高いなら、それはまさに「改善のしがいがある宝の山」だ。

—

注意点:これだけは覚えておいて

すごく便利なツールだけど、運用する上で2つだけ気をつけてほしいことがある。

1. 統計情報の蓄積: 統計情報はメモリに溜まる。サーバーが再起動すると消えるので、恒久的に分析したいなら定期的に別テーブルに退避させるような運用が必要だ。
2. 正規化の仕組み: `pg_stat_statements` は、同じクエリ(値が違っても構文が同じもの)を自動的にひとまとめにしてくれる。だから「WHERE id = 1」と「WHERE id = 2」は同じ行として集計される。これはすごく優秀なんだけど、あまりにクエリの種類が多いとメモリを食うこともある。その時は `pg_stat_statements.max` のパラメータで調整してくれ。

—

最後に:チューニングは「計測」から始まる

僕が後輩によく言うのは、「自分の直感を疑え」ということだ。

「ここが遅い気がする」という感覚は大事だけど、数値という証拠がないと、チューニングの結果が正しかったのか、たまたま運が良かっただけなのかがわからない。

`pg_stat_statements` を使えば、改善した後に「実行時間が平均で300msから10msになった」と胸を張って言えるようになる。この積み重ねが、君を「頼れるエンジニア」にしてくれるはずだよ。

さっそく今日の夜、自分の担当しているDBでこのビューを覗いてみてよ。きっと、今まで見えていなかった「改善のチャンス」がたくさん転がっているはずだから。

また何か困ったことがあったら、いつでも聞いてくれ。応援してるよ。

コメント

タイトルとURLをコピーしました