主键索引和唯一性索引的区别与联系

主键索引和唯一性索引的区别与联系

主键索引(Primary Key Index)和唯一性索(Unique Index)引都是索引,但它们在功能和特性上有明确的区别。

简单来说:主键索引是一种特殊的唯一性索引,它附带了更多的约束和语义。


核心总结

  • 主键索引 :是为主键约束自动创建的索引。它的核心是实现主键约束 ,即保证行的唯一标识符。一个表只能有一个
  • 唯一性索引 :是为唯一性约束自动创建的索引,或者可以手动创建。它的核心是加速查询并保证数据唯一性一个表可以有多个

详细对比

下表详细对比了它们的区别:

特性 主键索引 唯一性索引
创建方式 通过定义 主键约束 自动创建。 1. 通过定义 唯一性约束 自动创建。 2. 可以直接使用 CREATE UNIQUE INDEX 语句手动创建。
数量限制 一个表只能有一个主键索引。 一个表可以有多个唯一性索引。
是否允许NULL值 绝对不允许。主键列必须非空。 允许NULL值。具体规则与唯一性约束一致:大多数DBMS(如MySQL)允许多个NULL,因为NULL不相等;少数(如SQL Server)只允许一个NULL。
索引类型(默认) 在多数数据库(如 SQL Server, MySQL的InnoDB )中,主键索引默认为 聚集索引。这意味着表数据本身会按照主键的顺序物理存储。 默认为非聚集索引。索引和数据是分开存储的,索引中只包含指向数据行的指针。
逻辑关联 与表的实体完整性紧密绑定,是逻辑设计的核心。通常作为外键引用的目标。 更多是性能优化和数据完整性的工具,体现业务规则。
是否可以被其他表引用为外键 ,这是主键的主要用途之一。 可以,但不太常见。虽然数据库技术上允许外键引用唯一性索引(而不仅仅是主键),但在逻辑设计中,这通常不是最佳实践。

关键点深入探讨:聚集索引

这是两者最核心的物理区别。

  • 主键索引(通常为聚集索引) :想象一本书的目录。在聚集索引中,数据页就是书的页码本身,内容严格按照页码(主键)顺序排列。当你通过主键查找时,数据库能直接定位到数据所在的数据页,效率极高。因为数据物理上只能有一种排序方式,所以一个表只能有一个聚集索引。

  • 唯一性索引(通常为非聚集索引) :想象一本书末尾的索引 (比如,术语索引)。索引项(如"数据库")后面跟的是它出现的页码列表,而不是内容本身。你需要先查这个"索引",找到页码,再根据页码去对应的页查找具体内容。非聚集索引和数据的物理顺序无关,因此一个表可以创建很多个。

重要例外 :在有些数据库如 Oracle 中,默认情况下,索引组织表(IOT)才将主键作为聚集索引,而普通表的存储是堆表,主键索引也是非聚集的。但 SQL ServerMySQL(InnoDB) 的默认行为是主键即聚集索引。

举例说明

还是以 用户表 (Users) 为例:

sql 复制代码
CREATE TABLE Users (
    user_id INT PRIMARY KEY AUTO_INCREMENT,  -- 主键约束 -> 自动创建主键索引(聚集索引)
    username VARCHAR(50) UNIQUE,             -- 唯一约束 -> 自动创建唯一性索引(非聚集索引)
    email VARCHAR(100),
    phone VARCHAR(20)
);

-- 也可以手动为 email 创建一个唯一性索引,即使没有唯一约束
CREATE UNIQUE INDEX idx_unique_email ON Users(email);

在这个表中:

  1. 主键索引 (PRIMARY) :建立在 user_id 上。表的数据行在磁盘上大致是按照 user_id 从小到大存储的。
  2. 唯一性索引 (username) :自动为 username 列创建。它是一个独立的结构,包含排序后的 username 和对应的 user_id(主键值)。
  3. 唯一性索引 (idx_unique_email) :我们手动为 email 创建,功能上和自动创建的没有区别。

查询过程对比

  • SELECT * FROM Users WHERE user_id = 5;
    • 数据库使用聚集索引(主键索引),可以直接找到存储该行数据的磁盘位置,效率最高。
  • SELECT * FROM Users WHERE username = 'alice';
    • 数据库先使用非聚集索引(username上的唯一索引) 找到 username 为 'alice' 的条目,从中取出对应的 user_id(比如是 5)。
    • 然后再用这个 user_id = 5聚集索引(主键索引) 中进行一次查找(这个过程称为 书签查找回表),最终拿到所有数据。

总结与选择

场景 选择
需要唯一标识每一行,并希望数据按此顺序物理存储以获得最佳主键查询性能。 使用主键约束(自动创建主键索引)
需要确保某个业务字段(如邮箱、手机号)的唯一性,并加速按该字段的查询。 使用唯一性约束手动创建唯一性索引
表中已经有一个自然的主键(如user_id),但还有另一组列需要唯一性(如项目ID成员ID组合唯一)。 为这组列创建唯一性索引

简单记住:主键索引是"唯一标识+数据物理顺序",而唯一性索引是"保证唯一+加速查询"。

相关推荐
花菜会噎住23 天前
MySQL 高级特性与性能优化:深入理解函数、视图、存储过程、触发器
android·mysql·函数·索引·视图
流火无心1 个月前
mysql索引优化实战
mysql·优化·索引
老友@1 个月前
MySQL 索引失效全解析与优化指南
数据库·mysql·索引失效·索引
流火无心1 个月前
mysql索引 底层数据结构与算法
数据结构·mysql·索引
core5122 个月前
elk快速部署、集成、调优
elk·springboot·kibana·索引·查询
全栈小52 个月前
【数据库】使用Sql Server创建索引优化查询速度,一般2万多数据后,通过非索引时间字段排序查询出现超时情况
数据库·sql server·索引·查询优化
笑衬人心。2 个月前
MySQL 索引失效的场景与原因
数据库·mysql·索引
不修×蝙蝠2 个月前
MySQL 全详解:从入门到精通的实战指南
数据库·mysql·索引·最左前缀
之之为知知2 个月前
Chromadb 1.0.15 索引全解析:从原理到实战的向量检索优化指南
人工智能·深度学习·机器学习·大模型·索引·向量数据库·chromadb