学而实习之 不亦乐乎

解决 sqlite 删除数据后,文件大小不变问题

2020-11-12 20:25:24

当你在sqlite中删除了大量数据后,数据库文件的大小没有变。为什么会出现这个问题? 

原因是:
当你从Sqlite删除数据后,未使用的磁盘空间被添加到一个内在的”空闲列表”中用于存储你下次插入的数据。磁盘空间并没有丢失。但是也不向操作系统返回磁盘空间。(Sqlite.org的FAQ中提到过这个问题) 

解决方法

一、在数据删除后,手动执行VACUUM命令,执行方式很简单

SQL 命令方式:
VACUUM

代码方式:
objSQLHelper.ExecuteNonQuery(CommandType.Text, "VACUUM")

VACUUM命令会清空“空闲列表”,把数据库尺寸压缩到最小。但是要耗费一些时间。在手机上执行时,会生成了一个 .db-journal 后缀名的临时文件。

二、在数据库文件中,将 auto_vacuum 设置成"1"

注意:只有在数据库中未建任何表时才能改变auto-vacuum标记。试图在已有表的情况下修改不会导致报错。

cmd.CommandText = "PRAGMA auto_vacuum = 1;"
cmd.ExecuteNonQuery()

当开启auto-vacuum,当提交一个从数据库中删除除数据的事务时,数据库文件自动收缩。数据库会在内部存储一些信息,这使得数据库文件比不开启该选项时稍微大一些。

第二个方法同样有缺点,只会从数据库文件中截断空闲列表中的页,而不会回收数据库中的碎片,也不会像 VACUUM 命令那样重新整理数据库内容。实际上,由于需要在数据库文件中移动页, auto-vacuum 会产生更多的碎片。而且,在执行删除操作的时候,也有那个.db-journal文件产生。

要使用 auto-vacuum,需要一些前题条件。 数据库中需要存储一些额外的信息以记录它所跟踪的每个数据库页都找回其指针位置。 所以,auto-vacumm 必须在建表之前就开启。在一个表创建之后, 就不能再开启或关闭 auto-vacumm。