MySQL中复合主键性能的缺点
我们有一个包含三个字段的组合主键(在MySQL 5.1中)。 在这个表上每秒钟有200个插入和200个select,并且表的大小约为100万行,并且正在增加。
我的问题是:“复合主键”是否会降低此表上插入和select的性能?
我应该使用简单的自动增加INT ID字段而不是复合主键吗? (我想这个答案和MySQL在多列上处理索引的方式非常相关)
INSERT
和UPDATE
性能差别不大: (INT)
和(INT, INT)
键几乎相同。
复合PRIMARY KEY
SELECT
性能取决于许多因素。
如果你的表是InnoDB
,那么这个表隐式地聚集在PRIMARY KEY
值上。
这意味着,如果两个值都包含关键字,则对两个值的search将会更快:不需要额外的密钥查找。
假设你的查询是这样的:
SELECT * FROM mytable WHERE col1 = @value1 AND col2 = @value2
和表格布局是这样的:
CREATE TABLE mytable ( col1 INT NOT NULL, col2 INT NOT NULL, data VARCHAR(200) NOT NULL, PRIMARY KEY pk_mytable (col1, col2) ) ENGINE=InnoDB
,引擎只需要在表格中查找确切的键值。
如果您使用自动增量字段作为伪造ID:
CREATE TABLE mytable ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, col1 INT NOT NULL, col2 INT NOT NULL, data VARCHAR(200) NOT NULL, UNIQUE KEY ix_mytable_col1_col2 (col1, col2) ) ENGINE=InnoDB
那么引擎将首先需要查找索引ix_mytable_col1_col2
的(col1, col2)
的值,从索引( id
的值(col1, col2)
中检索行指针,并在表中通过id
进行另一个查找。
但是,对于MyISAM
表而言,这没什么区别,因为MyISAM
表是堆组织的,行指针只是文件偏移量。
在这两种情况下,都会创build一个相同的索引(对于PRIMARY KEY
或UNIQUE KEY
),并以相同的方式使用。
如果是InnoDB,则复合主键将包含在每个二级索引中的每个条目中。
这意味着
- 您的二级索引将占用与这些列+主键中的所有列一样多的空间
- 如果所有需要的列都包含在辅助索引+ pk中,则可以使用辅助索引作为覆盖索引
这些当然分别是缺点和优点。
复合主键不一定是坏的,有时它们可以真正有帮助,因为InnoDB将它们聚集在一起 – 这意味着使用less得多的IO操作就可以满足对PK的(磁盘绑定)范围扫描,这比非聚集索引。
当然,如果你在其他表中有外键,它们也会更宽,并且需要包含主表中的整个键。
但是总的来说,我会说平衡,不。 有一个复合主键本身不会引起问题。 然而,如果拥有“大”主键(例如大variables),则可能会超过聚类的优势,并且能够使用覆盖索引。
- 有了这个复合主键减慢
SELECT
一点点,虽然效果几乎可以忽略不计,不值得担心。 - 把这些列索引放慢你的
INSERT
,你肯定做了足够的INSERT
s来担心它。 如果它是一个MyISAM表,INSERT
locking表,比InnoDB表更重要。 如果通过使用auto_increment主键,您可以将这些列保持未索引,您将从中受益。 如果你仍然需要保留这三列的索引,但是(例如,如果你需要在它们的组合上强制执行唯一性),那么对于你来说在性能方面是不会做任何事情的。