データベースのmonitoringをpg_stat_activityやpg_stat_user_tablesなしでやるのは、体温だけで健康を判断するのと同じ感じ。全体しか見えなくて、どこに問題があるのか分からないよね。この2つのPostgreSQLのキーツールを使えば、ただ眺めるだけじゃなくて、実際に何が起きてるかをガッツリ分析できるんだ。
pg_stat_activityって何?
pg_stat_activityは、PostgreSQLのシステムビューで、データベースへの全接続の情報を表示してくれるやつ。誰がDBに繋いでるのか、今どんなクエリが走ってるのか、「アイドル」状態で止まってる接続はどれか、みたいな疑問に答えてくれる。サーバーの今のアクティビティを分析するためのツールだよ。
じゃあ、pg_stat_activityで見れる主なカラムを見てみよう。datnameはクライアントが繋いでるデータベース名、usenameは接続してるユーザー名。application_nameはその接続を使ってるアプリ名、client_addrはサーバーに繋いでるクライアントのIPアドレス。backend_startはクライアントがサーバーに繋いだ時間、stateは今の接続状態(active、idle、idle in transactionとか)、queryは今実行中または直近で実行されたクエリが入ってる。
例1: 全アクティブ接続の確認
アクティブな接続を見たいときは、こんなクエリを実行してみて:
SELECT datname, usename, client_addr, state, query
FROM pg_stat_activity
WHERE state = 'active';
queryカラムに注目してみて。今実行中のクエリが見れるよ。もしクエリの実行がやたら長いなら、何か問題があるかも。
例2: トランザクション状態の分析
たまに接続がidle in transaction状態で「詰まる」ことがある。これはトランザクションが始まったまま終わってなくて、ロックの原因になったりするんだ。
SELECT pid, usename, query, state
FROM pg_stat_activity
WHERE state = 'idle in transaction';
どうやって直す? もし「詰まってる」トランザクションを見つけたら、こんなコマンドで終了させられる:
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE state = 'idle in transaction';
でも、これにハマりすぎる開発者もいるから注意。まずはチームに「このプロセスkillしていい?」って確認しよう。あ、ごめん、「kill」じゃなくて「接続を終了」だね。
テーブル利用状況のモニタリング: pg_stat_user_tablesビュー
pg_stat_activityが接続の監視なら、pg_stat_user_tablesはテーブルのパフォーマンスを教えてくれるやつ。どのテーブルがどれだけ読まれたり書かれたりしてるか、どのテーブルが一番使われてるか、パフォーマンスの問題がどこにあるかが分かるよ。
pg_stat_user_tablesでチェックしたい主なカラムはこんな感じ。relnameはテーブル名、seq_scanはシーケンシャルスキャン(全件走査)の回数、idx_scanはインデックスを使ったスキャンの回数。n_tup_insはテーブルに挿入された行数、n_tup_updは更新された行数、n_tup_delは削除された行数だよ。
例1: インデックス利用とシーケンシャルスキャンの比較
もしインデックスの利用回数(idx_scan)がほぼゼロなら、そのテーブルへのクエリは最適化できるかも。
SELECT relname, seq_scan, idx_scan
FROM pg_stat_user_tables
ORDER BY seq_scan DESC;
結果例:
例えば、ordersテーブルのseq_scanがめっちゃ多くて、idx_scanが100しかないのに、employeesテーブルはseq_scanが50でidx_scanが1000とかだったら、ordersテーブルにインデックス追加を考えた方がいいよ。これは明らかに最適化のサイン!
例2: テーブルごとの操作数分析
テーブルの「活発さ」を知りたいなら、挿入・更新・削除された行数をチェックしよう:
SELECT relname, n_tup_ins, n_tup_upd, n_tup_del
FROM pg_stat_user_tables
ORDER BY n_tup_ins DESC;
何が分かる? 挿入(n_tup_ins)や削除(n_tup_del)が多いテーブルは、DBの「ホットスポット」になってるかも。そういうテーブルはパフォーマンスに特に気をつけてね。
パフォーマンス分析の実践: pg_stat_activityとpg_stat_user_tablesのデータを組み合わせる
DBのパフォーマンスを分析するときは、この2つの情報を組み合わせるのがコツ。まずpg_stat_activityで長時間実行中のクエリを特定して、次にそのクエリが使ってるテーブルをpg_stat_user_tablesでチェック。もしseq_scanが多いテーブルでクエリが遅いなら、クエリの最適化やインデックス追加を検討しよう。
クエリ例:
WITH active_queries AS (
SELECT pid, query
FROM pg_stat_activity
WHERE state = 'active' AND query <> '<IDLE>'
)
SELECT a.pid, a.query, t.relname, t.seq_scan, t.idx_scan
FROM active_queries a
JOIN pg_stat_user_tables t ON a.query LIKE '%' || t.relname || '%';
GO TO FULL VERSION