CodeGym /コース /SQL SELF /pg_stat_statementsで遅いクエリを分析しよう

pg_stat_statementsで遅いクエリを分析しよう

SQL SELF
レベル 45 , レッスン 4
使用可能

リアルなプロジェクトで開発してると、アプリに同時に何千人ものユーザーがアクセスしてくることがあるよね。みんながDBにクエリを投げて、データを追加したり読んだり更新したり... で、気づいたらサーバーが「うぅ...」って悲鳴を上げてる。これはクエリが全然最適化されてないサイン。紙の上では「イケてる」クエリも、実際にはパフォーマンスの大惨事になることもある。そんな時に登場するのがpg_stat_statementsだよ。

pg_stat_statementsを使うと、こんなことができる:

  1. 遅いクエリを追跡できる。
  2. どのクエリが何回実行されたか分かる。
  3. それぞれのクエリにどれだけ時間がかかったか分かる。
  4. クエリの平均実行時間が見える。
  5. アプリ全部書き直すみたいな致命的ミスを防げる!

pg_stat_statementsの構造を見てみよう

拡張機能を有効化すると、DBにpg_stat_statementsっていう特別なビューができる。ここに実行されたクエリのデータが全部入ってる。まずは中身を見てみよう:

SELECT * FROM pg_stat_statements LIMIT 1;

結果はこんな感じ(シンプルにしてるよ):

query calls total_time rows shared_blks_read
SELECT * FROM students 500 20000 ms 5000 100

ざっくり説明すると:

  • query — SQLクエリそのもの。
  • calls — このクエリが何回実行されたか。
  • total_time — このクエリが合計でどれだけ時間を使ったか。
  • rows — クエリが返した行数。
  • shared_blks_read — 読み込んだブロック数(キャッシュ使ってなければディスクから読むよ)。

結果を分析しよう

さて、pg_stat_statementsが有効になったら、遅いクエリをどうやって見つけるか見てみよう。

一番遅いクエリを探す

どのクエリが一番時間を食ってるか調べるには、こんなクエリを使う:

SELECT query, total_time, calls, mean_time
FROM pg_stat_statements
ORDER BY total_time DESC
LIMIT 5;

ここで:

  • mean_time — 1回あたりの平均実行時間(total_time / calls)。
  • ORDER BY total_time DESC — 合計実行時間でソートしてる。

よく実行されるクエリを探す

問題は遅いクエリだけじゃなくて、実行回数が多すぎるクエリにもある。例えば:

SELECT query, calls
FROM pg_stat_statements
ORDER BY calls DESC
LIMIT 5;

クエリの最適化

  1. インデックスを使おう

特定のカラムでクエリが遅いなら、そのカラムにインデックスがあるか確認しよう。例えば、studentsテーブルに大量の行があって、last_nameカラムによくアクセスするなら、インデックスを作るといい:

CREATE INDEX idx_students_last_name ON students (last_name);
  1. クエリを書き直そう

例えば、SELECT * FROM orders WHERE amount > 1000みたいなクエリがめっちゃ遅い場合、全部のカラムを取るんじゃなくて必要なカラムだけ選ぼう:

SELECT order_id, amount FROM orders WHERE amount > 1000;

統計情報のリセット

最適化後の新しい結果だけ見たいときは、pg_stat_statementsのデータをリセットしよう。コマンドはこれ:

SELECT pg_stat_statements_reset();

電卓の「リセット」ボタンみたいな感じ。実行したら統計がまたゼロから集計されるよ。

問題クエリの探し方

例えば、君が大学のDB管理者で、学生たちが「マイページが全然開かない!」って大量にクレームしてきたとしよう。そこでpg_stat_statementsをチェックする:

ステップ1: 一番遅いクエリを探す

SELECT query, total_time, calls, mean_time
FROM pg_stat_statements
ORDER BY total_time DESC
LIMIT 1;

例えばSELECT * FROM students WHERE status = 'active'みたいなクエリが30秒もかかってるのを発見。「やばっ」ってなるよね。すぐ対策しよう。

ステップ2: インデックスを確認 studentsテーブルを見てみたら、statusカラムにインデックスが無いことに気づく。すぐ追加しよう:

CREATE INDEX idx_students_status ON students (status);

ステップ3: 結果を確認 最適化した後、もう一度pg_stat_statementsを見てみると、クエリが0.5秒で終わるようになってる。やったね!

pg_stat_statementsでよくあるミス

クエリ分析で管理者がやりがちなミス:

  1. 拡張機能が有効化されてないshared_preload_librariespg_stat_statementsを追加し忘れると、統計が全然集まらないよ。
  2. インデックスを無視する。クエリが遅い時、インデックス追加で一発解決することも多い。
  3. 統計のリセットをしないpg_stat_statements_reset()を実行しないと、古いデータが混ざって今の状況が分かりにくくなる。

pg_stat_statementsを使うのは、DBのGPSナビみたいなもん。どこで「渋滞」してるか教えてくれるし、どうやって回避するかもヒントをくれる。ちゃんと設定して使いこなせば、DBのパフォーマンスがグッと良くなるよ!

1
アンケート/クイズ
PostgreSQLモニタリング、レベル 45、レッスン 4
使用不可
PostgreSQLモニタリング
PostgreSQLモニタリング
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION