我运行了比较使用MySQL 5.6将行插入空表。
每个表都包含一个由AUTO_INCREMENT串行递增的列(升序)和一对列( random_1 , random_2 )接收随机,唯一的数字。
在第一个测试中,升序是PRIMARY KEY,( random_1 , random_2 )是KEY。在第二个测试中,( random_1 , random_2 )为PRIMARY KEY,升序为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%。任何人都可以猜测为什么?
答案 0 :(得分:2)
主键通常用作实际存储数据的序列。如果主键递增,则简单地附加数据。如果主键是随机的,那么这意味着必须移动现有数据以使新行进入正确的序列。基本(非主键)索引的内容通常要轻得多,并且可以以更少的开销更快地移动。
我知道其他DBMS也是如此;我冒昧地猜测MySQL在这方面的工作方式类似。
<强>更新强>
正如@BillKarwin在下面的评论中所述,这一理论不适用于MyISAM表。作为后续理论,我将在下面提到@KevinPostlewaite的答案(他已删除),问题是PRIMARY KEY上缺少AUTO_INCREMENT - 必须是唯一的。使用AUTO_INCREMENT,可以更容易地确定值是唯一的,因为它们保证是增量的。使用随机值,可能需要一些时间来实际执行索引以进行此确定。