我们有一个表,该表具有由三个字段组成的复合主键(在MySQL 5.1中是这样)。 该表上每秒有近200个插入和200个选择,并且表的大小约为100万行,并且还在不断增加。

我的问题是:"复合主键"是否会降低此表上"插入和选择"的性能?

我应该使用简单的自动递增INT ID字段而不是Composite Primary Key吗? (我认为答案与MySQL处理多列索引的方式非常相关)

INSERT和UPDATE性能几乎没有变化:(INT)和(INT, INT)键几乎相同。

复合PRIMARY KEY的SELECT性能取决于许多因素。

如果您的表是InnoDB,则该表隐式聚集在PRIMARY KEY值上。

这意味着如果两个值都包含关键字,则搜索这两个值将更快:不需要额外的关键字查找。

假设您的查询是这样的:

SELECT  *
FROM    mytable
WHERE   col1 = @value1
AND col2 = @value2

表格的布局是这样的:

,引擎将只需要在表本身中查找确切的键值。

如果您使用自动递增字段作为伪造ID:

,则引擎首先需要在索引ix_mytable_col1_col2中查找(col1, col2)的值,从索引中检索行指针(id的值),并在表中通过id进行另一次查找本身。

但是,对于MyISAM表,这没有什么区别,因为MyISAM表是堆组织的,并且行指针只是文件偏移量。

在这两种情况下,将创建相同的索引(对于PRIMARY KEY或UNIQUE KEY)并将以相同的方式使用。

如果是InnoDB,则复合主键将包含在每个二级索引的每个条目中。

这意味着

您的二级索引将占用这些列+主键中所有列的空间

如果所有必需的列都包含在二级索引+ pk中,则可以使用二级索引作为覆盖索引

这些当然分别是缺点和优点。

复合主键不一定是坏的,有时它们可??能确实有用,因为InnoDB对其进行了聚类-这意味着使用PK操作(与非聚簇索引相比所需的IO少得多)可以满足PK上的(磁盘绑定)范围扫描。

当然,如果您在其他表中有外键,则外键会更宽,并且需要包含主表中的整个键。

但是总的来说,我会说不。具有复合主键本身不会引起问题。但是,如果拥有一个"大"主键(例如,大varchars),那可能胜过集群和能够使用覆盖索引的优势。

这是否意味着如果我在(reviewId,userId)上具有主键,在(userId)上具有辅助索引,则该索引将在内部包含(userId,reviewId,userId)?

@Benjamin是的,你说得对。 它在这里dev.mysql.com/doc/refman/5.7/en/innodb-index-types.html以及在这本书中都有明确说明shop.oreilly.com/product/0636920022343.do

使用该复合主键会使SELECT速度稍慢一些,尽管效果几乎可以忽略不计,也不用担心。

完全索引那些列会使您的INSERT变慢,并且您当然在做足够的INSERT来担心它。如果它是一个MyISAM表(其中INSERT锁定了该表),则比它是InnoDB表时,更值得关注。如果通过使用auto_increment主键可以使这些列保持未索引状态,则可以从更改中受益。但是,如果仍然需要对这三列进行索引(例如,如果您需要对它们的组合强制执行唯一性),那么它就不会对性能产生任何影响。