VACUUM

VACUUM

VACUUM 명령은 데이터베이스 파일을 재구성하여 사용하지 않는 공간을 회수하고 파일 조각화를 줄입니다. 이 페이지에서는 VACUUM의 구문과 동작 방식, 그리고 사용 시 알아야 할 제약 사항에 대해 설명합니다.

출처: 문서

본문

1. 구문

vacuum-stmt:

VACUUM schema-name INTO filename

(schema-nameINTO filename 절은 선택 사항이에요.)

2. 설명

VACUUM 명령은 데이터베이스 파일을 재구축해서 최소한의 디스크 공간으로 다시 압축해요. 애플리케이션이 이 작업을 수행하는 이유는 여러 가지가 있어요:

  • SQLite가 "auto_vacuum=FULL" 모드로 실행 중이 아닌 경우, 데이터베이스 파일에서 많은 양의 데이터를 삭제하면 빈 공간, 즉 "여유" 데이터베이스 페이지가 남아요. 이는 데이터베이스 파일이 엄밀히 필요한 것보다 커질 수 있음을 의미해요. VACUUM을 실행해 데이터베이스를 재구축하면 이 공간을 회수하고 데이터베이스 파일의 크기를 줄일 수 있어요.

  • 삽입(INSERT), 갱신(UPDATE), 삭제(DELETE)가 빈번하면 데이터베이스 파일이 단편화될 수 있어요. 즉, 단일 테이블이나 인덱스의 데이터가 데이터베이스 파일 곳곳에 흩어지게 돼요. VACUUM을 실행하면 각 테이블과 인덱스가 데이터베이스 파일 내에서 대부분 연속적으로 저장되도록 보장해요. 경우에 따라 VACUUM은 부분적으로만 채워진 페이지 수를 줄여 데이터베이스 파일의 크기를 더 줄일 수도 있어요.

  • SQLite 데이터베이스에서 콘텐츠를 삭제하면 콘텐츠가 실제로 지워지는 경우는 드물고, 콘텐츠를 보관하던 공간이 재사용 가능한 것으로 표시돼요. 이로 인해 해커나 포렌식 분석으로 삭제된 콘텐츠를 복구할 수 있어요. VACUUM을 실행하면 데이터베이스에서 삭제된 콘텐츠의 모든 흔적을 정리해서 공격자가 삭제된 콘텐츠를 복구하지 못하게 해요. 이런 방식의 VACUUM 사용은 PRAGMA secure_delete=ON을 설정하는 대안이에요.

  • 일반적으로 데이터베이스의 page_size와 auto_vacuum 지원 여부는 데이터베이스 파일이 실제로 생성되기 전에 구성해야 해요. 하지만 WAL(write-ahead log) 모드가 아닐 때는 page_size 프래그마 및/또는 auto_vacuum 프래그마를 사용한 다음 즉시 데이터베이스에 VACUUM을 실행해서 기존 데이터베이스의 page_size 및/또는 auto_vacuum 속성을 변경할 수 있어요. WAL 모드에서는 VACUUM으로 auto_vacuum 지원 속성만 변경할 수 있어요.

기본적으로 VACUUM은 메인 데이터베이스에서 작동해요. VACUUM 문에 적절한 schema-name을 추가하면 attached 데이터베이스도 vacuum할 수 있어요.

호환성 경고: attached 데이터베이스에 vacuum을 실행하는 기능은 버전 3.15.0(2016-10-14)에서 추가되었어요. 그 이전에는 VACUUM 문에 추가된 schema-name이 조용히 무시되고 "main" 스키마가 vacuum 처리되었어요.

2.1. INTO 절이 포함된 VACUUM

INTO 절이 포함되면 원본 데이터베이스 파일은 변경되지 않고, INTO 절의 인자로 이름이 지정된 파일에 새 데이터베이스가 생성돼요. 인자는 텍스트 리터럴 같은 스칼라 표현식이에요. 새 데이터베이스에는 원본 데이터베이스와 동일한 논리적 콘텐츠가 완전히 vacuum된 상태로 담겨요.

INTO 절이 포함된 VACUUM 명령은 실행 중인 데이터베이스의 백업 복사본을 만들 때 백업 API의 대안이에요. VACUUM INTO를 사용하면 결과 백업 데이터베이스의 크기가 최소화되어 파일 시스템 I/O 양을 줄일 수 있어요. 또한 삭제된 콘텐츠가 백업에서 모두 제거되어 포렌식 흔적이 남지 않아요. 반면 백업 API는 CPU 사용량이 더 적고 증분 방식으로 실행할 수 있어요.

