VACUUM命令是SQLite的一個擴充功能,模仿PostgreSQL中的相同命令而來。若調用VACUUM帶一個表名或索引名, 則將整理該表或索引。在SQLite 1.0中,VACUUM命令調用 gdbm_reorganize()整理後端資料庫檔案。
SQLITE 2.0.0中去掉了GDBM後端,VACUUM無效。在2.8.1版中,VACUUM被重新實現。現在索引名或表名被忽略。
當資料庫中的一個對象(表,索引或觸發器)被撤銷,會留下空白的空間。它使資料庫比需要的大小更大,但能加快插入速度。即時的插入和刪除會使得資料庫檔案結構混亂,減慢對資料庫內容訪問的速度。 VACUUM命令複製主要資料庫檔案到臨時資料庫並從臨時資料庫重新載入主要資料庫,以整理資料庫檔案。這將除去空白頁,使表資料彼此相鄰排列,並整理資料庫檔案結構。不能對附加資料庫檔案進行以上操作。
若當前有活動事務,該命令無法起作用。對於in-memory資料庫,該命令無效。
SQLite3.1中,可以通過使用auto-vacuum模式取代VACUUM命令,使用 auto_vacuum pragma開啟該模式。
VACUUM的使用:VACUUM main
當對3.4節中討論的資料進行VACUUM操作後,頁面只剩第一個頁面。
VACUUM實現:
代碼實現(vcuum.c):int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
///////////////////////////////////第1步////////////////////////////////////////////////
zSql = sqlite3MPrintf("ATTACH '%q' AS vacuum_db;", zTemp);
//建立臨時資料庫vacuum_db
rc = execSql(db, zSql);
///////////////////////////////////第2步////////////////////////////////////////////////
//開始一個事務
rc = execSql(db, "BEGIN EXCLUSIVE;");
///////////////////////////////////第3步////////////////////////////////////////////////
//在vacuum_db中建立main資料庫的所有表,索引和視圖,並將main中的所有表,索引和視圖的資料插入
//到vacuum_db。即在vacuum_db建立main的鏡象。
rc = execExecSql(db,
"SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14,100000000) "
" FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = execExecSql(db,
"SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14,100000000)"
" FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' ");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = execExecSql(db,
"SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21,100000000) "
" FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = execExecSql(db,
"SELECT 'CREATE VIEW vacuum_db.' || substr(sql,13,100000000) "
" FROM sqlite_master WHERE type='view'"
);
rc = execExecSql(db,
"SELECT 'INSERT INTO vacuum_db.' || quote(name) "
"|| ' SELECT * FROM ' || quote(name) || ';'"
"FROM sqlite_master "
"WHERE type = 'table' AND name!='sqlite_sequence';"
);
///////////////////////////////////第4步////////////////////////////////////////////////
//將vacumm_db資料庫對應的資料檔案的資料拷貝到main資料庫對應的資料檔案,一個頁面一個頁面的拷貝
rc = sqlite3BtreeCopyFile(pMain, pTemp);
///////////////////////////////////第5步////////////////////////////////////////////////
//提交事務
rc = sqlite3BtreeCommit(pTemp);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = sqlite3BtreeCommit(pMain);
}