VACUUM în SQLite

Indexuri și performanță SQLite 3.0.0 (VACUUM INTO din 3.27.0)

Reconstruiește fișierul bazei de date: eliberează spațiul rămas după ștergeri și, cu INTO, face o copie compactă.

Sintaxă
VACUUM;
VACUUM schema;
VACUUM INTO 'fisier.db';

Ce face VACUUM

Când ștergi rânduri, SQLite nu micșorează fișierul: paginile eliberate rămân în fișier, pe o listă de pagini libere (freelist), și sunt refolosite la următoarele inserări. VACUUM copiază tot conținutul într-o bază nouă, compactă, și o pune în locul celei vechi, așa că fișierul se micșorează.

VACUUM INTO 'copie.db' scrie baza compactată într-un fișier nou și lasă originalul neatins. Este un mod simplu de a face o copie de siguranță consistentă a unei baze deschise. Fișierul destinație nu trebuie să existe sau trebuie să fie gol.

VACUUM are nevoie de spațiu liber pe disc de până la dublul bazei, durează pe baze mari și nu poate rula în interiorul unei tranzacții. Ca alternativă, PRAGMA auto_vacuum = FULL (setată înainte de a crea tabele) eliberează paginile automat, dar poate fragmenta fișierul.

Parametri

Parametru Descriere
schema Baza atașată pe care o compactezi (main implicit).
INTO 'fisier' Scrie rezultatul într-un fișier nou, în loc să înlocuiască baza curentă.

Exemple

Exemplul 1: Paginile libere după o ștergere

Exemplul deschide un fișier, adaugă 2.000 de rânduri cu un CTE recursiv și le șterge pe ultimele 1.500. Paginile golite rămân în fișier, pe lista de pagini libere (freelist_count). După VACUUM, fișierul are mai puține pagini și nicio pagină liberă.

.open magazin.db
CREATE TABLE note (id INTEGER PRIMARY KEY, text TEXT);
WITH RECURSIVE n(i) AS (SELECT 1 UNION ALL SELECT i + 1 FROM n WHERE i < 2000)
INSERT INTO note (text) SELECT printf('Nota %d pentru elevul din Iași', i) FROM n;
DELETE FROM note WHERE id > 500;

SELECT page_count, freelist_count FROM pragma_page_count, pragma_freelist_count;
VACUUM;
SELECT page_count, freelist_count FROM pragma_page_count, pragma_freelist_count;

Rezultat

╭────────────┬────────────────╮
│ page_count │ freelist_count │
╞════════════╪════════════════╡
│         22 │             15 │
╰────────────┴────────────────╯
╭────────────┬────────────────╮
│ page_count │ freelist_count │
╞════════════╪════════════════╡
│          7 │              0 │
╰────────────┴────────────────╯

Exemplul 2: Copie de siguranță cu VACUUM INTO

VACUUM INTO creează copie.db; o atașăm ca să verificăm că are aceleași date.

.open magazin.db
CREATE TABLE clienti (nume TEXT, oras TEXT);
INSERT INTO clienti VALUES ('Ana', 'Iași'), ('Mihai', 'Cluj');

VACUUM INTO 'copie.db';

ATTACH 'copie.db' AS copie;
SELECT * FROM copie.clienti ORDER BY nume;

Rezultat

╭───────┬──────╮
│ nume  │ oras │
╞═══════╪══════╡
│ Ana   │ Iași │
│ Mihai │ Cluj │
╰───────┴──────╯

Greșeli frecvente

  • Rulezi VACUUM după fiecare DELETE. Paginile libere sunt oricum refolosite; VACUUM merită doar după ștergeri mari, când vrei fișierul mai mic.
  • Rulezi VACUUM într-o tranzacție (BEGIN; ... VACUUM;): primești eroarea cannot VACUUM from within a transaction.
  • Copiezi fișierul .db cu cp cât timp aplicația scrie în el (sau fără fișierele -wal). Copia poate fi inconsistentă; folosește VACUUM INTO sau comanda .backup.

Comenzi înrudite

  • PRAGMA journal_mode (WAL): Alege cum protejează SQLite datele la scriere. Modul WAL permite citiri în timp ce altcineva scrie și este alegerea uzuală pentru aplicații.
  • PRAGMA integrity_check: Verifică dacă fișierul bazei de date este întreg: paginile, indexurile și constrângerile. Răspunde „ok” dacă totul e în regulă.
  • ATTACH DATABASE: Deschide încă o bază de date în aceeași conexiune, ca să interoghezi sau să copiezi date între fișiere cu SQL obișnuit.
  • .dump: Scrie toată baza de date (sau doar unele tabele) ca instrucțiuni SQL, bune pentru backup, transfer sau control al versiunilor.