본문 바로가기
WIKI 기술 지식 베이스

VACUUM

원문 보기 위키 갱신

데이터베이스 파일을 다시 만들어 쓸모없는 공간을 회수하고 저장소를 조각모음하는 VACUUM 문이에요. VACUUM은 현재 데이터베이스를 그 자리에서 다시 만들고, VACUUM INTO는 원본을 건드리지 않으면서 압축된 사본을 새 파일로 기록해요.

출처: 문서

본문

VACUUM 문은 데이터베이스 파일을 다시 만들어 쓰지 않는 공간을 회수하고, 테이블과 인덱스의 조각을 모으고, 파일 크기를 줄여요. 두 가지 형태를 지원하는데, VACUUM은 현재 데이터베이스를 그 자리에서(in-place) 다시 만들고 VACUUM INTO는 원본을 수정하지 않고 압축된 사본을 새 파일에 기록해요.

Syntax

VACUUM [schema-name];
VACUUM [schema-name] INTO filename;
Parameter Description
schema-name VACUUM을 실행할 데이터베이스예요. 그 자리에서 실행하는 VACUUM은 main만 지원해요. VACUUM INTO는 연결된(attached) 어떤 스키마도 받아들이고, temp는 아무 작업도 하지 않으며 파일도 만들지 않아요. 기본값은 main이에요.
filename VACUUM INTO의 대상 파일 경로를 담은 문자열 리터럴이에요. 바인드 파라미터는 받지 않아요.

Common Requirements

이 규칙들은 VACUUM과 VACUUM INTO 모두에 적용돼요.

  • 연결이 autocommit 모드여야 해요. 어떤 형태든 명시적인 BEGIN 트랜잭션 안에서는 실행할 수 없어요.
  • 같은 연결에서 다른 문장이 활성 상태여서는 안 돼요.
  • 연결이 query_only 모드여서는 안 돼요.
  • 원본 데이터베이스가 auto_vacuum = incremental이어서는 안 돼요. 증분(incremental) 자동 vacuum은 지원하지 않아요.

VACUUM

그 자리에서 실행하는 `VACUUM`은 실험적 기능이라 [사용 전에 활성화](/sql-reference/experimental-features)해야 해요. `VACUUM INTO`는 플래그가 필요 없고 항상 사용할 수 있어요.

그 자리에서 실행하는 VACUUM은 압축된 이미지를 내부 임시 데이터베이스에 기록한 다음 그 페이지들을 원본 파일 위로 복사하는 방식으로 main 데이터베이스를 다시 만들어요. 완료되면 쓰지 않는 페이지가 해제되고 저장소 기반 객체가 모두 다시 만들어져요.

Effect

  • 삭제된 행과 제거된 객체가 남긴 쓰지 않는 페이지가 제거되어 파일이 줄어들어요.
  • 저장소 기반 테이블이 모두 다시 만들어지고 행이 다시 삽입되면서, 관련 인덱스도 다시 만들어져요.
  • AUTOINCREMENT 컬럼이 사용하는 sqlite_sequence 카운터는 그대로 유지돼요.
  • 스키마 쿠키가 올라가서 다른 연결들이 다음 접근 시 캐시해 둔 스키마를 다시 읽어 들여요.
  • 페이지 크기, 예약 공간, 텍스트 인코딩, user version, application ID는 그대로 유지돼요.

Requirements

공통 요건에 더해 다음 조건이 필요해요.

  • 데이터베이스가 WAL 저널 모드로 열려 있어야 해요.
  • 데이터베이스가 in-memory여서는 안 돼요.
  • 데이터베이스가 읽기 전용이어서는 안 돼요.
  • main 데이터베이스만 지원해요. 연결된 스키마를 그 자리에서 vacuum하는 건 아직 지원하지 않아요.
  • 다른 프로세스가 multi-process WAL을 잡고 있으면 안 돼요.

MVCC Databases

데이터베이스가 MVCC(PRAGMA journal_mode = mvcc)를 사용하면 그 자리에서의 VACUUM에 추가 규칙이 적용돼요.

  • 모든 MVCC 변경이 먼저 체크포인트되어야 해요. MVCC 로그에 체크포인트되지 않은 변경이 남아 있으면 VACUUM은 오류를 돌려줘요. 먼저 PRAGMA wal_checkpoint(TRUNCATE)를 실행하세요.
  • 어떤 연결에서도 다른 MVCC 트랜잭션이 활성 상태여서는 안 돼요. 발견되면 VACUUM은 busy 오류를 돌려줘요.
  • 작업이 진행되는 동안 다시 만든 스키마와 로그를 원자적으로 맞추기 위해 MVCC 서브시스템이 일시 중지돼요.

VACUUM INTO

VACUUM INTO는 주어진 경로에 데이터베이스의 압축된 사본을 만들고 원본 데이터베이스는 그대로 둬요. 대상은 독립적으로 열 수 있는 완전한 자기완결적(self-contained) 데이터베이스 파일이에요.

