如何有效地将SQlite数据库修剪到给定的文件大小?

Fre*_*abe 7 sql windows sqlite

我在Windows上使用SQLite 3.7.2.我的数据库用于存储每周7天每天24小时生成的日志数据.架构基本上是:

CREATE TABLE log_message(id INTEGER PRIMARY KEY AUTOINCREMENT, process_id INTEGER, text TEXT);
CREATE TABLE process(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT);
Run Code Online (Sandbox Code Playgroud)

log_message.process_id字段映射到process.id,从而将每个日志消息与其源自的进程相关联.

现在,数据库迟早会变得太大,我想删除最旧的条目(具有最低log_message.id值的条目),直到数据库再次降到给定大小(例如,1GB).为此,我正在做

PRAGMA page_count;
PRAGMA page_size;
Run Code Online (Sandbox Code Playgroud)

在每几条日志消息之后获取数据库的大小.如果超过我的限制,我只删除一小部分(现在:100条消息)的日志消息,如下所示:

BEGIN TRANSACTION;
DELETE FROM log_message WHERE id IN (SELECT id FROM log_message LIMIT 100);
DELETE FROM process WHERE id IN (SELECT id FROM PROCESS EXCEPT SELECT process_id FROM log_message);
COMMIT;
VACUUM;
Run Code Online (Sandbox Code Playgroud)

后一个DELETE语句从process表中删除所有未引用的条目.我重复这个过程,直到文件大小再次被接受.

这至少有两个问题:

  1. 删除100条日志消息的方法非常随机; 我根据一些实验得出了这个数字.我想知道我必须提前删除的条目数量.
  2. 重复的VACUUM调用可能需要相当长的时间(SQLite主页上说,在Linux上,每个MB的VACUUM可能需要多达半秒,我想在Windows上它不会更快).

有没有人对如何做到这一点有其他建议?

Jam*_*son 2

当您有一个“大小合适”的数据库时,请计算 log_message 行数。

SELECT COUNT(*) FROM LOG_MESSAGE
Run Code Online (Sandbox Code Playgroud)

存储这个号码。

当您想要缩小文件时,再次发出 count 命令。计算差异,从数据库中删除该行数,然后删除 VACCUM。

这只能是近似值,但它会让您很快接近 1GB。如果仍然结束,您可以返回到一次 100 行的方法。