2010-02-28 163 views
65

我面臨以下問題,我不確定最佳做法。MySQL中的兩個單列索引與一個兩列索引?

考慮下表(它會變大):

id PK | giver_id FK | recipient_id FK | date

我使用InnoDB,據我所知,它爲兩個外鍵列自動創建索引。不過,我也會做很多的查詢,我需要匹配一個特定的組合:

SELECT...WHERE giver_id = x AND recipient_id = t

每個這樣的組合在表中都是唯一的。

在這些列上添加兩列索引是否有任何好處,或者理論上兩個單獨索引是否足夠/相同?

回答

76

如果您有兩個單列索引,您的示例中只會使用其中的一個索引。

如果您有兩列的索引,查詢可能會更快(您應該測量)。雙列索引也可以用作單列索引,但僅限列出的列。

有時在(B)上有(A,B)和另一個索引的索引是有用的。這使查詢使用任何一個或兩個列的速度很快,但當然也會使用更多的磁盤空間。

選擇索引時,還需要考慮插入,刪除和更新的效果。更多索引=更新較慢。

21

覆蓋索引,如:

ALTER TABLE your_table ADD INDEX (giver_id, recipient_id); 

...將意味着如果查詢簡稱giver_id,或giver_idrecipient_id組合索引都可以使用。請注意,索引標準是最基礎的 - 僅提及recipient_id的查詢將無法在我提供的聲明中使用覆蓋索引。

此外,MySQL每個SELECT只能使用一個索引,因此覆蓋索引是優化查詢的最佳方式。

+4

'MySQL只能使用每個SELECT一個索引'這不再是真的,如果您編輯了要更新的答案,那將會很好。 – Davor 2015-09-22 21:25:42

+0

你是否介意解釋爲什麼覆蓋索引不能被'recipient_id'使用? – 2015-10-05 15:50:50

+2

@IvoPereira MySQL中的多列索引使您可以使用索引中的所有字段,從左到右。例如,如果你有一個'INDEX(col1,col2,col3,col4)',那麼這個索引將用於'WHERE'子句的搜索,比如'col1 ='A''或'col1 ='A'AND col2 = 'B'或'col1 ='A'和col2 ='B'和col3 ='C'和col4 ='D',但這個特定的索引不會用於像'WHERE col2 ='B' '或'WHERE col3 ='C'和col4 ='D',因爲搜索字段在索引定義中不是最多的。您將不得不添加額外的索引來覆蓋這些字段。 – Slicktrick 2017-02-15 17:43:14

3

如果其中一個外鍵索引已經非常有選擇性,那麼數據庫引擎應該使用那個指定的查詢。大多數數據庫引擎都使用某種啓發式方法來在這種情況下選擇最佳索引。如果兩個索引本身都不具有高度的選擇性,那麼添加構建在兩個鍵上的索引可能是有意義的,因爲您說你會使用這種類型的查詢。

要考慮的另一件事是,如果您可以消除此表中的PK字段並在giver_idrecipient_id字段中定義主鍵索引。你說這個組合是獨一無二的,所以這可能會起作用(鑑於許多其他條件,只有你可以回答)。不過,通常情況下,我認爲增加的額外複雜性並不值得一提。

+0

謝謝馬克,其中一個鍵確實非常有選擇性,所以它應該沒問題。我選擇保留這兩個(自動)索引,並查看它隨着時間的推移如何執行。我也想過一個聯合的提供者:接收者主鍵,但是每個字段也需要單獨搜索,它只會增加php的開銷。此外,新密鑰將是(更長)字符串,而不是(更短)整數。 – Tom 2010-02-28 04:35:27

0

要考慮的另一件事是兩種方法的性能特徵將基於數據集的大小和基數。您可能會發現,2列索引僅在某個數據集大小閾值時纔會注意到性能更高,或者恰恰相反。沒有任何東西可以替代您確切場景的性能指標。

相關問題