可以說我有表之間「表1」和「表2」是由來自兩個int字段的簡單許多一對多表:「表1-ID」和「表2-ID」。我應該如何索引這個鏈接表?如何正確索引鏈接表在MySQL許多一對多連接?
我以前只是做一個複合主指數(表1-ID,表2-ID),但我看,如果你更改查詢中字段的順序該指數可能無法正常工作。那麼最佳解決方案是什麼 - 爲沒有主索引的每個領域制定獨立索引?
謝謝。
可以說我有表之間「表1」和「表2」是由來自兩個int字段的簡單許多一對多表:「表1-ID」和「表2-ID」。我應該如何索引這個鏈接表?如何正確索引鏈接表在MySQL許多一對多連接?
我以前只是做一個複合主指數(表1-ID,表2-ID),但我看,如果你更改查詢中字段的順序該指數可能無法正常工作。那麼最佳解決方案是什麼 - 爲沒有主索引的每個領域制定獨立索引?
謝謝。
這取決於你如何進行搜索。
如果搜索是這樣的:
/* Given a value from table1, find all related values from table2 */
SELECT *
FROM table1 t1
JOIN table_table tt ON (tt.table_1 = t1.id)
JOIN table2 t2 ON (t2.id = tt.table_2)
WHERE t1.id = @id
,那麼你需要:
ALTER TABLE table_table ADD CONSTRAINT pk_table1_table2 (table_1, table_2)
在這種情況下,table1
將領先NESTED LOOPS
,只有當table1
是第一個索引的索引將是可用。
如果搜索是這樣的:
/* Given a value from table2, find all related values from table1 */
SELECT *
FROM table2 t2
JOIN table_table tt ON (tt.table_2 = t2.id)
JOIN table1 t1 ON (t1.id = tt.table_1)
WHERE t2.id = @id
,那麼你需要:
ALTER TABLE table_table ADD CONSTRAINT pk_table1_table2 (table_2, table_1)
上述原因。
這裏你不需要獨立的索引。可以在任何可以使用第一列的普通索引的地方使用組合索引。如果使用獨立的索引,你將不能爲這兩個值有效地搜索:
/* Check if relationship exists between two given values */
SELECT 1
FROM table_table
WHERE table_1 = @id1
AND table_2 = @id2
對於這樣的查詢,則需要在兩列的至少一個指引。
這是從來沒有壞到有第二場附加指標:
ALTER TABLE table_table ADD CONSTRAINT pk_table1_table2 PRIMARY KEY (table_1, table_2)
CREATE INDEX ix_table2 ON table_table (table_2)
主鍵將被用於搜索on both values
和基於的table_1
值的搜索,更多的索引將被用於基於搜索值爲table_2
。
只要您在查詢中指定了這兩個鍵,則它們在查詢中的順序無關緊要,也不重要在索引中指定它們的順序。
但是,您有時只有一個或另一個密鑰不是不可能的。如果您有時只ID_1,那麼這應該是第一(但你仍然只需要一個索引)。
如果您有時有一個,有時是另一個,有時兩個,您需要一個索引與兩個鍵,第二個(非唯一)索引與一個字段 - 更有選擇性的兩個鍵 - 和主要組合索引應以另一個鍵開始。
@Quassnoi,在您的第一個查詢中,您實際上只使用了tt.table_1
鍵,正如我們從WHERE子句中看到的那樣:WHERE t1.id = @id
。並在第二個查詢 - 只有tt.table_2
。
因此,由於WHERE table_1 = @id1 AND table_2 = @id2
,多列索引可能僅適用於第三個查詢。如果這種查詢不會被使用,那麼您認爲應該使用兩個單獨的一列索引嗎?
感謝您的詳細解答,但如果我搜索兩種方式呢?另外我使用Hibernate,所以我甚至不確定它使用的是哪種方式。 – serg 2009-02-20 22:02:49
如果您搜索兩種方式,您需要兩個索引:PRIMARY KEY的一個組合和PRIMARY KEY中第二個的列的一個平鋪。它在我的帖子底部。 – Quassnoi 2009-02-20 22:05:09