pg_stat_statements는 PostgreSQL의 확장 모듈로, SQL 쿼리 실행 통계를 수집하고 조회할 수 있도록 합니다.
주요 기능
- 쿼리 성능 분석:
- 실행된 쿼리의 호출 횟수, 평균 실행 시간, 총 시간 등 다양한 성능 통계를 제공합니다.
- 리소스 사용 모니터링:
- CPU 사용량, I/O 횟수 등을 추적하여 리소스 소비가 많은 쿼리를 식별합니다.
- 튜닝 도구:
- 성능 저하를 유발하는 쿼리를 최적화하는 데 도움을 줍니다.
설치
CREATE EXTENSION pg_stat_statements;
shared_preload_libraries = 'pg_stat_statements' -- postgresql.conf 재시작 필요
위 처럼 db에서 활성화 해주면 되고 db마다 활성화가 필요하기 때문에
template1 에다 설치해놓고 새로운 DB를 생성 할때 마다 template1을 참조해서 생성한다면 신규DB에 pg_stat_statements extention이 설치 됩니다.
기존에 설치 되어 있는 DB에는 create extension pg_stat_statements; 명령으로 설치를 따로 해줘야 합니다.
확인
select * from public.pg_stat_statements
컬럼 | 설명 |
userid | 쿼리 실행 사용자ID, 어떤 쿼리를 어떤 사용자가 사용했는지 추적 가능 |
dbid | 쿼리 실행 데이터베이스 ID, 동일 인스턴스 에 여러 데이터베이스를 사용하는 경우, 데이터베이스 실행 추적 가능 |
queryid | 쿼리 텍스트의 해쉬 값, 동일 쿼리 식별 가능 (쿼리가 변형되어도 ID를 통해 유사쿼리 그룹화 가능) |
query | 실제 실행된 쿼리 텍스트 |
calls | 쿼리가 실행된 횟수 쿼리 호출 횟수로, 예상 수치보다 자주 호출되거나, 자주 호출되는데 실행시간이 길다면 확인 대상 |
total_time | 쿼리의 총 실행 시간 (ms), 쿼리가 총 소모한 시간이 특정 시점부터 급격히 증가하면 확인 대상 |
min_time | 쿼리 실행 최소 시간 (ms) |
max_time | 쿼리 실행 최대 시간 (ms) 쿼리 최대 실행시간이 특정 상황에서 비정상적으로 오래 시간이 걸린다면 확인 대상 |
mean_time | 쿼리 실행 평균 시간 (ms) 쿼리의 평균 실행시간이 특정 시점부터 급격히 증가하면 확인 대상 |
stddev_time | 쿼리 실행 표준편차 ( 실행 시간의 변동성 판단 가능, 변동성이 크다면 특정 상황에서 성능문제 발생할 수 있음 ) |
rows | 쿼리 실행 결과 행 수 |
shared_blks_read | 공유 메모리에서 블록이 히트된 횟수, 메모리에서 쿼리가 얼마나 효율적으로 데이터를 읽었는지 파악 가능 |
shared_blks_dirtied | 디스크에서 읽은 공유 블록의 수 (값이 높으면 디스크 I/O가 많이 발생) |
shard_blks_written | 쿼리 실행중 수정된 공유블록의 수, (데이터 변경이 얼마나 발생했는지 확인 가능) |
local_blks_hit local_blks_read local_blks_dirtied local_blks_written |
shared_ 헤더의 값들과 유사, 공유 메모리가 아닌 로컬 메모리에서의 지표 |
temp_blks_read | 쿼리 실행 중 임시 테이블에서 읽은 블록 수 (높으면 쿼리가 임시 테이블을 많이 사용중) |
temp_blks_written | 쿼리 실행 중 임시 테이블에 기록된 블록 수 (높다면 쿼리 최적화 필요) |
blk_read_time | 블록을 읽는데 총 걸린 시간 (ms) 쿼리가 I/O작업에서 얼마나 많은 시간을 소비했는지 확인 가능 |
blk_write_time | 블록을 쓰는데 걸린 총 시간 (ms) 데이터 쓰기 작업이 성능에 얼마나 영향을 미쳤는지 파악 가능 |
활용방안
/* 수행시간이 제일 긴 쿼리를 상위 50개만 조회 */
select a.userid
, b.usename
, a.dbid
, c.datname
, a.queryid
, substr(a.query, 1, 100) as query
, a.calls
, a.total_exec_time
, a.min_exec_time
, a.max_exec_time
, a.rows
from public.pg_stat_statements a
join pg_catalog.pg_user b on a.userid = b.usesysid
join pg_catalog.pg_stat_database c on a.dbid = c.datid
order by a.max_exec_time desc
limit 50
/*가장 자주 실행된 쿼리 확인*/
SELECT query, calls, total_time, mean_time, rows
FROM pg_stat_statements
ORDER BY calls DESC
LIMIT 5;
--calls 값이 지나치게 높으면 캐싱 또는 배치 처리와 같은 최적화 방법 고려.
/*가장 느린 쿼리 확인*/
SELECT query, calls, total_time, mean_time, rows
FROM pg_stat_statements
ORDER BY mean_time DESC
LIMIT 5;
--mean_time이 높은 쿼리는 인덱스 추가, 쿼리 리팩토링, 테이블 파티셔닝 등을 고려.
/*가장 많은 리소스를 소모한 쿼리 확인*/
SELECT query, calls, shared_blks_hit, shared_blks_read, shared_blks_written, total_time
FROM pg_stat_statements
ORDER BY shared_blks_read + shared_blks_written DESC
LIMIT 5;
--shared_blks_read가 높으면 디스크 I/O 부하를 줄이기 위해 인덱스 최적화, 캐싱 적용 검토.
--shared_blks_written이 높으면 체크포인트나 쓰기 빈도를 조정.
주의사항
- pg_stat_statements는 쿼리에 대한 추가 통계를 수집하기 때문에 성능에 약간의 오버헤드를 유발할 수 있다.
일반적으로 시스템 운영에 영향을 줄정도로 크지 않지만, 매우 트래픽이 많은 시스템은 주의가 필요하다. - 통계가 계속 축적되기 때문에 설정에 따라 디스크 사용량이 증가할 수 있다. pg_stat_statements_max (기본값 : 5000)을 적절히 조정하여 관리해야 한다.
- pg_stat_statements를 통해 실행되는 쿼리문 자체가 저장되기에 민감 데이터가 노출되지 않도록 관리해야 한다. (사용자 권한을 제한 권고)
- 누적된 집계 외에 특정 시점 이후의 성능을 분석하고 싶다면 통계 초기화해야 한다.
SELECT pg_stat_statements_reset();
참조
'Postgresql' 카테고리의 다른 글
Visibility Map(가시성 맵) (0) | 2024.12.17 |
---|---|
PostgreSQL 15.8 시스템 변수 최적화 (0) | 2024.12.11 |
VACUUM type 에 따른 redo 발생량 차이 (0) | 2024.11.13 |
PostgreSQL architecture (Local Memory) (0) | 2024.11.13 |
[book] PostgreSQL 9.6 성능 이야기 - vacuum (0) | 2024.10.30 |