INTO 절의 파일 이름은 문자열로 평가되는 임의의 SQL 표현식일 수 있어요. INTO 절이 가리키는 파일은 이전에 존재하지 않거나 빈 파일이어야 해요. 그렇지 않으면 VACUUM INTO 명령이 오류와 함께 실패해요.

URI 파일 이름이 활성화되어 있으면 INTO의 인자는 URI 파일 이름일 수 있어요. 다음 중 하나라도 해당하면 URI 파일 이름이 활성화돼요:

  • SQLite 라이브러리가 -DSQLITE_USE_URI=1로 컴파일된 경우
  • 시작 시 sqlite3_config(SQLITE_CONFIG_URI,1) 인터페이스가 호출된 경우
  • VACUUM INTO 문을 실행하는 데이터베이스 연결이 처음에 SQLITE_OPEN_URI 플래그를 사용해 열린 경우

VACUUM INTO 명령은 생성된 출력 데이터베이스가 원본 데이터베이스의 일관된 스냅샷이라는 점에서 트랜잭션적이에요. 하지만 예기치 않은 종료나 전원 손실로 VACUUM INTO 명령이 중단되면 생성된 출력 데이터베이스가 불완전하거나 손상될 수 있어요.

다만 원본 데이터베이스의 PRAGMA synchronous 설정이 NORMAL 또는 FULL이면, SQLite는 출력 데이터베이스를 기록한 후 fsync() 또는 FileFlushBuffers()를 호출해서 디스크에 동기화해요. 즉, 이런 경우에는 VACUUM INTO 명령이 완료된 후 발생하는 전원 손실이나 예기치 않은 종료가 데이터베이스를 손상시키지 않아요(OS, 파일 시스템, 하드웨어가 올바르게 작동한다고 가정해요).

3. VACUUM의 작동 방식

VACUUM 명령은 데이터베이스의 콘텐츠를 임시 데이터베이스 파일로 복사한 다음, 임시 파일의 콘텐츠로 원본을 덮어쓰는 방식으로 작동해요. 원본을 덮어쓸 때는 다른 데이터베이스 트랜잭션과 마찬가지로 롤백 저널 또는 WAL(write-ahead log) 파일이 사용돼요. 즉, 데이터베이스에 VACUUM을 실행할 때는 원본 데이터베이스 파일 크기의 최대 2배에 달하는 여유 디스크 공간이 필요해요.

VACUUM INTO 명령도 동일한 방식으로 작동하지만, 임시 데이터베이스 대신 INTO 절이 가리키는 파일을 사용하고 vacuum된 데이터베이스를 원본 위에 다시 복사하는 단계를 생략해요.

VACUUM 명령은 명시적인 INTEGER PRIMARY KEY가 없는 테이블에 있는 항목들의 ROWID를 변경할 수 있어요.

VACUUM을 실행하려는 데이터베이스 연결에 열린 트랜잭션이 있으면 VACUUM은 실패해요. 종료(finalize)되지 않은 SQL 문은 일반적으로 읽기 트랜잭션을 열린 상태로 유지하므로, 같은 연결에 종료되지 않은 SQL 문이 있으면 VACUUM이 실패할 수 있어요. VACUUM(VACUUM INTO는 제외)은 쓰기 작업이에요. 따라서 다른 데이터베이스 연결이 쓰기를 방해하는 잠금을 보유하고 있으면 VACUUM이 실패해요.

데이터 삭제 후 공간을 회수하기 위해 VACUUM 명령을 사용하는 대안은 auto_vacuum 프래그마로 활성화하는 auto-vacuum 모드예요. 데이터베이스에 auto_vacuum이 활성화되어 있으면 데이터 삭제 후 여유 페이지가 회수되어 파일이 줄어들 수 있고, VACUUM으로 전체 데이터베이스를 재구축할 필요가 없어요. 그러나 auto_vacuum을 사용하면 데이터베이스 파일 단편화가 더 심해질 수 있어요. 또한 auto_vacuum은 VACUUM과 달리 부분적으로만 채워진 데이터베이스 페이지를 압축하지 않아요.

이 페이지는 2025-07-12 15:11:36Z에 마지막으로 업데이트되었어요.

더 알아보기 (Learn more)