我们有一个包含三个字段的复合主键的表(它在 MySQL 5.1 中)。该表每秒有近 200 次插入和 200 次选择,表的大小约为 100 万行,并且还在增加。
我的问题是:“复合主键”是否会降低该表上插入和选择的性能?
我应该使用简单的自动递增 INT ID 字段而不是复合主键吗?(我认为答案与 MySQL 处理多列索引的方式非常相关)
我们有一个包含三个字段的复合主键的表(它在 MySQL 5.1 中)。该表每秒有近 200 次插入和 200 次选择,表的大小约为 100 万行,并且还在增加。
我的问题是:“复合主键”是否会降低该表上插入和选择的性能?
我应该使用简单的自动递增 INT ID 字段而不是复合主键吗?(我认为答案与 MySQL 处理多列索引的方式非常相关)
INSERT
和性能变化不大:和键UPDATE
几乎相同。(INT)
(INT, INT)
SELECT
复合材料的性能PRIMARY KEY
取决于许多因素。
如果您的表是InnoDB
,则该表隐含地聚集在该PRIMARY KEY
值上。
这意味着如果两个值都包含键,则搜索这两个值会更快:不需要额外的键查找。
假设您的查询是这样的:
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
,那么引擎首先需要在索引中查找 的值,(col1, col2)
从索引ix_mytable_col1_col2
中检索行指针( 的值)并在表本身中id
进行另一次查找。id
然而,对于MyISAM
表来说,这没有什么区别,因为MyISAM
表是堆组织的,而行指针只是文件偏移量。
在这两种情况下,将创建相同的索引(forPRIMARY KEY
或 for UNIQUE KEY
)并以相同的方式使用。
如果是 InnoDB,则复合主键将包含在每个二级索引的每个条目中。
这意味着
当然,这些分别是缺点和优点。
复合主键不一定是坏的,有时它们真的很有帮助,因为 InnoDB 将它们聚集在一起——这意味着可以使用比非聚集索引所需的少得多的 IO 操作来满足对 PK 的(磁盘绑定)范围扫描.
当然,如果您在其他表中有外键,它们会更宽,并且它们需要包含主表中的整个键。
但总的来说,我会说不。拥有复合主键本身不会导致问题。但是,如果这超过了集群和能够使用覆盖索引的优势,那么拥有一个“大”主键(例如大 varchars)可能会起作用。
SELECT
一点,尽管效果几乎可以忽略不计,不值得担心。INSERT
的 s 速度,而且您肯定已经做了足够多INSERT
的 s 来担心它。如果它是一个INSERT
锁定表的 MyISAM 表,这比它是一个 InnoDB 表更令人担忧。如果通过使用 auto_increment 主键,您可以使这些列不被索引,您将从更改中受益。但是,如果您仍然需要对这三列进行索引(例如,如果您需要对它们的组合强制唯一性),那么它对您的性能没有任何帮助。