pg_stat_statements 분석 (느린 쿼리 찾기)

브라우저 안에서만 처리됩니다. 입력한 내용과 선택한 파일은 서버로 전송되지 않습니다. 익명 방문 통계만 집계합니다.

진단 SQL

SELECT
  s.query AS query_text,
  s.calls AS calls,
  round(s.total_exec_time::numeric, 2) AS total_exec_time_ms,
  round(s.mean_exec_time::numeric, 2) AS mean_exec_time_ms,
  s.rows AS rows_total,
  s.shared_blks_hit AS shared_blks_hit,
  s.shared_blks_read AS shared_blks_read,
  i.stats_reset AS stats_reset
FROM pg_stat_statements AS s
CROSS JOIN pg_stat_statements_info AS i
ORDER BY s.total_exec_time DESC
LIMIT 50;

복사한 SQL 을 psql --csv -f-(권장 — 파싱이 가장 견고합니다)로 실행하거나, psql 안에서 그대로 실행한 기본 출력도 지원합니다. 출력 전체를 아래에 붙여넣으세요.

필요 권한/확장 — pg_stat_statements 확장 필요 — shared_preload_libraries 에 추가 후 서버 재시작 + CREATE EXTENSION pg_stat_statements. 자신이 실행하지 않은 쿼리문 조회는 슈퍼유저 또는 pg_read_all_stats 권한 필요. PostgreSQL 13 이상 필요(total_exec_time 컬럼 — 12 이하는 total_time 이라는 다른 이름이라 이 SQL 이 컬럼 없음 에러로 실패합니다).

통계는 stats_reset 이후 누적입니다(기간이 아님). psql --csv -f- 실행을 권장합니다 — 쿼리문 안의 개행·쉼표까지 안전하게 담깁니다.

사용법

  1. SQL 카드의 복사 버튼으로 진단 SQL(pg_stat_statements 조회)을 복사합니다.
  2. 복사한 SQL 을 psql 에서 그대로 실행합니다 — psql --csv -f- 를 권장하지만, 기본 실행 결과도 지원합니다.
  3. 출력 전체를 아래 textarea 에 붙여넣으면 총시간 비중·평균·호출·캐시 히트율로 분석됩니다.

자주 묻는 질문

붙여넣은 쿼리 통계가 서버로 전송되나요?

아니요. 붙여넣은 내용은 이 브라우저 안에서만 파싱·분석되고 어디로도 전송되지 않습니다.

pg_stat_statements 확장을 설치해야 하나요? 권한은요?

shared_preload_libraries 에 pg_stat_statements 를 추가하고 서버를 재시작한 뒤 CREATE EXTENSION pg_stat_statements 가 필요합니다. 자신이 실행하지 않은 다른 사용자의 쿼리문을 조회하려면 슈퍼유저 또는 pg_read_all_stats 권한이 있어야 합니다.

값이 예상보다 훨씬 큽니다 — 뭘 보고 있는 건가요?

pg_stat_statements 의 통계는 stats_reset 시각 이후 계속 누적된 값이지, 최근 1시간·하루 같은 기간 통계가 아닙니다. 특정 구간만 보고 싶다면 SELECT pg_stat_statements_reset(); 로 리셋한 뒤 그 구간이 지난 다음 다시 조회하세요.

느린 쿼리를 찾았는데 다음엔 뭘 봐야 하나요?

해당 쿼리 텍스트를 복사해 EXPLAIN ANALYZE 로 실행한 뒤, 그 결과를 실행계획 분석 도구에 붙여넣으면 어느 노드가 시간을 쓰는지 트리로 볼 수 있습니다.

캐시 히트율이 낮으면 무조건 문제인가요?

낮은 히트율의 기준은 워크로드마다 달라 이 도구는 값만 보여줍니다. 직접 판단해 주세요.

진단 SQL 을 실행하면 컬럼이 없다는 에러가 나요.

total_exec_time·mean_exec_time 컬럼은 PostgreSQL 13 부터 쓰는 이름입니다 — 12 이하에서는 같은 값이 total_time·mean_time 이라는 다른 이름으로 저장돼 있어 "column ... does not exist" 에러가 납니다. 12 이하 서버라면 이 SQL 의 total_exec_time/mean_exec_time 을 total_time/mean_time 으로 바꿔 실행한 뒤 결과를 붙여넣으세요(이 도구가 기대하는 컬럼명 자체가 total_exec_time_ms/mean_exec_time_ms 별칭이라 이름을 맞춰야 합니다).