DELETE查询很简单:
DELETE FROM pages WHERE status = 0
完成大约需要15分钟(用于删除~20K行)。它是一个~500 MB的数据库,可以映射本地文件系统,并包含大约300万条记录。
结构:
pages
- 只是几条记录files
- 大约230K记录,包含ON DELETE CASCADE
引用pages
meta
- 大约300万条记录,包含引用ON DELETE CASCADE
和files
pages
的外键约束
search
- 一个FTS4表,与meta
几乎完全相同。使用触发器维护此表的完整性。CREATE TABLE pages(
id INTEGER PRIMARY KEY AUTOINCREMENT,
slug TEXT,
name TEXT NOT NULL,
type INTEGER NOT NULL DEFAULT 1,
data TEXT,
parent INTEGER,
status INTEGER DEFAULT 1,
comments INTEGER DEFAULT 1,
priority INTEGER DEFAULT 0,
UNIQUE(slug),
FOREIGN KEY(parent) REFERENCES pages(id) ON DELETE CASCADE
);
CREATE INDEX "pageParent" ON "pages"("parent");
CREATE TABLE files(
id INTEGER PRIMARY KEY AUTOINCREMENT,
gallery INTEGER NOT NULL,
type INTEGER NOT NULL DEFAULT 1,
sPath TEXT,
rPath TEXT,
parent INTEGER,
hero INTEGER,
hidden INTEGER DEFAULT 0,
createdAt DATETIME,
mTime TEXT,
UNIQUE(sPath),
FOREIGN KEY(gallery) REFERENCES pages(id) ON DELETE CASCADE,
FOREIGN KEY(parent) REFERENCES files(id) ON DELETE CASCADE,
FOREIGN KEY(hero) REFERENCES files(id) ON DELETE SET NULL
);
CREATE INDEX "fileGallery" ON "files"("gallery");
CREATE INDEX "fileType" ON "files"("type");
CREATE INDEX "fileParent" ON "files"("parent");
CREATE INDEX "fileRPathNS" ON "files"("rPath" COLLATE NATSORT);
CREATE TABLE thumbs(
hash TEXT,
image INTEGER,
width INTEGER,
height INTEGER,
FOREIGN KEY(image) REFERENCES files(id) ON DELETE CASCADE,
PRIMARY KEY(hash, image) ON CONFLICT REPLACE
);
CREATE INDEX "thumbImage" ON "thumbs"("image");
CREATE TABLE meta(
id INTEGER PRIMARY KEY AUTOINCREMENT,
file INTEGER NOT NULL,
key TEXT NOT NULL,
value TEXT,
extra TEXT,
gallery INTEGER,
FOREIGN KEY(gallery) REFERENCES pages(id) ON DELETE CASCADE,
FOREIGN KEY(file) REFERENCES files(id) ON DELETE CASCADE
);
CREATE INDEX "metaFileId" ON "meta"("file");
CREATE INDEX "metaKey" ON "meta"("key");
CREATE INDEX "metaExtra" ON "meta"("extra");
CREATE VIRTUAL TABLE search USING fts4(file, key, value, gallery);
CREATE TRIGGER metaBeforeUpd BEFORE UPDATE ON meta BEGIN
DELETE FROM search WHERE docid = OLD.rowid;
END;
CREATE TRIGGER metaBeforeDel BEFORE DELETE ON meta BEGIN
DELETE FROM search WHERE docid = OLD.rowid;
END;
CREATE TRIGGER metaAfterUpd AFTER UPDATE ON meta BEGIN
INSERT INTO search(docid, file, key, value, gallery) VALUES(NEW.rowid, NEW.file, NEW.key, NEW.value, NEW.gallery);
END;
CREATE TRIGGER metaAfterIns AFTER INSERT ON meta BEGIN
INSERT INTO search(docid, file, key, value, gallery) VALUES(NEW.rowid, NEW.file, NEW.key, NEW.value, NEW.gallery);
END;
问题是它不仅速度慢,而且还会锁定这些表,因此在此期间我无法对它们进行任何更改。
我尝试了this question and answers的所有建议,但没有重大改进。将日记模式设置为MEMORY并关闭同步使其运行速度更快,但风险太大。
为了避免长写锁定,我尝试逐步删除记录,40时间间隔0.5秒。但这会使整个过程减慢甚至10倍
还有其他方法可以提高速度和/或避免锁定吗?
答案 0 :(得分:2)
从pages
删除的速度很慢,因为gallery
表中的meta
列没有索引。
每当实际删除pages
记录时,数据库必须搜索与ON DELETE CASCADE约束匹配的任何meta
记录;这会导致每个已删除记录的全表扫描。
(INSERT更快,因为不必进行此类检查。)
SQLite不是为并发而设计的;永远不可能同时拥有多个作者。 但是,要允许多个读者同时作为作者,请考虑启用write-ahead logging。