可以说我有表之间“表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