Skip to content

SQLite - VACUUM

在 SQLite 中,当你删除数据时,被占用的空间会被标记为“空闲”并可供未来插入操作重用,但数据库文件的大小不会缩小。VACUUM 命令会从头开始重建整个数据库文件,以回收这些未使用的空间,从而得到一个更小、更紧凑(去碎片化)的数据库文件。

这个过程会将内容复制到一个临时数据库,然后再重新加载到原始文件中。这通过消除空闲页面并使表数据连续来清理文件结构。请注意:对于没有显式 INTEGER PRIMARY KEY 的表,VACUUM 可能会改变条目的 ROWID。

VACUUM 对整个 main 数据库进行操作。它不能用于附加的数据库。如果当前有活跃的事务正在进行,它也会失败。对于内存数据库,VACUUM 没有效果。

要在整个数据库上运行 VACUUM,你可以在 SQLite shell 中直接执行该命令:

sqlite> VACUUM;

注意:旧语法 VACUUM table_name; 在现代 SQLite 版本中已不再支持。VACUUM 总是处理整个数据库。

一个更新的、通常更安全的替代方案是 VACUUM INTO。这个命令将数据库的一个新的、已整理的版本写入到一个单独的文件中,而不会触及原始数据库。这对于创建干净的备份非常有用。

语法:

sqlite> VACUUM INTO 'new_database_file.db';

这会创建一个名为 new_database_file.db 的最小化、去碎片化的副本。

自动 VACUUM 是一种不同的机制。它不是重建数据库,而是将空闲页面移动到文件末尾并截断文件,从而防止文件不必要地增长。它不像完整的 VACUUM 那样整理数据碎片。此模式必须在创建表之前启用。

你可以使用 PRAGMA 语句配置自动 VACUUM:

-- 禁用自动 VACUUM(默认)
PRAGMA auto_vacuum = NONE; -- Value: 0
-- 启用完全自动 VACUUM
PRAGMA auto_vacuum = FULL; -- Value: 1
-- 启用增量 VACUUM(需要 PRAGMA incremental_vacuum)
PRAGMA auto_vacuum = INCREMENTAL; -- Value: 2

你可以从命令行检查数据库的当前设置:

$ sqlite3 your_database.db "PRAGMA auto_vacuum;"
  • 性能影响: VACUUM 可能是一个缓慢且 I/O 密集型的操作,在运行时会阻塞所有其他数据库连接。请在维护期间使用它。
  • 何时使用: 在大规模数据删除后,它最有效。对于存储有限的嵌入式系统上的数据库,定期进行 VACUUM 处理可能至关重要。
  • auto_vacuum 与 VACUUM: 对于频繁更改的数据库,使用 auto_vacuum 来控制文件大小。使用 VACUUM 进行定期的深度清理和去碎片化。