PostgreSQL 監視ガイド
このドキュメントでは、PostgreSQLの監視方法とアラート設計を解説します。
目次
1. 監視の概要
1.1 監視の目的
┌──────────────────────────────────────────────────────────────┐
│ 監視の目的 │
├──────────────────────────────────────────────────────────────┤
│ │
│ 【可用性監視】 │
│ - PostgreSQLプロセスが稼働しているか │
│ - 接続を受け付けているか │
│ - レプリケーションが正常か │
│ │
│ 【パフォーマンス監視】 │
│ - クエリの応答時間 │
│ - スロークエリの発生 │
│ - ロック競合 │
│ │
│ 【リソース監視】 │
│ - ディスク使用量 │
│ - 接続数 │
│ - メモリ使用状況 │
│ │
│ 【キャパシティプランニング】 │
│ - データ増加傾向 │
│ - トランザクション数の推移 │
│ - リソース使用率のトレンド │
│ │
└──────────────────────────────────────────────────────────────┘
1.2 監視の設定
# postgresql.conf
# 統計情報収集を有効化
track_activities = on # pg_stat_activity
track_counts = on # pg_stat_*_tables, pg_stat_*_indexes
track_io_timing = on # I/O時間計測 (若干のオーバーヘッド)
track_wal_io_timing = on # WAL I/O時間計測
track_functions = all # 関数の統計 (none, pl, all)
# 統計情報の更新頻度
stats_fetch_consistency = cache # none, cache, snapshot
2. 統計情報ビュー (pg_stat_*)
2.1 主要な統計情報ビュー
┌──────────────────────────────────────────────────────────────┐
│ 主要な統計情報ビュー │
├──────────────────────────────────────────────────────────────┤
│ │
│ 【アクティビティ】 │
│ pg_stat_activity : 現在の接続とクエリ │
│ pg_stat_progress_* : 長時間操作の進捗 │
│ │
│ 【データベース】 │
│ pg_stat_database : データベース全体の統計 │
│ pg_stat_database_conflicts : スタンバイでの競合 │
│ │
│ 【テーブル/インデックス】 │
│ pg_stat_user_tables : テーブルの統計 │
│ pg_stat_user_indexes : インデックスの統計 │
│ pg_statio_user_tables : テーブルのI/O統計 │
│ pg_statio_user_indexes: インデックスのI/O統計 │
│ │
│ 【バックグラウンドプロセス】 │
│ pg_stat_bgwriter : バックグラウンドライター │
│ pg_stat_wal : WAL統計 │
│ pg_stat_archiver : アーカイバ │
│ │
│ 【レプリケーション】 │
│ pg_stat_replication : レプリケーション状態 │
│ pg_stat_wal_receiver : WALレシーバー (スタンバイ) │
│ pg_replication_slots : レプリケーションスロット │
│ │
└──────────────────────────────────────────────────────────────┘
2.2 pg_stat_activity
-- 現在のアクティブセッション
SELECT
pid,
usename,
datname,
client_addr,
state,
wait_event_type,
wait_event,
query_start,
now() - query_start AS query_duration,
LEFT(query, 100) AS query
FROM pg_stat_activity
WHERE state != 'idle'
ORDER BY query_start;
-- 状態別の接続数
SELECT
state,
count(*) AS count
FROM pg_stat_activity
GROUP BY state;
-- 長時間実行中のクエリ
SELECT
pid,
usename,
datname,
now() - query_start AS duration,
state,
query
FROM pg_stat_activity
WHERE state = 'active'
AND now() - query_start > interval '1 minute'
ORDER BY query_start;
-- ロック待ちのセッション
SELECT
pid,
usename,
wait_event_type,
wait_event,
query
FROM pg_stat_activity
WHERE wait_event_type = 'Lock';
2.3 pg_stat_database
-- データベース統計
SELECT
datname,
numbackends AS connections,
xact_commit AS commits,
xact_rollback AS rollbacks,
blks_read,
blks_hit,
ROUND(100.0 * blks_hit / NULLIF(blks_hit + blks_read, 0), 2) AS cache_hit_ratio,
tup_returned,
tup_fetched,
tup_inserted,
tup_updated,
tup_deleted,
conflicts,
deadlocks,
temp_files,
pg_size_pretty(temp_bytes) AS temp_bytes,
stats_reset
FROM pg_stat_database
WHERE datname NOT LIKE 'template%';
-- トランザクション数 (コミット + ロールバック)
SELECT
datname,
xact_commit + xact_rollback AS total_transactions,
xact_commit,
xact_rollback,
ROUND(100.0 * xact_rollback / NULLIF(xact_commit + xact_rollback, 0), 2) AS rollback_ratio
FROM pg_stat_database
WHERE datname = current_database();
2.4 pg_stat_user_tables
-- テーブル統計
SELECT
schemaname,
relname,
seq_scan,
seq_tup_read,
idx_scan,
idx_tup_fetch,
n_tup_ins,
n_tup_upd,
n_tup_del,
n_live_tup,
n_dead_tup,
ROUND(100.0 * n_dead_tup / NULLIF(n_live_tup + n_dead_tup, 0), 2) AS dead_tuple_ratio,
last_vacuum,
last_autovacuum,
last_analyze,
last_autoanalyze
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 20;
-- シーケンシャルスキャンが多いテーブル (インデックス追加の候補)
SELECT
schemaname,
relname,
seq_scan,
idx_scan,
CASE WHEN idx_scan > 0 THEN
ROUND(seq_scan::numeric / idx_scan, 2)
ELSE
seq_scan
END AS seq_to_idx_ratio,
pg_size_pretty(pg_relation_size(schemaname || '.' || relname)) AS size
FROM pg_stat_user_tables
WHERE seq_scan > 100
ORDER BY seq_scan DESC
LIMIT 20;
-- 最近VACUUMされていないテーブル
SELECT
schemaname,
relname,
n_dead_tup,
last_vacuum,
last_autovacuum,
GREATEST(last_vacuum, last_autovacuum) AS last_vacuumed
FROM pg_stat_user_tables
WHERE n_dead_tup > 1000
ORDER BY GREATEST(last_vacuum, last_autovacuum) NULLS FIRST
LIMIT 20;
2.5 pg_stat_user_indexes
-- インデックス統計
SELECT
schemaname,
relname,
indexrelname,
idx_scan,
idx_tup_read,
idx_tup_fetch,
pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_stat_user_indexes
ORDER BY idx_scan DESC
LIMIT 20;
-- 使用されていないインデックス (削除候補)
SELECT
schemaname,
relname,
indexrelname,
idx_scan,
pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_stat_user_indexes
WHERE idx_scan = 0
AND indexrelname NOT LIKE '%_pkey' -- 主キーは除外
ORDER BY pg_relation_size(indexrelid) DESC;
2.6 pg_statio_user_tables
-- テーブルのI/O統計
SELECT
schemaname,
relname,
heap_blks_read,
heap_blks_hit,
ROUND(100.0 * heap_blks_hit / NULLIF(heap_blks_hit + heap_blks_read, 0), 2) AS heap_hit_ratio,
idx_blks_read,
idx_blks_hit,
ROUND(100.0 * idx_blks_hit / NULLIF(idx_blks_hit + idx_blks_read, 0), 2) AS idx_hit_ratio,
toast_blks_read,
toast_blks_hit
FROM pg_statio_user_tables
ORDER BY heap_blks_read DESC
LIMIT 20;
3. パフォーマンス監視
3.1 キャッシュヒット率
-- データベース全体のキャッシュヒット率
SELECT
datname,
blks_read,
blks_hit,
ROUND(100.0 * blks_hit / NULLIF(blks_hit + blks_read, 0), 2) AS cache_hit_ratio
FROM pg_stat_database
WHERE datname = current_database();
-- 目安:
-- 99% 以上: 良好
-- 95-99%: 許容範囲
-- 95% 未満: shared_buffers の増加を検討
-- テーブル別のキャッシュヒット率
SELECT
schemaname,
relname,
heap_blks_read + idx_blks_read AS total_reads,
heap_blks_hit + idx_blks_hit AS total_hits,
ROUND(100.0 * (heap_blks_hit + idx_blks_hit) /
NULLIF(heap_blks_hit + idx_blks_hit + heap_blks_read + idx_blks_read, 0), 2) AS hit_ratio
FROM pg_statio_user_tables
WHERE heap_blks_read + idx_blks_read > 0
ORDER BY total_reads DESC
LIMIT 20;