VACUUM命令重建数据库文件,将其重新打包到最小的磁盘空间中。应用程序可能会这样做的原因有几个:
除非SQLite在“ auto_vacuum = FULL”模式下运行,否则从数据库文件中删除大量数据时,它将留下空白空间或“可用”数据库页面。这意味着数据库文件可能大于严格所需的文件。运行VACUUM重建数据库将回收此空间并减小数据库文件的大小。
频繁的插入,更新和删除会导致数据库文件碎片化-单个表或索引的数据分散在数据库文件周围。运行VACUUM可确保每个表和索引在数据库文件中很大程度上连续存储。在某些情况下,VACUUM还可以减少数据库中部分填充的页面数,从而进一步减小数据库文件的大小。
从SQLite数据库删除内容时,通常不会删除内容,而是将用于保存内容的空间标记为可重复使用。这可以允许黑客或通过取证分析来恢复已删除的内容。运行VACUUM将清除数据库中所有已删除内容的痕迹,从而防止对手恢复已删除内容。以这种方式使用VACUUM是设置PRAGMA secure_delete = ON的替代方法 。
通常,必须在实际创建数据库文件之前配置数据库的page_size以及数据库是否支持auto_vacuum。但是,当不在预写日志模式下时,可以使用page_size 和/或 pragma auto_vacuum编译指示来更改现有数据库的 page_size和/或auto_vacuum属性,然后立即对数据库进行VACUUM。在预写日志模式下,只能 使用VACUUM更改auto_vacuum支持属性。
默认情况下,VACUUM仅在主数据库上起作用。 通过将适当的架构名称附加到VACUUM语句,可以清理 附加的数据库。
兼容性警告:版本3.15.0(2016-10-14)中添加了清理附加数据库的功能。在此之前,添加到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()来确保在完成之前已到达非易失性存储。
VACUUM命令的工作原理是将数据库的内容复制到一个临时数据库文件中,然后用该临时文件的内容覆盖原始文件。覆盖原始文件时,将使用回滚日志或预写日志WAL文件,就像处理任何其他数据库事务一样。这意味着在对数据库进行VACUUM时,可用磁盘空间需要的大小是原始数据库文件的两倍。
VACUUM INTO命令的工作方式相同,不同之处在于它使用INTO子句中命名的文件代替临时数据库,并省略了将清理后的数据库复制回原始数据库之上的步骤。
VACUUM命令可以更改没有显式INTEGER PRIMARY KEY的任何表中条目的ROWID。
如果数据库连接上有尝试运行VACUUM的打开事务,则VACUUM将失败。未完成的SQL语句通常会使读取事务保持打开状态,因此,如果同一连接上存在未完成的SQL语句,则VACUUM可能会失败。VACUUM(但不是VACUUM INTO)是写操作,因此,如果另一个数据库连接持有阻止写操作的锁,则VACUUM将失败。
删除数据后使用VACUUM命令回收空间的另一种方法是使用auto_vacuum编译指示启用自动真空模式。当auto_vacuum了数据库的免费页面可能删除数据,导致文件缩水,不重建使用真空整个数据库之后被回收启用。但是,使用 auto_vacuum可能导致额外的数据库文件碎片。并且auto_vacuum 不会像VACUUM那样压缩数据库的部分填充页面。