MySQL中有两个单列索引还是一个两个列索引?


113

我面临以下问题,我不确定什么是最佳实践。

考虑下表(该表会变大):

id PK | Giver_id FK | FK | 日期

我正在使用InnoDB,据我了解,它会自动为两个外键列创建索引。但是,在需要匹配以下特定组合的情况下,我还会做很多查询:

SELECT...WHERE giver_id = x AND recipient_id = t

每个这样的组合在表中将是唯一的。

在这些列上添加双列索引有什么好处,还是理论上两个单独的索引足够/相同?


1
如果两列的组合是唯一的,则可以创建具有独特功能的两列索引,这不仅可以提高查询速度,还可以增加表的一致性。
sguven

“ MySQL可以将多列索引用于测试索引中所有列的查询,或仅测试第一列,前两列,前三列等等的查询。如果在右侧指定列按照索引定义的顺序,单个组合索引可以加快对同一张表的几种查询。” - 多列索引
AlikElzin-kilaka

在@ user1585784上推断;如果这两列的组合是唯一的,我认为应该为它们使用唯一的键。实际上,如果要在数据库级别实施唯一性,则唯一键是最简单的方法……
Erk

Answers:


132

如果您有两个单列索引,那么在您的示例中将只使用其中一个。

如果您有一个包含两列的索引,则查询可能会更快(应该进行测量)。两列索引也可以用作单列索引,但仅适用于首先列出的列。

有时在(A,B)上有一个索引,在(B)上有另一个索引可能会很有用。这使得使用任一列或两列的查询都很快,但是当然也使用了更多的磁盘空间。

选择索引时,还需要考虑对插入,删除和更新的影响。更多索引=更新速度较慢。


1
“ MySQL可以将多列索引用于测试索引中所有列的查询,或仅测试第一列,前两列,前三列等等的查询。如果在右侧指定列按照索引定义的顺序,单个组合索引可以加快对同一张表的几种查询。” - 多列索引
AlikElzin-kilaka

33

覆盖指数如下:

ALTER TABLE your_table ADD INDEX (giver_id, recipient_id);

...将意味着如果查询中提到的索引可以使用giver_id,或组合giver_idrecipient_id。请注意,索引标准是基于最左侧的-仅引用的查询recipient_id将无法使用我提供的语句中的覆盖索引。

另外,MySQL每个SELECT只能使用一个索引,因此覆盖索引将是优化查询的最佳方法。


9
MySQL can only use one index per SELECT这不再是事实,如果您编辑了要更新的答案,那就太好了。
Davor

您介意解释为什么覆盖索引不能被使用recipient_id吗?
伊沃·佩雷拉

2
@IvoPereira MySQL中的多列索引使您可以从左到右使用索引中的所有字段。例如,如果您有一个,INDEX (col1, col2, col3, col4)则该索引将用于带有WHERE诸如col1 = 'A'col1 = 'A' AND col2 = 'B'或的子句的搜索col1 = 'A' AND col2 ='B' AND col3 = 'C' AND col4 = 'D',但是该特定索引将不用于诸如WHERE col2 = 'B'或的任何东西,WHERE col3 = 'C' AND col4 = 'D'因为搜索字段在索引定义中没有保留最多。您将不得不添加其他索引来覆盖这些字段。
Slicktrick

“每个SELECT一个索引”,对于mariadb 10.1仍然适用吗?
oldboy '18

1
@Anthony:不,请看上面Davor的评论。
kapad

4

如果外键索引之一已经具有很高的选择性,那么数据库引擎应将那个用于您指定的查询。大多数数据库引擎使用某种启发式方法能够在那种情况下选择最佳索引。如果两个索引本身都不是高度选择性的,那么添加基于两个键构建的索引可能确实有意义,因为您说您将大量使用该类型的查询。

要考虑的另一件事是,是否可以消除此表中的PK字段并在giver_idrecipient_id字段上定义主键索引。您说组合是唯一的,因此可能会起作用(鉴于许多其他条件,只有您可以回答)。不过,通常来说,我认为增加的复杂性不值得麻烦。


谢谢马克,关键之一确实是非常有选择性的,所以应该没问题。我选择将两个(自动)索引保留在适当的位置,并观察它随着时间的推移如何运行。我还考虑了一个组合的Giver:Recipient主键,但是由于每个字段也需要单独进行搜索,因此只会增加php开销。同样,新键将是一个(较长)字符串,而不是一个(较短)整数。
汤姆(Tom)2010年

2

要考虑的另一件事是,这两种方法的性能特征都将基于数据集的大小和基数。您可能会发现2列索引仅在某个数据集大小阈值或相反的情况下才注意到更高的性能。没有什么可以替代您实际情况下的性能指标。


您能否链接到一些与此相关的文档。谢谢。
kapad
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.