SQlite,Android,真实故事。我有一个表,我将其用作缓存:
CREATE TABLE cache(key TEXT, ts TIMESTAMP, size INTEGER, data BLOB);
CREATE UNIQUE INDEX by_key ON cache(key);
CREATE INDEX by_ts ON cache(ts);
在应用程序生命周期中,我填充了缓存,并且在某些时候我想清除它并删除N
记录。通常,此表将包含 ~25000 个 ~100-500Kb 的 blob,数据库中的总 blob 大小为 600-800Mb,但现在我测试 ~2000 个约为 60Mb(以下数字适用于这种情况)。Clear 删除 90% 的缓存条目。
我尝试了不同的方法来做到这一点,这里简要说明:
[1]最糟糕和最简单的。首先选择,而不是一一删除,行走光标。非常慢。
[2]让 SQLite 通过查询来完成(删除其中包含全部N
字节的 blob):
DELETE FROM blobs WHERE
ROWID IN (SELECT ROWID FROM blobs WHERE
(SELECT SUM(size) FROM blobs AS _ WHERE ts <= blobs.ts) <= N);
这更快,但仍然非常慢:~15 秒。似乎它也具有二次复杂性。
[3]选择要删除的行(使用平均 blob 大小进行计算)并使用简单WHERE
子句删除:
-- Find row after which to delete, let it's time stamp is T0:
SELECT ts FROM cache ORDER BY ts LIMIT 1 OFFSET count;
-- Delete
DELETE FROM cache WHERE ts < T0;
这要好得多,但需要约 7 秒。
[4]创建新表,复制我需要保存并删除旧表。请注意,在复制所有这些内容之后,我在新表中创建了索引:
-- Insert only rows I want leave
INSERT INTO temp(key, ts, size, data) SELECT key, ts, size, data
FROM cache ORDER BY ts LIMIT count;
-- Drop table and indices.
DROP INDEX by_key;
DROP INDEX by_ts;
DROP TABLE cache;
-- Rename temp table and create indices...
对于 6Mb 的 blob,复制需要大约 300 毫秒。但是DROP TABLE
大约是 8 秒。
请注意,在所有情况下,我都VACUUM
需要大约 1 秒。我怎样才能使它快速?为什么DROP TABLE
和删除这么慢?我认为这可能是因为索引:当我在DELETE
它工作得更快之前删除了关键索引。如何让 SQLite 快速删除?