sqlite刪除數據
某日, 在使用sqlite的時候發現查詢速度極慢, 查看了一下文件大小, sqlite數據庫文件已經達到了 22G! 對於一個文件數據庫來說, 已經相當致命了,先不說后面如果解決文件過大的問題, 首先手動刪除一些文件, 釋放一些空間; 本文就釋放空間的過程遇到的問題做一個記錄
問題一: 刪除表后, 數據庫文件占用磁盤空間並沒有釋放
在 drop table **
之后, 查看文件占用空間大小, 發現並沒有變化
是因為sqlite的機制是, 當你刪除表后, sqlite會把釋放出來的空間, 放到一個空閑列表中, 用於下次你插入數據的時候用, 並不會把空間返還給操作系統 , 很流氓的做法
這時如果想強制釋放空間, 需要用 vacuum;
命令
問題二:db or disk is full
當你執行完 vacuum命令后, 滿心歡喜的等待釋放空間, 結果等了好久, 最后報了一個這個錯, 說磁盤或者數據庫空間已滿;
這是因為 sqlite執行 vacuum命令釋放空間的機制, 是需要把數據庫文件拷貝到一個臨時文件中, 然后再刪除;所以需要兩倍於 數據庫文件大小 的磁盤空間
問題三:Vacuum命令的臨時文件目錄, 是哪個
磁盤當然是不夠用的, 那這時需要掛載一個硬盤了, 可是, 掛載到哪個目錄呢?
在上一步執行 vacuum命令的時候, 觀察了一下 磁盤使用情況, 發現 根目錄 / 一直在增加使用量;那肯定是臨時文件生成到 根目錄了, 是根目錄的那個目錄呢; 要是直接把硬盤掛載到根目錄, 那就別玩了;
查了一下谷歌,這個論壇 https://oomake.com/question/6765345 指出了 sqlite vacuum的臨時文件目錄
粘貼一下 文章內容:
注意到在VACUUM期間,SQLite創建的臨時文件大小與原始數據庫大小相同。它這樣做是為了維護數據庫ACID屬性。 SQLite使用一個目錄來保存執行VACUUM時所需的臨時文件。為了確定要使用的目錄,它會下降層次結構,查找具有適當訪問權限的第一個目錄。如果它找到了一個它無權訪問的目錄,它將忽略該目錄並繼續下降層次結構,尋找它所執行的目錄。我提到這個,以防任何人指定了一個環境變量,而SQLite似乎忽略了它。 在他的回答中,CL給出了Linux的層次結構,並在他的評論中提到層次結構是依賴於操作系統的。為了完整性,這里是層次結構(據我可以從代碼中確定它們)。 對於Unix(和Linux),層次結構是:
- 無論SQLITE_TMPDIR環境變量指定了什么,
- 無論TMPDIR環境變量指定什么,
- / var / tmp中,
- 的/ usr / TMP,
- / tmp,最后
- 當前的工作目錄。
對於Cygwin,層次結構是:
- 無論SQLITE_TMPDIR環境變量指定了什么,
- 無論TMPDIR環境變量指定什么,
- 無論TMP環境變量指定什么,
- 無論TEMP環境變量指定什么,
- 無論USERPROFILE環境變量指定了什么,
- / var / tmp中,
- 的/ usr / TMP,
- / tmp,最后
- 當前的工作目錄。
對於Windows,層次結構是:
- GetTempPath(),記錄為返回:
- 無論TMP環境變量指定什么,
- 無論TEMP環境變量指定什么,
- 無論USERPROFILE環境變量指定了什么,最后
- Windows目錄。
有了這個, 就可以了, 把硬盤掛載到/ var / tmp 目錄, 或者再sqlite交互頁面中, 執行臨時文件的目錄
關於SQLITE_TMPDIR 的指定, 參考官方文檔 https://www.sqlite.org/pragma.html#pragma_temp_store_directory 使用 PRAGMA temp_store_directory = 'directory-name';
命令可以指定 臨時文件的目錄, 注意一定要保證該目錄有寫權限
再說一下掛載的問題:
運營給的硬盤的盤符是 xvdg,那么掛載點就是 /dev/xvdg
掛載命令: sudo mount /dev/xvdg /var/tmp/
這樣就把 /var/tmp/ 掛載到了新硬盤上了
卸載的命令:
umount /dev/xvdg
或者 umount /var/tmp
查看一個目錄的掛載位置: df 文件名