Effect

  • filename 경로에 새 데이터베이스 파일이 만들어지고, 원본의 모든 사용자 테이블, 인덱스, 트리거, 뷰, 가상 테이블 내용이 담겨요.
  • 인덱스, 트리거, 뷰는 데이터 복사가 끝난 후에 다시 만들어져서, 복사 중에는 트리거가 발동하지 않아요.
  • 커스텀 인덱스 메서드(예: FTS, 벡터)는 복사된 데이터를 기반으로 자기 구조를 다시 만들어요.
  • AUTOINCREMENT 컬럼이 사용하는 sqlite_sequence 카운터는 유지돼요.
  • 페이지 크기, 예약 공간, 텍스트 인코딩, user version, application ID는 원본에서 복사돼요.
  • 원본이 MVCC를 사용하면 대상은 MVCC가 켜진 상태로 만들어지지만 상태는 새것이에요. 원본의 MVCC 메타데이터 테이블은 복사되지 않아요.
  • 문장이 돌아오기 전에 파일이 완전히 동기화(sync)되고 TRUNCATE 체크포인트가 수행되므로, 추가 작업 없이도 대상이 영구적으로 보존돼요.
`VACUUM INTO`는 암호화를 대상 파일로 이어 주지 않아요. 원본이 암호화되어 있어도 압축된 사본은 일반적인 암호화되지 않은 데이터베이스 파일로 기록되어 키 없이 열 수 있어요. 예약 헤더 바이트는 그대로 복사되기 때문에 대상의 페이지 레이아웃은 원본과 같아요.

Requirements

공통 요건에 더해 다음 조건이 필요해요.

  • 대상 파일이 이미 존재해서는 안 돼요. 덮어쓰고 싶다면 먼저 삭제하거나 옮기세요.
  • 경로는 SQL 문장 안에서 문자열 리터럴로 제공해야 해요.
  • VACUUM temp INTO filename은 아무 작업도 하지 않고 파일도 만들지 않아요. SQLite의 동작과 동일해요.

VACUUM INTO는 복사가 진행되는 동안 암시적 읽기 트랜잭션을 시작해 원본의 일관된 뷰를 확보해요. 그래서 복사 중에 다른 연결이 원본에 쓰더라도 대상은 항상 원본의 단일 스냅샷을 반영해요.

Examples

Rebuild the Main Database

-- 현재 데이터베이스의 공간을 회수하고 조각모음해요
VACUUM;

Write a Compacted Copy to a New File

VACUUM INTO 'backup.db';

원본 데이터베이스는 그대로예요. backup.db는 독립적인 데이터베이스로 열 수 있어요.

tursodb backup.db

Vacuum an Attached Database Into a New File

ATTACH DATABASE 'archive.db' AS archive;

-- archive 스키마의 압축된 사본을 새 파일로 기록해요
VACUUM archive INTO 'archive-compact.db';

Use VACUUM INTO for a Backup Snapshot

VACUUM INTO는 일관된 스냅샷에서 복사하기 때문에, 활성 데이터베이스의 특정 시점(point-in-time) 백업을 담는 간단한 방법이에요.

VACUUM INTO '/var/backups/app-2026-04-23.db';

Restore Performance After Heavy Churn

대량 삭제나 오래 이어진 워크로드로 인덱스가 조각화됐다면, VACUUM이 인덱스를 다시 만들어 주어 스캔 속도가 좋아지는 경우가 많아요.

DELETE FROM events WHERE created_at < '2025-01-01';
VACUUM;

Errors

Error Cause
VACUUM is an experimental feature. Enable with --experimental-vacuum flag 실험적 플래그 없이 릴리스 빌드에서 그 자리의 VACUUM을 실행했어요.
VACUUM is only supported for the main database; schema '<name>' is not supported yet main이 아닌 스키마로 그 자리의 VACUUM schema-name을 실행했어요.
Cannot execute VACUUM in query_only mode PRAGMA query_only가 설정된 연결에서 VACUUM이나 VACUUM INTO를 실행했어요.
cannot VACUUM from within a transaction / cannot VACUUM INTO from within a transaction 명시적인 BEGIN 안에서 실행했어요.
cannot VACUUM - SQL statements in progress 같은 연결에서 다른 문장이 아직 활성 상태예요.
Incremental auto-vacuum is not supported 원본 데이터베이스가 auto_vacuum = incremental이에요. VACUUM과 VACUUM INTO 모두에 적용돼요.
VACUUM requires a WAL-mode database WAL이 아닌 데이터베이스에서 그 자리의 VACUUM을 실행했어요.
cannot VACUUM an in-memory database in-memory 데이터베이스에서 그 자리의 VACUUM을 실행했어요.
ReadOnly 읽기 전용 데이터베이스에서 그 자리의 VACUUM을 실행했어요.
cannot VACUUM while experimental multiprocess WAL is active in another process 다른 프로세스가 multi-process WAL을 잡고 있는 동안 그 자리의 VACUUM을 실행했어요.
cannot VACUUM an MVCC database with uncheckpointed changes; run PRAGMA wal_checkpoint(TRUNCATE) first 로그에 미처리 항목이 남은 MVCC 데이터베이스에서 그 자리의 VACUUM을 실행했어요.
output file already exists: <path> VACUUM INTO의 대상 파일이 이미 존재해요.
VACUUM INTO path cannot be empty VACUUM INTO ''를 사용했어요.
VACUUM INTO requires a string literal path 대상으로 리터럴이 아닌 표현식(예: 바인드 파라미터)을 사용했어요.
no such database: <name> VACUUM <schema> INTO가 알 수 없는 스키마를 참조했어요.

See Also

  • Experimental Features for enabling in-place VACUUM
  • PRAGMAs for auto_vacuum, journal_mode, query_only, and wal_checkpoint
  • ATTACH DATABASE for attaching a schema that can be targeted by VACUUM INTO
  • ANALYZE for refreshing query planner statistics after a vacuum

더 알아보기 (Learn more)