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 체크포인트가 수행되므로, 추가 작업 없이도 대상이 영구적으로 보존돼요.
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, andwal_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)
- Experimental Features - 그 자리의
VACUUM활성화 방법 - PRAGMAs -
auto_vacuum,journal_mode,query_only,wal_checkpoint - ATTACH DATABASE -
VACUUM INTO의 대상이 될 스키마 연결 - ANALYZE - vacuum 이후 쿼리 플래너 통계 갱신