CodeGym /コース /SQL SELF /pg_stat_statementsで遅いクエリを追跡する方法

pg_stat_statementsで遅いクエリを追跡する方法

SQL SELF
レベル 42 , レッスン 2
使用可能

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を使えば、クエリのパフォーマンスを効率よく監視できるし、「ボトルネック」を見つけてデータベースのパフォーマンスを上げられるよ。クエリの分析は早めに始めるほど、システム全体の最適化が楽になるから、ぜひ活用してみて!

コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION