VACUUM

1.语法

真空stmt:

VACUUM schema-name INTO filename

2.说明

VACUUM 命令重建数据库文件,将其重新打包到最少的磁盘空间中。应用程序可能这样做的原因有多种:

  • 除非 SQLite 以“auto_vacuum=FULL”模式运行,否则当从数据库文件中删除大量数据时,它会留下空白空间或“空闲”数据库页面。这意味着数据库文件可能比绝对必要的要大。运行 VACUUM 重建数据库会回收此空间并减小数据库文件的大小。

  • 频繁的插入、更新和删除会导致数据库文件变得碎片化——单个表或索引的数据分散在数据库文件周围。运行 VACUUM 确保每个表和索引大部分连续存储在数据库文件中。在某些情况下,VACUUM 还可以减少数据库中部分填充的页数,从而进一步减小数据库文件的大小。

  • 当从 SQLite 数据库中删除内容时,通常不会删除内容,而是将用于保存内容的空间标记为可重复使用。这可以允许黑客或通过取证分析恢复已删除的内容。运行 VACUUM 将清除数据库中所有已删除内容的痕迹,从而防止对手恢复已删除的内容。以这种方式使用 VACUUM 是设置PRAGMA secure_delete=ON的替代方法

  • 通常,数据库page_size和数据库是否支持auto_vacuum必须在实际创建数据库文件之前配置。然而,当不处于预写日志模式时, 现有数据库的page_size和/或auto_vacuum属性可以通过使用page_size 和/或 pragma auto_vacuum pragmas 更改,然后立即对数据库进行 VACUUMing。预写日志模式下,只能 使用 VACUUM 更改 auto_vacuum支持属性。

默认情况下,VACUUM 在主数据库上运行。 可以通过将适当的 模式名称附加到 VACUUM 语句 来清理附加的数据库。

兼容性警告:在版本 3.15.0 (2016-10-14)中添加了清理附加数据库的功能。在此之前, 添加到 VACUUM 语句的模式名称将被静默忽略,“主”模式将被清理。

2.1. 带有 INTO 子句的 VACUUM

如果包含 INTO 子句,则原始数据库文件不变,并在由 INTO 子句的参数命名的文件中创建一个新数据库。新数据库将包含与原始数据库相同的逻辑内容,完全清理。

带有 INTO 子句的 VACUUM 命令是 用于生成实时数据库备份副本的备份 API的替代方法。使用 VACUUM INTO 的优点是生成的备份数据库的大小最小,因此可以减少文件系统 I/O 的数量。此外,所有已删除的内容都会从备份中清除,不会留下任何取证痕迹。另一方面,备份 API使用更少的 CPU 周期并且可以增量执行。

INTO 子句中的文件名可以是计算结果为字符串的任意 SQL 表达式。INTO 子句指定的文件之前必须不存在,否则它必须是一个空文件,否则 VACUUM INTO 命令将失败并出错。

如果启用了 URI 文件名,则INTO 的参数可以是URI 文件名。如果满足以下任一条件,则启用 URL 文件名:

VACUUM INTO 命令是事务性的,因为生成的输出数据库是原始数据库的一致快照。但是,如果 VACUUM INTO 命令被意外关机或断电中断,则生成的输出数据库可能不完整且已损坏。此外,SQLite 不会在生成的数据库上调用 fsync() 或 FlushFileBuffers() 以确保它在完成之前已到达非易失性存储。

3. VACUUM 的工作原理

VACUUM 命令的工作原理是将数据库的内容复制到临时数据库文件中,然后用临时文件的内容覆盖原始文件。覆盖原始文件时,将使用回滚日志或预写日志WAL 文件,就像用于任何其他数据库事务一样。这意味着当 VACUUMing 数据库时,可用磁盘空间需要原始数据库文件大小的两倍。

VACUUM INTO 命令的工作方式相同,只是它使用 INTO 子句中命名的文件代替临时数据库,并省略了将已清理的数据库复制回原始数据库之上的步骤。

VACUUM 命令可以更改任何没有显式INTEGER PRIMARY KEY的表中条目的ROWID

如果在尝试运行 VACUUM 的数据库连接上存在打开的事务,则 VACUUM 将失败。未完成的 SQL 语句通常会打开一个读取事务,因此如果同一连接上有未完成的 SQL 语句,则 VACUUM 可能会失败。VACUUM(但不是 VACUUM INTO)是一个写操作,因此如果另一个数据库连接持有阻止写入的锁,则 VACUUM 将失败。

在删除数据后使用 VACUUM 命令回收空间的替代方法是自动真空模式,使用auto_vacuum pragma 启用。当为数据库启用auto_vacuum时,删除数据后可能会回收空闲页面,导致文件缩小,而无需使用 VACUUM 重建整个数据库。但是,使用 auto_vacuum会导致额外的数据库文件碎片。auto_vacuum不像VACUUM 那样压缩数据库的部分填充页面。