Performance 在sqlite中删除时如何避免锁定?
删除查询很简单:Performance 在sqlite中删除时如何避免锁定?,performance,sqlite,cascading-deletes,sql-delete,Performance,Sqlite,Cascading Deletes,Sql Delete,删除查询很简单: DELETE FROM pages WHERE status = 0 大约需要15分钟才能完成(删除约20K行)。它是一个约500 MB的数据库,映射本地文件系统,包含约300万条记录 结构: 页面-只有几条记录 文件-大约230K条记录,包含一个外键约束,在删除级联时带有,该约束引用了页面中的一列 meta-大约有300万条记录,包含外键约束,在DELETE CASCADE上引用文件和页面中的列 search-FTS4表格,几乎与meta完全相同。此表的完整性由触发器维护
DELETE FROM pages WHERE status = 0
大约需要15分钟才能完成(删除约20K行)。它是一个约500 MB的数据库,映射本地文件系统,包含约300万条记录
结构:
-只有几条记录页面
-大约230K条记录,包含一个外键约束,在删除级联时带有文件
,该约束引用了
页面中的一列
-大约有300万条记录,包含外键约束,在DELETE CASCADE上引用meta
和文件
页面中的列
-FTS4表格,几乎与search
完全相同。此表的完整性由触发器维护meta
PS:让我困惑的是插入速度要快得多。插入我删除的记录数量需要2分钟,这段时间包括一些繁重的文件处理(Exif读取大量图像)。为什么删除记录比插入记录慢?从
页面
删除记录慢,因为meta
表中的库
列上没有索引。
每当实际删除页面
记录时,数据库必须搜索与ON DELETE CASCADE约束匹配的任何meta
记录;这将导致对每个已删除记录进行完整的表扫描
(插入速度更快,因为无需进行此类检查。)
SQLite不是为并发而设计的;不可能同时有多个编写器。
但是,为了允许多个读者同时作为一个作者,考虑启用.建议,使用软删除而不是硬删除。缺点是代码更改,可能会增加存储量。数据库模式(包括索引)?@CL:,但我不得不注释掉一个索引和fts表,因为它在SQLFIDLE上似乎不起作用。所谓软删除,是指使用一个值更新记录,该值表明在SELECT查询中不应考虑该记录吗?这就是我正在做的,但我仍然希望在后台进程中删除死记录。问题是,该进程锁定了一些表,并且所做的事情花费的时间太长。我认为它将使用
metaFileId
索引。无论如何,在我为gallery列添加索引之前,我做了一个“解释查询计划”,它确实在扫描meta。现在解释查询计划告诉我正在使用新索引,但查询速度和以前一样慢:(好的,问题是hero
列缺少索引,这也有一个限制:)向meta.gallery
列添加索引没有多大区别,因为它只对每个删除的页面记录进行一次扫描,这对我的db来说是+2秒,我可以接受。但是你是对的,谢谢你的帮助!我希望EXPLAIN QUERY PLAIN能提供更多信息,比如级联删除的搜索/扫描操作。。。
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;