2009-02-20 114 views
23

可以说我有表之间“表1”和“表2”是由来自两个int字段的简单许多一对多表:“表1-ID”和“表2-ID”。我应该如何索引这个链接表?如何正确索引链接表在MySQL许多一对多连接?

我以前只是做一个复合主指数(表1-ID,表2-ID),但我看,如果你更改查询中字段的顺序该指数可能无法正常工作。那么最佳解决方案是什么 - 为没有主索引的每个领域制定独立索引?

谢谢。

回答

25

这取决于你如何进行搜索。

如果搜索是这样的:

/* 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

+0

感谢您的详细解答,但如果我搜索两种方式呢?另外我使用Hibernate,所以我甚至不确定它使用的是哪种方式。 – serg 2009-02-20 22:02:49

+2

如果您搜索两种方式,您需要两个索引:PRIMARY KEY的一个组合和PRIMARY KEY中第二个的列的一个平铺。它在我的帖子底部。 – Quassnoi 2009-02-20 22:05:09

4

只要您在查询中指定了这两个键,则它们在查询中的顺序无关紧要,也不重要在索引中指定它们的顺序。

但是,您有时只有一个或另一个密钥不是不可能的。如果您有时只ID_1,那么这应该是第一(但你仍然只需要一个索引)。

如果您有时有一个,有时是另一个,有时两个,您需要一个索引与两个键,第二个(非唯一)索引与一个字段 - 更有选择性的两个键 - 和主要组合索引应以另一个键开始。

0

@Quassnoi,在您的第一个查询中,您实际上只使用了tt.table_1键,正如我们从WHERE子句中看到的那样:WHERE t1.id = @id。并在第二个查询 - 只有tt.table_2

因此,由于WHERE table_1 = @id1 AND table_2 = @id2,多列索引可能仅适用于第三个查询。如果这种查询不会被使用,那么您认为应该使用两个单独的一列索引吗?