Skip to Content
Infra & DevOpsPostgreSQL 테이블별 디스크 사용량 조회
☁️ Infra & DevOps2018년 10월 22일

PostgreSQL 테이블별 디스크 사용량 조회

#postgres#sql#database#performance#dba

PostgreSQL에서 어느 테이블이 공간을 많이 사용하는지 확인할 때 참고하던 쿼리입니다. 원래 메모는 pg_class와 pg_namespace를 조회해 전체 크기가 큰 순서대로 20개를 보는 방식이었습니다.

테이블별 전체 크기

다음은 스키마 이름을 추가하고 일반 테이블로 대상을 제한한 쿼리입니다. 현재 접속한 데이터베이스 안의 테이블을 조회합니다.

sql
SELECT n.nspname AS schema_name, c.relname AS table_name, pg_size_pretty(pg_total_relation_size(c.oid)) AS total_size, pg_size_pretty(pg_table_size(c.oid)) AS table_size, pg_size_pretty(pg_indexes_size(c.oid)) AS indexes_size, c.reltuples::numeric AS estimated_rows FROM pg_class AS c JOIN pg_namespace AS n ON n.oid = c.relnamespace WHERE c.relkind = 'r' AND n.nspname NOT IN ('pg_catalog', 'information_schema') AND n.nspname !~ '^pg_toast' ORDER BY pg_total_relation_size(c.oid) DESC LIMIT 20;

크기는 숫자 값으로 정렬하고, 출력할 때만 pg_size_pretty로 단위를 바꿉니다. 단위가 붙은 문자열을 정렬 기준으로 쓰면 크기 순서와 달라질 수 있습니다.

용량 함수의 범위

함수포함하는 범위
pg_relation_size기본적으로 해당 relation의 main fork
pg_table_size테이블의 TOAST와 보조 저장 영역 포함, 인덱스 제외
pg_indexes_size테이블에 연결된 인덱스
pg_total_relation_size테이블과 인덱스·TOAST를 포함한 전체

pg_relation_size를 테이블 전체 크기로 해석하면 TOAST나 보조 저장 영역을 놓칠 수 있습니다. 전체 크기는 pg_table_size와 pg_indexes_size의 합으로 볼 수 있습니다.

위 쿼리의 relkind = 'r'에는 일반 테이블과 개별 파티션이 포함됩니다. 파티션 부모와 모든 자식의 합계를 한 행으로 보여 주는 쿼리는 아니므로, 파티션 테이블은 자식까지 묶어 별도로 집계해야 합니다.

추정 행 수 해석

reltuples는 COUNT(*) 결과가 아니라 통계 갱신 과정에서 얻은 추정치입니다. 최근 데이터 변경이 아직 반영되지 않았거나, 통계가 준비되지 않은 관계에서는 값의 의미를 확인해야 합니다.

용량이 큰 테이블을 찾는 데는 유용하지만, 이 값만으로 정확한 데이터 건수나 조회 속도를 보장할 수는 없습니다.

용량 확인 이후의 판단

테이블이 크다는 이유만으로 VACUUM이나 인덱스 삭제를 바로 결정하지는 않습니다. 보관할 데이터인지, 재사용 가능한 빈 공간인지, 인덱스가 필요한지부터 구분해야 합니다.

일반 VACUUM은 죽은 행의 공간을 다시 사용할 수 있도록 정리하지만, 보통 그 공간을 운영체제에 반환하지는 않습니다. VACUUM FULL은 테이블을 다시 쓰며 강한 잠금과 추가 공간이 필요합니다. 통계의 dead tuple 비율 하나를 모든 테이블의 실행 기준으로 삼기 어렵습니다.

참고 자료

Last updated on