vacuum 을 수행하는 명령은 몇가지가 있는데, 각각 기능이 조금 상이하다. 각 명령어마다 어느 작업을 수행하는지 알아보자.
- vacuum - vacuum analyze - autovacuum - vacuum full
VACUUM 작업의 역할
1. dead tuple 정리
VACUUM, VACUUM ANALYZE, VACUUM FULL 모두 dead tuple을 대상으로 공간을 회수한다. 회수된 공간은 테이블 내에서 재사용 가능해 진다.
2. 통계정보 수집
VACUUM 만 쓰면 통계정보는 수집하지 않고, VACUUM ANALYZE 를 써야 통계정보까지 새로 수집한다. 동시에 dead tuple을 정리한다. VACUUM FULL만 단독으로 쓰면 통계정보 수집은 하지 않습니다.
3. xid freeze
오래된 tuple의 XID를 frozen 특수 값으로 바꿔서, 트랜잭션 ID wraparound(40억 도달 시 심각한 장애 위험)를 방지 VACUUM, VACUUM ANALYZE, VACUUM FULL 모두 xid freeze 처리를 지원한다.
4. 안쓰는 공간 OS 반환
일반 VACUUM, VACUUM ANALYZE는 dead tuple이 차지하던 공간을 내부적으로만 재사용할 뿐, 실제로 운영체제(OS) 입장에서 파일은 줄지 않는다. VACUUM FULL은 dead tuple을 삭제한 뒤, 테이블을 새로 복사하여 불필요한 공간을 OS에 반환한다. 느리고 작업 중 락이 걸린다는 단점이 있다.
정리를 하면...
dead tuple 정리와 xid freeze 는 어느 vacuum 명령을 해도 처리된다.
필요성
VACUUM
VACUUM ANALYZE
autovacuum
VACUUM FULL
dead tuple 정리
O
O
O
O
통계정보 수집
X
O (락 발생)
O (락 적게)
X
xid freeze
O
O
O
O
안쓰는 공간 반환
X (재사용)
X (재사용)
X (재사용)
O (OS로 반환)
OS 로 공간반환이 필요하거나, 통계 수집이 필요할때만 필요한 vacuum 명령어를 사용해주면 된다.
# autovacuum 과 vacuum analyze 의 차이
autovacuum 은 특정 조건을 만족하면 자동으로 vacuum 작업이 돌게 된다. 그러나 이름과 다르게, (autovacuum 이면 vacuum 만 자동으로 할거 같지만..) 위의 표에서 보듯이 autovacuum 이 하는 작업은 vacuum analyze 와 동일하다.
- dead tuple 정리 - xid freeze - 통계 정보 수집
내부 작동 방식이 차이가 나면서 autovacuum 은 lock 을 적게 사용하여 운영중에도 사용이 가능하다.
동일구조 테이블을 2개 생성하여 각각에 vacuum full 과 pg_repack 을 하여 비교해보자
-- 1. 동일 구조의 두 테이블 생성 DROP TABLE IF EXISTS t_vacu; DROP TABLE IF EXISTS t_repk;
CREATE TABLE t_vacu ( id SERIAL PRIMARY KEY, data TEXT );
CREATE TABLE t_repk ( id SERIAL PRIMARY KEY, data TEXT );
-- 2. 동일 데이터 대량 삽입 (예: 10만 건) INSERT INTO t_vacu (data) SELECT md5(random()::text) FROM generate_series(1, 100000);
INSERT INTO t_repk (data) SELECT md5(random()::text) FROM generate_series(1, 100000);
-- 3. 초기 상태 확인 : 테이블 크기 및 dead tuple 비율 조회 SELECT relname, pg_size_pretty(pg_relation_size(relid)) AS table_size, n_live_tup, n_dead_tup, ROUND((n_dead_tup::numeric / (n_live_tup + n_dead_tup)) * 100, 2) AS dead_tuple_pct FROM pg_stat_user_tables WHERE relname IN ('t_vacu', 't_repk');
-- 4. 일부 데이터 삭제 (예: 30% 정도) DELETE FROM t_vacu WHERE id % 10 < 3; DELETE FROM t_repk WHERE id % 10 < 3;
-- 5. 삭제 후 상태 다시 확인 SELECT relname, pg_size_pretty(pg_relation_size(relid)) AS table_size, n_live_tup, n_dead_tup, ROUND((n_dead_tup::numeric / (n_live_tup + n_dead_tup)) * 100, 2) AS dead_tuple_pct FROM pg_stat_user_tables WHERE relname IN ('t_vacu', 't_repk');
-- 6. VACUUM FULL, pg_repack 적용 (t_vacu) VACUUM FULL t_vacu;
* 아래는 pg_repack 클라이언트에서 실행한다. export PATH=$PATH:/home/ubuntu/pg_repack-1.5.0/bin
-- 7. 적용 후 상태 재확인 SELECT relname, pg_size_pretty(pg_relation_size(relid)) AS table_size, n_live_tup, n_dead_tup, ROUND((n_dead_tup::numeric / (n_live_tup + n_dead_tup)) * 100, 2) AS dead_tuple_pct FROM pg_stat_user_tables WHERE relname IN ('t_vacu', 't_repk');