原因是:
sqlite采用的是變長紀錄存儲,當你從Sqlite刪除數據后,未使用的磁盤空間被添加到一個內在的”空閑列表”中用於存儲你下次插入的數據,用於提高效率,磁盤空間並沒有丟失,但也不向操作系統返回磁盤空間,這就導致刪除數據乃至清空整個數據庫后,數據文件大小還是沒有任何變化,還是很大
解決方法:兩種
一,在數據刪除后,手動執行VACUUM命令,執行方式很簡單
sqlite> vacuum;
VACUUM命令會清空“空閑列表”,把數據庫尺寸壓縮到最小。但是要耗費一些時間。
FQA里面說,在Linux的環境下,大約0.5秒/M。並且要使用兩倍於數據庫文件的空間。
我憎恨此FQA,他只說系統環境,不說機器硬件環境。我在測試手機上執行用了將近13秒時間壓縮了將近3M的空間。至於它所占用的另一部分空間,是生成了一個.db-journal后綴名的臨時文件。(這個問題對我現在來說是無所謂的。)
二,在數據庫文件建成中,將auto_vacuum設置成“1”。
注意:只有在數據庫中未建任何表時才能改變auto-vacuum標記。試圖在已有表的情況下修改不會導致報錯。
cmd.CommandText = "PRAGMA auto_vacuum = 1;"
cmd.ExecuteNonQuery()
當開啟auto-vacuum,當提交一個從數據庫中刪除除數據的事物時,數據庫文件自動收縮。
數據庫會在內部存儲一些信息以便支持這一功能,這使得數據庫文件比不開啟該選項時稍微大一些。
我的表結構,不含任何數據是,數據庫文件大小是25K左右,開了auto_vacuum之后是26K。
插入運行基礎數據后,文件變成35K,開了auto_vacuum之后是36K。
變化不大,無所謂。
但是第二個方法同樣有缺點,只會從數據庫文件中截斷空閑列表中的頁, 而不會回收數據庫中的碎片,也不會像VACUUM 命令那樣重新整理數據庫內容。實際上,由於需要在數據庫文件中移動頁, auto-vacuum 會產生更多的碎片。而且,在執行刪除操作的時候,也有那個.db-journal文件產生。
要使用auto-vacuum,需要一些前題條件。 數據庫中需要存儲一些額外的信息以記錄它所跟蹤的每個數據庫頁都找回其指針位置。 所以,auto-vacumm 必須在建表之前就開啟。在一個表創建之后, 就不能再開啟或關閉 auto-vacumm。
其實按照運行時間上的比較,兩個在做了大刪除操作后,從3M變到35K的時間其實差不多,執行VACUUM命令稍微長一點,但是也長不了多少,相對而言,這種一點點的長可以忽略不計。
加上AUTO的方式對碎片的造成情況,如果數據交換次數多的話,這種方式很不合適。