我在 Windows 上使用 SQLite 3.7.2。我的数据库用于存储 24/7 全天候生成的日志数据。架构基本上是:
CREATE TABLE log_message(id INTEGER PRIMARY KEY AUTOINCREMENT, process_id INTEGER, text TEXT);
CREATE TABLE process(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT);
log_message.process_id
字段映射到 process.id
,从而将每条日志消息与其来源的进程相关联。
现在,迟早数据库会变得太大,我想删除最旧的条目(那些具有最低 log_message.id
值的条目),直到数据库再次下降到给定大小(比如,1GB)。为此,我目前正在做
PRAGMA page_count;
PRAGMA page_size;
在每隔几条日志消息后获取数据库的大小。如果它超出了我的限制,我只删除一部分日志消息(现在: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;
后面的 DELETE
语句从 process
表中删除所有未引用的条目。我重复此过程,直到文件大小再次可接受。
这至少有两个问题:
- 删除 100 条日志消息的方法非常随机;我根据一些实验得出了这个数字。我想知道我必须提前删除的条目数。
- 重复的 VACUUM 调用可能会占用相当长的时间(SQLite 主页说 VACUUM 在 Linux 上每 MB 最多可能需要半秒,我猜它在 Windows 上不会更快)。
有人对如何执行此操作有其他建议吗?
最佳答案
当你有一个“大小合适”的数据库时,然后计算 log_message 行的数量。
SELECT COUNT(*) FROM LOG_MESSAGE
存储这个数字。
当你想缩小文件时再次发出计数命令。计算差异,从数据库中删除该行数,然后 VACCUM。
这只能是近似值,但它会让您很快达到接近 1GB。如果您还没有结束,您可以回到一次 100 行的方法。
关于sql - 如何有效地将 SQlite 数据库缩小到给定的文件大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5987042/