일반적으로 다음과 같은 순서로 REDO 로그량이 많이 발생합니다:
VACUUM FULL > VACUUM > VACUUM FREEZE
[테스트 시나리오]
- 데이터 준비
- 100만 건의 초기 데이터 생성
- 각 VACUUM 테스트 전에 서로 다른 패턴으로 데이터 업데이트/삭제
- 각 VACUUM 유형별 특징
- VACUUM FULL: 테이블 전체 재작성으로 가장 많은 REDO 발생
- 일반 VACUUM: 삭제된 레코드 정리
- VACUUM FREEZE: 트랜잭션 ID 에이징 처리
- 측정 방법
- pg_current_wal_lsn() 함수로 WAL 위치 측정
- pg_wal_lsn_diff() 함수로 발생한 REDO 로그량 계산
- pg_size_pretty() 함수로 읽기 쉽게 포맷팅
- 결과 분석
- 각 VACUUM 유형별 REDO 로그 발생량 비교 제공
- VERBOSE 옵션으로 상세한 작업 내용 확인 가능
-- 1. 테스트 환경 설정
CREATE DATABASE vacuum_test;
\c vacuum_test
-- 테스트 테이블 생성
CREATE TABLE test_vacuum (
id SERIAL PRIMARY KEY,
data TEXT,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 초기 데이터 삽입 (100만건)
INSERT INTO test_vacuum (data)
SELECT md5(random()::text)
FROM generate_series(1, 1000000);
-- 2. VACUUM FULL 테스트
-- 데이터 업데이트로 부담 생성
UPDATE test_vacuum
SET data = md5(random()::text),
updated_at = CURRENT_TIMESTAMP
WHERE id % 2 = 0;
-- VACUUM FULL 실행 전 REDO 위치 기록
SELECT pg_current_wal_lsn() AS before_full_vacuum_lsn \gset
-- VACUUM FULL 실행
VACUUM FULL VERBOSE test_vacuum;
-- VACUUM FULL 실행 후 REDO 위치 기록 및 차이 계산
SELECT pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), :'before_full_vacuum_lsn')) AS full_vacuum_redo_size;
-- 3. 일반 VACUUM 테스트
-- 추가 데이터 업데이트
UPDATE test_vacuum
SET data = md5(random()::text),
updated_at = CURRENT_TIMESTAMP
WHERE id % 3 = 0;
-- 일부 데이터 삭제
DELETE FROM test_vacuum WHERE id % 5 = 0;
-- VACUUM 실행 전 REDO 위치 기록
SELECT pg_current_wal_lsn() AS before_vacuum_lsn \gset
-- VACUUM 실행
VACUUM VERBOSE test_vacuum;
-- VACUUM 실행 후 REDO 위치 기록 및 차이 계산
SELECT pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), :'before_vacuum_lsn')) AS vacuum_redo_size;
-- 4. VACUUM FREEZE 테스트
-- 오래된 트랜잭션 시뮬레이션을 위한 데이터 업데이트
UPDATE test_vacuum
SET data = md5(random()::text),
updated_at = CURRENT_TIMESTAMP
WHERE id % 4 = 0;
-- VACUUM FREEZE 실행 전 REDO 위치 기록
SELECT pg_current_wal_lsn() AS before_freeze_vacuum_lsn \gset
-- VACUUM FREEZE 실행
VACUUM FREEZE VERBOSE test_vacuum;
-- VACUUM FREEZE 실행 후 REDO 위치 기록 및 차이 계산
SELECT pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), :'before_freeze_vacuum_lsn')) AS freeze_vacuum_redo_size;
-- 5. 결과 비교를 위한 요약
SELECT
'VACUUM FULL' as vacuum_type,
pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), :'before_full_vacuum_lsn')) AS redo_size
UNION ALL
SELECT
'VACUUM' as vacuum_type,
pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), :'before_vacuum_lsn')) AS redo_size
UNION ALL
SELECT
'VACUUM FREEZE' as vacuum_type,
pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), :'before_freeze_vacuum_lsn')) AS redo_size
ORDER BY vacuum_type;
테스트 결과
VACUUM FULL > VACUUM > VACUUM FREEZE 확인이 되었음.
VACUUM FULL이 가장 많은 REDO 로그를 발생시키는 이유는? LIKE CTAS
- 테이블 전체를 새로운 물리적 파일로 재작성
- 모든 데이터 페이지를 새로 생성
- 인덱스도 전체 재구축
- 테이블의 모든 블록에 대한 변경사항을 WAL에 기록
- 기존 테이블 삭제 및 새 테이블 생성 작업도 로깅
-- VACUUM FULL: maintenance_work_mem 설정값 전체 사용
일반 VACUUM이 중간 정도의 REDO 로그를 발생시키는 이유는? 삭제된 데이터 공간 일부만 수정
- 삭제된 레코드의 공간만 재사용 가능하도록 마킹
- 인덱스 정리 작업 수행
- 일부 페이지만 수정하므로 FULL보다 적은 로그 발생
- 변경된 부분만 WAL에 기록
-- 일반 VACUUM: maintenance_work_mem의 일부만 사용
VACUUM FREEZE가 가장 적은 REDO 로그를 발생시키는 이유는? 메타데이터만 수정
- 주로 트랜잭션 ID 관련 메타데이터만 업데이트
- 물리적 데이터 이동이 거의 없음
- 페이지 내용 자체는 거의 변경되지 않음
-- VACUUM FREEZE: 최소한의 메모리만 사용
'Postgresql' 카테고리의 다른 글
쿼리성능 분석 툴 pg_stat_statements (0) | 2024.12.17 |
---|---|
PostgreSQL 15.8 시스템 변수 최적화 (0) | 2024.12.11 |
PostgreSQL architecture (Local Memory) (0) | 2024.11.13 |
[book] PostgreSQL 9.6 성능 이야기 - vacuum (0) | 2024.10.30 |
PostgreSQL architecture (shared Memory) (0) | 2024.10.22 |