DELETE 쿼리는 간단하다sqlite에서 DELETE 중 잠금을 피하는 방법은 무엇입니까?
이DELETE FROM pages WHERE status = 0
그것은 (20K 행 ~ 제거) 완료하는 데 약 15 분 정도 소요됩니다. 로컬 파일 시스템을 매핑하는 약 500MB의 데이터베이스이며 약 3 백만 개의 레코드가 들어 있습니다.
구조 :
pages
- 몇 가지 기록files
- 약 3 백만 기록 - 약 23 만 기록은pages
meta
에서 열을 참조ON DELETE CASCADE
와 외래 키 제약 조건을 포함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로 설정하고 동기화를 끄면 조금 더 빨리 실행되지만 너무 위험합니다.
긴 쓰기 잠금을 피하기 위해 나는 0.5 초 간격으로 한 번에 40 레코드를 삭제하려고했습니다. 하지만 이로 인해 전체 프로세스가 10 배까지 느려집니다.
속도를 향상시키고 잠금을 피할 수있는 다른 방법이 있습니까?
추 신 : INSERT가 훨씬 빠르다는 것이 나에게는 당황 스럽습니다. 삭제하는 레코드의 양을 삽입하는 데 2 분이 걸리며 그 시간에는 많은 파일 처리 (Exif가 많은 이미지에서 읽음)가 포함됩니다. 레코드를 삽입하는 것보다 느리게 제거하는 이유는 무엇입니까?
제안하면 하드 삭제보다는 소프트 삭제를 사용하십시오. 단점은 코드가 변경되어 저장 용량이 증가 할 수 있습니다. – Rippo
데이터베이스 스키마 (인덱스 포함)? –
@CL : [스키마] (http://sqlfiddle.com/#!5/39c70),하지만 sqlfiddle에서 작동하지 않는 것처럼 인덱스와 fts 테이블을 주석 처리해야했습니다.부드러운 삭제로 레코드를 SELECT 쿼리에서 고려해서는 안되는 값으로 레코드를 업데이트한다는 의미입니까? 이것이 내가하고있는 일이지만, 여전히 백그라운드 프로세스에서 죽은 레코드를 제거하고 싶습니다. 문제는 프로세스가 일부 테이블을 잠그고 수행하는 작업에 너무 오래 걸리는 것입니다. –