SQLite 查询计划
SQLite Query plan
有没有办法操纵在 SQLite 中生成的查询计划?
我试着解释一下我的问题:
我有 3 个 table:
CREATE TABLE "index_term" (
"id" INT,
"term" VARCHAR(255) NOT NULL,
PRIMARY KEY("id"),
UNIQUE("term"));
CREATE TABLE "index_posting" (
"doc_id" INT NOT NULL,
"term_id" INT NOT NULL,
PRIMARY KEY("doc_id", "field_id", "term_id"),,
CONSTRAINT "index_posting_doc_id_fkey" FOREIGN KEY ("doc_id")
REFERENCES "document"("doc_id") ON DELETE CASCADE,
CONSTRAINT "index_posting_term_id_fkey" FOREIGN KEY ("term_id")
REFERENCES "index_term"("id") ON DELETE CASCADE);;
CREATE INDEX "index_posting_term_id_idx" ON "index_posting"("term_id");
CREATE TABLE "published_files" (
"doc_id" INTEGER NOT NULL,,
"uri_id" INTEGER,
"user_id" INTEGER NOT NULL,
"status" INTEGER NOT NULL,
"title" VARCHAR(1024),
PRIMARY KEY("uri_id"));
CREATE INDEX "published_files_doc_id_idx" ON "published_files"("doc_id");
index_term 中约有 600.000 个条目,index_posting 中约有 400 万个条目,published_files table 中约有 300.000 个条目。
现在,当我想在 index_posting 中查找唯一 doc_ids 的数量时,我使用以下 SQL.
select count(distinct index_posting.doc_id) from index_term, index_posting
where
index_posting.term_id = index_term.id and index_term.term like '%test%'
结果显示在合理的时间内(0.3 秒)。询问解释查询计划 returns
0|0|0|SCAN TABLE index_term
0|1|1|SEARCH TABLE index_posting USING INDEX index_posting_term_id_idx (term_id=?)
当我想以仅包含 index_posting 的 doc_ids 的方式过滤计数时,如果存在 published_files 条目:
select count(distinct index_posting.doc_id) from index_term, index_posting,
published_files where
index_posting.term_id = index_term.id and index_posting.doc_id = published_files.doc_id and index_term.term like '%test%'
查询时间几乎是之前的 10 倍。询问解释查询计划 returns
0|0|1|SCAN TABLE index_posting
0|1|0|SEARCH TABLE index_term USING INDEX sqlite_autoindex_index_term_1 (id=?)
0|2|2|SEARCH TABLE published_files AS pf USING COVERING INDEX published_files_doc_id_idx (doc_id=?)
据我所知,SQLITE 在这里更改了它的查询计划,对 index_posting 进行了完整的 table 扫描,并在 index_term 中进行了查找,而不是在另一个中查找一路走来。
作为解决方法,我确实做了
analyze index_posting;
analyze index_term;
analyze published_files;
现在看来是正确的,
0|0|0|SCAN TABLE index_term
0|1|1|SEARCH TABLE index_posting USING INDEX index_posting_term_id_idx (term_id=?)
0|2|2|SEARCH TABLE published_files USING COVERING INDEX published_files_doc_id_idx (doc_id=?)
但我的问题是 - 有没有办法强制 SQLITE 始终使用正确的查询计划?
TIA
ANALYZE 不是解决方法;它应该被使用。
可以使用CROSS JOIN to enforce a certain order of the nested loops, or use INDEXED BY强制使用某个索引。
但是,您要求 "the correct query plan",这可能与这些机制强制执行的不同。
有没有办法操纵在 SQLite 中生成的查询计划?
我试着解释一下我的问题:
我有 3 个 table:
CREATE TABLE "index_term" (
"id" INT,
"term" VARCHAR(255) NOT NULL,
PRIMARY KEY("id"),
UNIQUE("term"));
CREATE TABLE "index_posting" (
"doc_id" INT NOT NULL,
"term_id" INT NOT NULL,
PRIMARY KEY("doc_id", "field_id", "term_id"),,
CONSTRAINT "index_posting_doc_id_fkey" FOREIGN KEY ("doc_id")
REFERENCES "document"("doc_id") ON DELETE CASCADE,
CONSTRAINT "index_posting_term_id_fkey" FOREIGN KEY ("term_id")
REFERENCES "index_term"("id") ON DELETE CASCADE);;
CREATE INDEX "index_posting_term_id_idx" ON "index_posting"("term_id");
CREATE TABLE "published_files" (
"doc_id" INTEGER NOT NULL,,
"uri_id" INTEGER,
"user_id" INTEGER NOT NULL,
"status" INTEGER NOT NULL,
"title" VARCHAR(1024),
PRIMARY KEY("uri_id"));
CREATE INDEX "published_files_doc_id_idx" ON "published_files"("doc_id");
index_term 中约有 600.000 个条目,index_posting 中约有 400 万个条目,published_files table 中约有 300.000 个条目。
现在,当我想在 index_posting 中查找唯一 doc_ids 的数量时,我使用以下 SQL.
select count(distinct index_posting.doc_id) from index_term, index_posting
where
index_posting.term_id = index_term.id and index_term.term like '%test%'
结果显示在合理的时间内(0.3 秒)。询问解释查询计划 returns
0|0|0|SCAN TABLE index_term
0|1|1|SEARCH TABLE index_posting USING INDEX index_posting_term_id_idx (term_id=?)
当我想以仅包含 index_posting 的 doc_ids 的方式过滤计数时,如果存在 published_files 条目:
select count(distinct index_posting.doc_id) from index_term, index_posting,
published_files where
index_posting.term_id = index_term.id and index_posting.doc_id = published_files.doc_id and index_term.term like '%test%'
查询时间几乎是之前的 10 倍。询问解释查询计划 returns
0|0|1|SCAN TABLE index_posting
0|1|0|SEARCH TABLE index_term USING INDEX sqlite_autoindex_index_term_1 (id=?)
0|2|2|SEARCH TABLE published_files AS pf USING COVERING INDEX published_files_doc_id_idx (doc_id=?)
据我所知,SQLITE 在这里更改了它的查询计划,对 index_posting 进行了完整的 table 扫描,并在 index_term 中进行了查找,而不是在另一个中查找一路走来。
作为解决方法,我确实做了
analyze index_posting;
analyze index_term;
analyze published_files;
现在看来是正确的,
0|0|0|SCAN TABLE index_term
0|1|1|SEARCH TABLE index_posting USING INDEX index_posting_term_id_idx (term_id=?)
0|2|2|SEARCH TABLE published_files USING COVERING INDEX published_files_doc_id_idx (doc_id=?)
但我的问题是 - 有没有办法强制 SQLITE 始终使用正确的查询计划?
TIA
ANALYZE 不是解决方法;它应该被使用。
可以使用CROSS JOIN to enforce a certain order of the nested loops, or use INDEXED BY强制使用某个索引。 但是,您要求 "the correct query plan",这可能与这些机制强制执行的不同。