Postgresql

VACUUM type 에 따른 redo 발생량 차이

dbavayne 2024. 11. 13. 17:04

 

일반적으로 다음과 같은 순서로 REDO 로그량이 많이 발생합니다:

VACUUM FULL > VACUUM > VACUUM FREEZE

 

[테스트 시나리오]

  1. 데이터 준비
    • 100만 건의 초기 데이터 생성
    • 각 VACUUM 테스트 전에 서로 다른 패턴으로 데이터 업데이트/삭제
  2. 각 VACUUM 유형별 특징
    • VACUUM FULL: 테이블 전체 재작성으로 가장 많은 REDO 발생
    • 일반 VACUUM: 삭제된 레코드 정리
    • VACUUM FREEZE: 트랜잭션 ID 에이징 처리
  3. 측정 방법
    • pg_current_wal_lsn() 함수로 WAL 위치 측정
    • pg_wal_lsn_diff() 함수로 발생한 REDO 로그량 계산
    • pg_size_pretty() 함수로 읽기 쉽게 포맷팅
  4. 결과 분석
    • 각 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: 최소한의 메모리만 사용