压缩Sqlite数据文件大小,解决数据删除后占用空间不变的问题

最近有一网站使用Sqlite数据库作为数据临时性的缓存,对多片区进行划分 Sqlite数据库文件,每天大概新增近1万的数据量,起初效率有明显的提高,但历经一个多月后数据库文件从几K也上升到了近160M,数据量也达到了 40多万条,平均每一条数据占用了 4K的空间,虽然使用上的效率直观上没有造成太大的影响,但服务器的占用内存却比原来多占用了20%左右。今天刚好打算清除一个Sqlite的冗余数据, 将保留最近10天的数据就可以了,结果执行了删除指令delete后删除30多万条数据保留了10多万数据,却发现Sqlite数据库文件占用空间的大小 一点没有少,这是为什么呢?


 


原因是:


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


 


解决方法:两种


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


 


objSQLHelper.ExecuteNonQuery(CommandType.Text, "VACUUM")


 


VACUUM命令会清空“空闲列表”,把数据库尺寸压缩到最小。但是要耗费一些时间。


FQA里面说,在Linux的环境下,大约0.5秒/M。并且要使用两倍于数据库文件的空间。


我憎恨此FQA,他只说系统环境,不说机器硬件环境。我在测试手机上执行用了将近13秒时间压缩了将近3M的空间。至于它所占用的另一部分空间,是生成了一个.db-journal后缀名的临时文件。(这个问题对我现在来说是无所谓的。)


 


使用Navicat for Sqlite也是非常简单的,如下图所示:




打开命令界面,手工输入 VACUUM;


回车即可;


 


二,在数据库文件建成中,将auto_vacuum设置成“1”。


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


cmd.CommandText = "PRAGMA auto_vacuum = 1;"


cmd.ExecuteNonQuery()


当开启auto-vacuum,当提交一个从数据库中删除除数据的事物时,数据库文件自动收缩。


数据库会在内部存储一些信息以便支持这一功能,这使得数据库文件比不开启该选项时稍微大一些。


我的表结构,不含任何数据是,数据库文件大小是25K左右,开了auto_vacuum之后是26K。


插入运行基础数据后,文件变成35K,开了auto_vacuum之后是36K。


变化不大,无所谓。


有话要说