40

假设我在表“table1”和“table2”之间有一个简单的多对多表,它由两个 int 字段组成:“table1-id”和“table2-id”。我应该如何索引这个链接表?

我以前只是创建一个复合主索引(table1-id,table2-id),但我读到如果您更改查询中字段的顺序,该索引可能不起作用。那么最佳解决方案是什么 - 为没有主索引的每个字段创建独立索引?

谢谢。

4

3 回答 3

41

这取决于您如何搜索。

如果你这样搜索:

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

于 2009-02-20T21:42:24.730 回答
5

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

但是,您有时可能只有一个或另一个键。如果您有时只有 id_1,那应该是第一个(但您仍然只需要一个索引)。

如果您有时有一个,有时另一个,有时两者都有,您将需要一个具有两个键的索引,以及具有一个字段的第二个(非唯一)索引 - 两个键中更具选择性 - 主复合索引应该从另一个键开始。

于 2009-02-20T22:02:25.243 回答
0

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

因此,多列索引可能仅在第三个查询中有用,因为WHERE table_1 = @id1 AND table_2 = @id2. 如果不使用此类查询,您认为是否值得使用两个单独的单列索引?

于 2011-05-25T23:50:54.273 回答