【发布时间】:2013-10-23 00:00:30
【问题描述】:
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 快速删除?
【问题讨论】:
-
如果你加入一个线程怎么办。那么它不会影响用户..我想不理想。
-
注意:在插入之前或之后创建索引所花费的时间大致相同。它仍然需要索引。
-
其实,在交易中围绕
DELETE很有帮助!