如何在MySQL中为多对多连接正确索引链接表?

ser*_*erg 30 mysql indexing many-to-many

假设我在表"table1"和"table2"之间有一个简单的多对多表,它包含两个int字段:"table1-id"和"table2-id".我应该如何索引此链接表?

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

谢谢.

Qua*_*noi 29

这取决于你如何搜索.

如果你这样搜索:

/* 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
Run Code Online (Sandbox Code Playgroud)

那么你需要:

ALTER TABLE table_table ADD CONSTRAINT pk_table1_table2 (table_1, table_2)
Run Code Online (Sandbox Code Playgroud)

在这种情况下,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
Run Code Online (Sandbox Code Playgroud)

那么你需要:

ALTER TABLE table_table ADD CONSTRAINT pk_table1_table2 (table_2, table_1)
Run Code Online (Sandbox Code Playgroud)

由于上述原因.

你这里不需要独立的指数.可以在任何可以使用第一列上的普通索引的地方使用复合索引.如果使用独立索引,则无法有效搜索这两个值:

/* Check if relationship exists between two given values */
SELECT 1
FROM table_table
WHERE table_1 = @id1
  AND table_2 = @id2
Run Code Online (Sandbox Code Playgroud)

对于这样的查询,您需要在两列上至少有一个索引.

为第二个字段添加一个额外的索引永远不会是坏事:

ALTER TABLE table_table ADD CONSTRAINT pk_table1_table2 PRIMARY KEY (table_1, table_2)
CREATE INDEX ix_table2 ON table_table (table_2)
Run Code Online (Sandbox Code Playgroud)

主键将用于搜索on both values和基于值的搜索table_1,其他索引将用于基于值的搜索table_2.

  • 如果你搜索两种方式,你将需要两个索引:一个复合用于PRIMARY KEY,一个用于列,它是PRIMARY KEY中的第二个.它在我的帖子的底部. (3认同)
  • 为了回答我自己的问题,@Quassnoi 建议的单列索引似乎隐含地包含第二列。所以,这只是一个简洁与明确的问题。来源:http://mysql.rjweb.org/doc.php/index_cookbook_mysql#many_to_many_mapping_table (2认同)

dkr*_*etz 5

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

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

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

  • 一个比较技术性的词是“基数”。这意味着该字段有多少个不同的值。在一个极端的高基数下,每个值都是唯一的。另一方面,某些字段可能只有几个不同的值,在这种情况下,索引不会在磁盘读取中节省太多。 (2认同)