2016-01-13 117 views
0

有沒有辦法來處理在SQLite中生成的查詢計劃?SQLite查詢計劃

我「L試着解釋我的問題:

我有3個表:

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"); 

約600.000條目在index_term,約4百萬在index_posting並在published_files表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秒)。問解釋查詢計劃返回

0|0|0|SCAN TABLE index_term 
0|1|1|SEARCH TABLE index_posting USING INDEX index_posting_term_id_idx (term_id=?) 

時,我想,它僅包括,如果存在一個published_files進入index_posting的doc_ids的方式來過濾計數:

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倍長。問解釋查詢計劃返回

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的全表掃描和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

回答

1

ANALYZE不是一種變通方法;它應該被使用。

您可以使用CROSS JOIN強制執行某個嵌套循環的順序,或使用INDEXED BY強制使用某個索引。 但是,您要求提供「正確的查詢計劃」,可能與這些機制強制執行的計劃不一樣。