Thu, 12 Jan 2023 15:59:30 +0900

테이블 크기 알기

PostgreSQL은 각 객체가 OS 저장 공간을 얼마나 사용하는지 확인할 때는 함수를 사용해야한다. 데이터베이스 정보를 보여주는 테이블이나, 뷰를 조회해서 그 값을 찾는게 아니라, pg_*_size() 함수를 사용해서 각 객체들의 크기를 확인한다.

이 함수가 호출 될 때, 이 함수는 내부적으로 그 객체에 해당하는 OS 파일시스템의 파일 크기를 구한다. - 데이터베이스나 테이블스페이스라면, 해당 디렉터리 안에 있는 모든 파일의 크기 총 합을 알려준다.

여기서 기억해야 할 것은 그 함수의 호출 자체가 해당 객체를 access share 모드로 잠근다는 것이다.

즉, 이 모드 잠금을 할 수 없는 상황 - 먼저 다른 쪽에서 access exclusive 모드로 잠군 상황 - 이라면 기다리게 된다(!).

크기 조회 함수들

각 객체의 크기를 조회하는 함수는

https://postgresql.kr/docs/current/functions-admin.html#FUNCTIONS-ADMIN-DBOBJECT

문서에서 소개하고 있다.

이 글에서 이것을 다시 정리하면,

(여기서 소개하고 있는 쿼리는 언제든지 바로 그 결과를 확인할 수 있다고 믿으면 안된다. 앞에서 이야기했듯이 이 함수가 호출되는 대상 객체가 잠겨 있으면 쿼리 자체가 대기 상태가 된다.)

select datname, pg_database_size(oid) from pg_database

해당 데이터베이스 디렉터리($PGDATA/base/숫자) 이하 있는 모든 파일 크기의 총합

즉, 그 디렉터리를 대상으로 일어나는 중간 과정의 모든 임시 파일들도 그 총합에 포함된다 (concurrently 옵션을 사용해서 만들고 있는 임시 인덱스들의 크기도 포함된다)

select spcname, pg_tablespace_size(oid) from pg_tablespace

설명 생략

select oid::regclass, relkind, pg_indexes_size(oid) from pg_class where relkind in ('r', 'm', 't')

이 인덱스 크기를 구하는 함수의 인자는 인덱스가 아니라, 그 인덱스를 사용하는 객체다.

그 객체에 딸린 모든 인덱스의 총합이다.

각 개별 인덱스의 크기를 살펴보려면, 아래 pg_relation_size() 함수를 이용한다.

select oid::regclass, relkind, pg_relation_size(oid) from pg_class where relkind not in ('S', 'v', 'c', 'f','p','I')

여기서 재미난 것이 숨어 있는데, 이 함수는 입력 인자로 하나만 쓰면 그 객체 그 자체의 크기를 반환하고, 두번째 입력인자로 'main', 'fsm', 'vm', 'init' 중 하나를 지정하면 그에 맞는 크기를 반환한다.

main: 그 객체 자체(토스트 테이블 제외)

fsm: 테이블, 토스트, 구체화된 뷰인 경우 그 객체의 빈터 지도 파일 크기

vm: 테이블, 토스트, 구체화된 뷰인 경우 그 객체의 실자료 지도 파일 크기

init: unlogged 옵션을 사용하는 테이블의 init 파일 크기 (https://postgresql.kr/docs/current/storage-init.html 참조)

이렇기 때문에, 이 pg_relation_size() 함수는 정확한 이해 없이 사용하게 되면 의도하지 않게 부정확한 크기를 구하게 된다.

테이블만을 고려대상으로 한다면, 아래에서 소개하는 pg_table_size(), pg_total_relation_size() 함수를 사용하는 것이 더 간편하다.

select oid::regclass, relkind, pg_table_size(oid) from pg_class where relkind in ('r', 'm')

인덱스를 제외한 테이블에 관계된 모든 파일의 총합(main + fsm + vm + init + toast의 그것들도 함께)

즉, 저수준으로 pg_table_size 함수를 구현한다면, pg_relation_size 함수가 여덟번 호출한 결과의 총합이다.

select oid::regclass, relkind, pg_total_relation_size(oid) from pg_class where relkind in ('r', 'm')

대망의 데이터베이스 관리자가 관심 있는 용량 관리용으로 제일 많이 사용하는 함수다 - 이 테이블을 지우면 얼마의 공간을 확보할 수 있어요? 질문의 답을 찾는 함수다.

pg_table_size() + pg_indexes_size() 값이다.

아쉽게도 해당 스키마 소속 모든 객체의 총합을 구하는 함수는 아직 없다.

지금까지 설명을 기반으로 잘 만들어서 써봅시다. 숙제