sqlite删除数据
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 文件名