2013-04-07 70 views
0

我有我目前定義如下的表:我應該使用多列索引還是兩列1列?

CREATE TABLE pairs ( 
id INTEGER PRIMARY KEY, 
p1 INTEGER, 
p2 INTEGER, 
r INTEGER, 
UNIQUE(p1, p2) ON CONFLICT IGNORE, 
FOREIGN KEY (p1) REFERENCES points(id), 
FOREIGN KEY (p2) REFERENCES points(id) 
) 

之後,它填充有千兆字節的數據。現在我需要做很多選擇的正是這樣:

SELECT id, r FROM pairs WHERE p1 = 666 OR p2 = 666 

所以,問題是:我應該創建什麼索引,以加快這一選擇?

CREATE INDEX p1_index ON pairs(p1) 
CREATE INDEX p2_index ON pairs(p2) 

或可能

CREATE UNIQUE INDEX p_index ON pairs(p1, p2) 

或者甚至可能兩者兼而有之? (併爲他們購買新的硬盤)。 SQLite3不會自動爲多列上的UNIQUE約束創建索引。

回答

2

由於您使用OR條件,我會去與多個索引。如果這是一個AND條件,那麼多列索引會更好。

對於OR條件: 優化程序將開始查看其中一個索引,找到一個匹配並抓取該行。另一個索引只在與第一個索引不匹配時才被查看。 在多處理器系統上,兩個索引都將(應該)並行掃描。太棒了,對吧?

對於AND條件: 如果有兩個索引可用,優化器將不得不查看它們,合併兩個索引掃描的輸出,然後從基表中獲取結果。這可能會變得很昂貴。在這裏,多列索引本來就很棒。

但是,再次,優化器可能會根據可用的表和索引統計信息選擇不同的路徑。

希望這會有所幫助。

+0

不確定舊的sqlite3是否使用線程。 – 2013-04-07 08:18:29

+0

SQLite不使用線程。 – 2013-04-07 09:58:23

1

使用EXPLAIN QUERY PLAN檢查是否使用索引。

爲了您的示例查詢,無論是單列索引將用於:

> EXPLAIN QUERY PLAN SELECT id, r FROM pairs WHERE p1 = 666 OR p2 = 666; 
0|0|0|SEARCH TABLE pairs USING INDEX p1_index (p1=?) (~10 rows) 
0|0|0|SEARCH TABLE pairs USING INDEX p2_index (p2=?) (~10 rows) 

多列索引(你已經因爲獨特的約束)將被使用,如果一個查詢單記錄需要兩個柱:

> EXPLAIN QUERY PLAN SELECT id, r FROM pairs WHERE p1 = 666 AND p2 = 666; 
0|0|0|SEARCH TABLE pairs USING INDEX sqlite_autoindex_pairs_1 (p1=? AND p2=?) (~1 rows) 

然而,一個多列索引也可以用於查找它的第一列(或多個):

> DROP INDEX p1_index; 
> EXPLAIN QUERY PLAN SELECT id, r FROM pairs WHERE p1 = 666 OR p2 = 666; 
0|0|0|SEARCH TABLE pairs USING INDEX sqlite_autoindex_pairs_1 (p1=?) (~10 rows) 
0|0|0|SEARCH TABLE pairs USING INDEX p2_index (p2=?) (~10 rows) 

另請參閱文檔:
Query Optimizer Overview,
Query Planning

+0

當我使用.indices查看我擁有的索引時,它顯示主鍵列的自動索引,但沒有UNIQUE約束的索引。我認爲它只是在列描述中定義UNIQUE時才創建索引,而不是作爲單獨的語句。 – 2013-04-07 11:15:44

+0

'。indices'不顯示內部索引(例如我的示例中的'sqlite_autoindex_pairs_1')。 – 2013-04-07 12:24:58