pg_stat_statementsはPostgreSQLに標準で入ってる拡張機能で、実際にどんなクエリがデータベースで動いてるか、どんな感じで動いてるかを監視できるんだ。いわば、静かだけど観察力バツグンのアシスタントみたいなもので、どんなSQLクエリが実行されたか、どれくらい時間がかかったか、何回実行されたか、どれくらいシステムに負荷をかけたかを全部記録してくれる。
なんでこれが必要なの?まず、問題のあるクエリを見つけるためだよ。たまに、DBが遅いのは一つの悪者のせいじゃなくて、同じ重いクエリが何回も実行されてるせいだったりする。それに、どのクエリがCPUやメモリ、ディスクのリソースを食ってるかも分かる。あと、インデックスがちゃんと効いてるかもチェックできるし、もしかしたら全然使われてないか、逆に足りてないかもしれない。
pg_stat_statementsを使えば、勘じゃなくてリアルな数字が見えるから、それを元にちゃんと判断して最適化できるんだ。
どうやって遅いクエリを見つける?
ここからが本番!pg_stat_statementsテーブルを使って、実行時間が長いとか、サーバーに負荷をかけてるクエリを探せるよ。
基本の考え方:
pg_stat_statementsテーブルの各行は、1つのクエリの統計情報を表してる。クエリはテキスト(つまりqueryカラム)ごとにグループ化されてて、それぞれに次のメトリクスが集計されてる:
total_time— クエリの合計実行時間(ミリ秒単位)。calls— クエリが実行された回数。mean_time— クエリの平均実行時間(total_time / calls)。rows— クエリが返した行数。
シンプルな分析例
平均実行時間が長いクエリを探してみよう:
SELECT
query,
mean_time,
calls,
rows
FROM
pg_stat_statements
ORDER BY
mean_time DESC
LIMIT 5;
このクエリは、実行時間が長いTOP5のクエリを表示してくれる。mean_timeカラムに500~1000ミリ秒を超える値があったら、それは最適化のサインだよ。
遅いクエリの分析例
例を見てみよう:
さっきのクエリの実行結果はこんな感じ:
| query | mean_time | calls | rows |
|---|---|---|---|
| SELECT * FROM orders WHERE status = 'new'; | 1234.56 | 10 | 10000 |
| SELECT * FROM products | 755.12 | 5000 | 100 |
| SELECT * FROM customers WHERE id = $1 | 543.21 | 1000 | 1 |
何が分かる?
ordersテーブルへのクエリ:実行回数はすごく少ない(たった10回)けど、毎回1万行も引っ張ってきてる。たぶんテーブルがめっちゃ大きいか、インデックスが使われてないんだろうね。
productsテーブルへのクエリ:何千回も呼ばれてる。たぶんアプリのループとかで使われてるんじゃないかな。毎回100行しか返さないけど、回数が多いからこれも問題になるかも。
customersテーブルへのクエリ:実行は速い(543ms)けど、呼ばれすぎてる。
遅いクエリの最適化
問題のクエリが見つかったら、EXPLAIN ANALYZEで実行プランを見てみよう。例えばordersテーブルのクエリなら:
EXPLAIN ANALYZE
SELECT * FROM orders WHERE status = 'new';
何が見える?
Seq Scan:もしシーケンシャルスキャン(全件走査)になってたら、インデックスを追加しよう:
CREATE INDEX idx_orders_status ON orders (status);
フィルタの問題:もしクエリが大量の行を引っ張ってるなら、クエリ自体を見直そう。追加条件をつけたり、結果を制限したりできるかも:
SELECT * FROM orders WHERE status = 'new' LIMIT 100;
実行時間の統計を出す
たまに、問題のクエリが分かりにくい場合もある。例えば、よく関数やサブクエリを呼ぶクエリとか。そんな時はtotal_timeカラムを見ると便利:
SELECT
query,
total_time,
calls,
mean_time
FROM
pg_stat_statements
ORDER BY
total_time DESC
LIMIT 10;
このクエリは、合計実行時間が一番「高い」クエリを表示してくれる。
インデックス最適化のコツ
遅いクエリの原因は、必要なインデックスがないことが多い。pg_stat_statementsを使って、どのクエリがインデックスを使ってないかチェックしよう。同じフィルタ(例えばstatusカラム)で遅いクエリが多いなら、対応するインデックスを追加しよう:
CREATE INDEX idx_orders_status ON orders (status);
その後、EXPLAIN ANALYZEでクエリのパフォーマンスをもう一度チェックしてみて。
pg_stat_statementsを使えば、クエリのパフォーマンスを効率よく監視できるし、「ボトルネック」を見つけてデータベースのパフォーマンスを上げられるよ。クエリの分析は早めに始めるほど、システム全体の最適化が楽になるから、ぜひ活用してみて!
GO TO FULL VERSION