我有一個複雜的C#程序,它使用動態構建的查詢從SQLite數據庫中讀取。 當我在調試器下運行程序,我注意到,我得到的大量輸出,如:當字段是表的主鍵SQLite「MyTable(Id)上的自動索引」
SQLite warning (284): automatic index on MyTable(Id)
我已經看了架構MyTable的,和ID指定作爲主鍵,就像這樣:
CREATE TABLE MyTable (Id varchar(50) collate nocase primary key not null,
Name varchar(50) not null,
(etc)
我以爲SQLite爲主鍵創建了索引,那爲什麼要創建另一個?
此外,在一個相關的說明,我得到了很多關於子查詢的自動索引警告。例如,在查詢:
SELECT MyTable.Id, MyTable.Name, Amount
FROM MyTable
LEFT JOIN (SELECT ArrangementId, Amount, AgreementDate FROM SubTable
JOIN Organisations ON Organisations.Id = SubTable.OrganisationId AND Organisations.Direction = 1
) AS MyJoin ON MyJoin.ArrangementId = MyTable.Id
ORDER BY Id
凡
MyTable has Id as the primary key
Organisations has Id as the primary key
SubTable has a unique index on ArrangementId, OrganisationId
EXPLAIN的查詢產生查詢計劃:
1|0|0|SCAN TABLE SubTable
1|1|1|SEARCH TABLE Organisations USING INDEX sqlite_autoindex_Organisations_1 (Id=?)
0|0|0|SCAN TABLE Arrangements USING INDEX sqlite_autoindex_Arrangements_1
0|1|1|SEARCH SUBQUERY 1 AS MyJoin USING AUTOMATIC COVERING INDEX (ArrangementId=?)
我想SQLite是沒有足夠的智慧認識到,子查詢不需要進入臨時表?
是否有任何重寫查詢的方法,以避免子查詢?
出於好奇,你爲什麼要使用VARCHAR爲您的主鍵?這將導致列值存儲兩次,一次在b-tree中,一次在表中。我建議使用整數主鍵並將文本存儲在單獨的列中。如果需要,您仍然可以在其他列上設置唯一的約束。 – seairth
你是說在文本上創建唯一索引所需的空間比以文本作爲主鍵的空間要少? –
不,在這兩種情況下,最後都會出現一個包含文本副本的B樹。我更關心使用varchar作爲主鍵。在回答中繼續發表評論... – seairth