最近 PostgreSQL で動いているシステムに携わるようになって、しばらく MySQL ばかり触っていたので、PostgreSQL の障害調査の時とかに四苦八苦するので、使えそうな SQL とかコマンドの類をメモとして書いておく。
現在実行中のクエリを確認する
pg_stat_activity
ビューに、PostgreSQLの各サーバープロセスのに関する情報を持っているので、これを参照する。
select * from pg_stat_activity where state != 'idle' order by query_start asc;
また、例えば実行に 30 秒以上かかっているクエリを参照する場合は以下のような感じになる。
select pid , client_addr , query_start , query from pg_stat_activity where state = 'active' and query_start < ( current_timestamp - interval '30' second ) and pid <> pg_backend_pid() order by query_start;
ロックの状態を確認する。ロック状態にあるものは pg_locks ビューにロックの情報が格納されているので、ここに格納されている pid と pg_stat_activity ビューにある pid を元に内部結合して、ロックされているプロセスの情報を参照する。
select locktype , pg_locks.pid , mode , relation::regclass , usename , application_name , client_addr , query_start , state_change , granted , state , query from pg_locks inner join pg_stat_activity on pg_locks.pid = pg_stat_activity.pid where pg_locks.pid <> pg_backend_pid();
各テーブルのサイズ等の情報を確認する
各テーブルのサイズを取得する。
SELECT pgn.nspname , relname , pg_size_pretty(relpages::bigint * 8 * 1024) AS size , CASE WHEN relkind = 't' THEN (SELECT pgd.relname FROM pg_class pgd WHERE pgd.reltoastrelid = pg.oid) WHEN nspname = 'pg_toast' AND relkind = 'i' THEN (SELECT pgt.relname FROM pg_class pgt WHERE SUBSTRING(pgt.relname FROM 10) = REPLACE(SUBSTRING(pg.relname FROM 10), '_index', '')) ELSE (SELECT pgc.relname FROM pg_class pgc WHERE pg.reltoastrelid = pgc.oid) END::varchar AS refrelname, CASE WHEN nspname = 'pg_toast' AND relkind = 'i' THEN (SELECT pgts.relname FROM pg_class pgts WHERE pgts.reltoastrelid = (SELECT pgt.oid FROM pg_class pgt WHERE SUBSTRING(pgt.relname FROM 10) = REPLACE(SUBSTRING(pg.relname FROM 10), '_index', ''))) END AS relidxrefrelname, relfilenode, relkind, reltuples::bigint, relpages FROM pg_class pg , pg_namespace pgn WHERE pg.relnamespace = pgn.oid AND pgn.nspname NOT IN ('information_schema', 'pg_catalog') ORDER BY relpages DESC;
VACUUM の情報を確認する
n_live_tup(有効な行数)とn_dead_tup(不要な行数)、それらの比率や最後に AutVacuum が実行されたタイミングを確認できる。
select relname , n_live_tup , n_dead_tup , round(n_dead_tup * 100 / nullif(n_live_tup + n_dead_tup, 0), 2) as dead_ratio , last_autovacuum from pg_stat_user_tables;
実行計画を取得する
実行計画を取得する。トランザクションを貼って実行するようにして、影響を少なくする。
begin; explain analyze ...; rollback;
キャッシュヒット率をみる
以下で取得可能。
select datname , blks_hit * 100.0 / (blks_read + blks_hit) AS cache_hit from pg_stat_database where datname = 'db_name_hogehoge';
実行中のクエリを停止する
以下で停止したいクエリの pid を取得する。
select * from pg_stat_activity;
取得した pid に対して以下を実行する。
SELECT pg_cancel_backend(pid);
上記でも停止しない場合は以下を実行する。
SELECT pg_terminate_backend(pid);
参考
- 28.2. 統計情報コレクタ
- 9.9.5. 遅延実行
- 稼動統計情報を活用しよう(2) | Let's POSTGRES
- 2018年度WG3活動報告書 性能トラブル調査編
- PostgreSQL エンタープライズ・コンソーシアム : 活動報告トップページ
- PostgreSQL Conference Europe Talks 2013 - PostgreSQL wiki
- pganalyze - Monitoring for Casual DBAs
- PostgreSQLでSQLチューニングや障害状況調査に使ったクエリ達まとめ - $shibayu36->blog;
- PostgreSQLで各テーブルの総サイズと平均サイズを知る - Qiita