若表中主键为聚集索引,其他列(如唯一列)是否均为非聚集索引?
关于聚集索引与唯一列索引的疑问解答
首先先看你提供的people表创建语句(注意这里有个小拼写错误:LastNanme应该是LastName):
CREATE TABLE people( personID int, FirstName VARCHAR(255), LastNanme VARCHAR(255), Address VARCHAR(255), City VARCHAR(255), PRIMARY KEY (PERSONID) );
默认情况下,多数主流数据库(比如SQL Server、MySQL InnoDB)会把主键设置为聚集索引——这也是你问题的前提,那我们基于这个场景来拆解问题:
核心结论:其他唯一列并不「必然」全是非聚集索引,但一张表永远只能有一个聚集索引
- 先明确一个关键规则:一张表只能存在一个聚集索引。因为聚集索引的本质是决定了表中数据在磁盘上的物理存储顺序,一张表的数据总不能同时按两种顺序排列吧?所以聚集索引是唯一的。
- 回到你的场景:如果
personID已经是聚集索引,那么:- 当你给其他唯一列(比如给
FirstName加唯一约束,或者新增一个唯一的Email列)创建唯一索引/约束时,数据库默认会创建非聚集索引——这是最常见的使用场景。 - 你没法直接给另一个唯一列加聚集索引,除非先把原主键的聚集属性拿掉(比如把主键改成非聚集索引),之后才能把目标唯一列设为聚集索引。但这么操作后,原来的主键索引就变成了非聚集索引,表中依然只有一个聚集索引。
- 当你给其他唯一列(比如给
举个具体操作例子(以SQL Server为例):
- 先移除原主键的聚集属性:
ALTER TABLE people DROP CONSTRAINT PK_people_personID; ALTER TABLE people ADD CONSTRAINT PK_people_personID PRIMARY KEY NONCLUSTERED (personID);
- 新增唯一列并设置为聚集索引:
ALTER TABLE people ADD COLUMN Email VARCHAR(255) UNIQUE NOT NULL; CREATE CLUSTERED INDEX CI_people_Email ON people(Email);
这时候Email是聚集索引,而personID的主键索引就变成了非聚集索引。
额外小补充
在MySQL的InnoDB引擎里,聚集索引是强制存在的:如果没显式设主键,数据库会自动选第一个非空的唯一列当聚集索引;如果连这样的列都没有,会偷偷创建一个内部自增列作为聚集索引。但不管哪种情况,一张表始终只有一个聚集索引。
内容的提问来源于stack exchange,提问作者Saket khatavkar




