我运行了比较使用MySQL 5.6将行插入空表 .
每个表包含一个由AUTO_INCREMENT串行递增的列( ascending ),以及一对接收随机唯一数字的列( random_1 ,_ random_2 ) .
在第一个测试中, ascending 是PRIMARY KEY,( random_1 , random_2 )是KEY . 在第二个测试中,( random_1 ,_ random_2 )是PRIMARY KEY, ascending 是KEY .
CREATE TABLE clh_test_pk_auto_increment (
ascending_pk BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, -- PK
random_ak_1 BIGINT UNSIGNED NOT NULL, -- AK1
random_ak_2 BIGINT UNSIGNED, -- AK2
payload VARCHAR(40),
PRIMARY KEY ( ascending_pk ),
KEY ( random_ak_1, random_ak_2 )
) ENGINE=MYISAM
AUTO_INCREMENT=1
;
CREATE TABLE clh_test_auto_increment (
ascending_ak BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, -- AK
random_pk_1 BIGINT UNSIGNED NOT NULL, -- PK1
random_pk_2 BIGINT UNSIGNED, -- PK2
payload VARCHAR(40),
PRIMARY KEY ( random_pk_1, random_pk_2 ),
KEY ( ascending_ak )
) ENGINE=MYISAM
AUTO_INCREMENT=1
;
一致地,第二个测试(其中自动增量列不是PRIMARY KEY)运行得稍快 - 5-6% . 任何人都可以猜测为什么?
1 回答
主键通常用作实际存储数据的序列 . 如果主键递增,则简单地附加数据 . 如果主键是随机的,那么这意味着必须移动现有数据以使新行进入正确的序列 . 基本(非主键)索引的内容通常要轻得多,并且可以以更少的开销更快地移动 .
我知道其他DBMS也是如此;我冒昧地猜测MySQL在这方面的工作方式类似 .
UPDATE
正如@BillKarwin在下面的评论中所述,这一理论不适用于MyISAM表 . 作为后续理论,我将在下面提到@KevinPostlewaite的答案(他已删除),问题是PRIMARY KEY上缺少AUTO_INCREMENT - 必须是唯一的 . 使用AUTO_INCREMENT,可以更容易地确定值是唯一的,因为它们保证是增量的 . 使用随机值,可能需要一些时间来实际遍历索引以进行此确定 .