首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >MySQL 普通索引 vs 唯一索引:不只是“能不能重复”这么简单

MySQL 普通索引 vs 唯一索引:不只是“能不能重复”这么简单

作者头像
沈宥
发布2026-01-08 10:49:03
发布2026-01-08 10:49:03
4590
举报

一、定义层面的区别:查询工具 vs 数据规则

1. 普通索引(INDEX):纯粹的访问路径优化

从 InnoDB 的角度看,普通索引的职责非常单一:

为某个访问模式提供一条更低成本的查找路径

CREATE INDEX idx_xxx ON t(col);

其核心特征是:

  • 只参与查询优化器的成本计算
  • 不参与任何数据合法性判断
  • 不承担数据正确性责任

换句话说:

**普通索引解决的是“怎么更快读到数据”,而不是“这份数据对不对”**。


2. 唯一索引(UNIQUE):索引 + 约束的复合体

CREATEUNIQUE INDEX uk_xxx ON t(col);

在 InnoDB 内部,唯一索引多承担了一层职责:

  • 在写入路径中
  • 作为 唯一性约束(Constraint) 执行校验

也就是说:

**UNIQUE 是一种“参与写入流程的索引”**。

从架构角度看,这意味着:

  • 数据一致性下沉到数据库层
  • 应用侧不再是唯一性判断的最终裁判

3. 定义层面对比总结

维度

INDEX

UNIQUE

是否建立 B+Tree

是否约束数据

是否参与写入校验

是否承担数据一致性

**UNIQUE 的本质不是“更严格的索引”,而是“数据库层的数据规则”**。


二、数据层面的差异:数据责任到底交给谁

1. 普通索引:数据库对数据正确性“保持沉默”

当某字段仅有普通索引时:

INSERTINTO t(col) VALUES ('A');

INSERTINTO t(col) VALUES ('A');

在数据库视角:

  • 数据完全合法
  • 是否重复不在其职责范围内

这意味着:

  • 唯一性完全依赖应用逻辑
  • 并发下极易写穿

从 DBA 视角看,这类表的风险是:

**数据错误不是“偶发 Bug”,而是“结构性必然”**。


2. 唯一索引:数据库成为一致性仲裁者

当字段被 UNIQUE 约束:

INSERTINTO t(col) VALUES ('A');

INSERTINTO t(col) VALUES ('A');

-- Duplicate entry

InnoDB 在写入路径中完成:

  • 索引级别的存在性校验
  • 并发安全的唯一性保证

这意味着:

  • 一致性不依赖代码
  • 不依赖事务隔离级别
  • 不依赖业务方是否写对逻辑

UNIQUE 是数据库参与业务正确性的最小、也是最可靠方式


3. NULL 的语义

在 MySQL 中:

  • UNIQUE 允许多个 NULL
  • 因为 NULL ≠ NULL

这在 DBA 设计阶段非常关键:

  • 如果业务语义是“必须有值且唯一”
  • 必须:<span>UNIQUE + NOT NULL</span>

否则:

表结构与业务语义天然不一致


三、执行与性能层面:读写路径的真实差异

1. 查询路径:差异极小,不是决策点

从执行计划角度看:

  • INDEX 与 UNIQUE 都是二级索引
  • 都是 B+Tree
  • 查询复杂度一致

优化器层面:

  • UNIQUE 可推断 <span>= 条件</span> 最多返回一行
  • 可能提前结束扫描

但在绝大多数 OLTP 场景下:

查询性能差异可以忽略,不应作为选型依据


2. 写入路径:这是 DBA 关注的核心差异

普通索引写入路径
  1. 插入记录
  2. 更新索引页
  3. 提交
唯一索引写入路径
  1. 在索引中探测是否存在
  2. 加锁(防并发冲突)
  3. 校验唯一性
  4. 插入记录
  5. 更新索引页

这意味着:

  • UNIQUE 写入路径更长
  • 热点 key 下锁竞争更明显

但从架构视角:

这是为“数据绝对正确”付出的合理成本


3. 并发模型下的根本差异

场景

INDEX

UNIQUE

并发写入

可能写穿

强一致

幂等支持

需业务实现

数据库天然支持

回放 / 重试

高风险

安全

这也是为什么在:

  • 订单号
  • 交易号
  • 账户号

这类字段上,不用 UNIQUE 基本等同于架构缺陷


四、与 PRIMARY KEY 的关系:层级与职责划分

从 DBA 视角,三者职责清晰分层:

  • PRIMARY KEY:行身份
  • UNIQUE:业务规则
  • INDEX:访问路径

1. PRIMARY KEY 的本质

PRIMARY KEY = 唯一 + 非空 + 聚簇

它承担的是:

  • 行的物理组织方式
  • 表级身份标识

不应滥用为业务约束。


2. 三者关系总结

类型

唯一

NULL

角色

PRIMARY KEY

行身份

UNIQUE

业务规则

INDEX

性能工具


五、同字段同时建 UNIQUE + INDEX

ADDUNIQUE INDEX uk_col(col);

ADD INDEX idx_col(col);

1. InnoDB 的真实结果

  • 两棵几乎完全相同的 B+Tree
  • 优化器只会选择其中一个

2. 带来的问题

  • 双倍磁盘占用
  • 写入双倍索引维护成本
  • DDL、回滚、扩容复杂度上升

这是一种“功能完全重叠但成本翻倍”的设计错误


六、典型使用场景

1. 必须使用 UNIQUE 的字段

  • 订单号 / 交易号
  • 账户号 / 绑定关系
  • 业务唯一标识

凡是“不能错”的数据,一定要数据库兜底


2. 适合普通索引的字段

  • 状态
  • 时间
  • 枚举类型
  • 维度字段

这些字段:

  • 允许重复
  • 不承载业务规则

七、汇总结论

  1. UNIQUE 是数据规则,不是性能工具
  2. INDEX 只负责快,不负责对
  3. 不要把数据一致性押在应用代码上
  4. 不要重复建索引
  5. PRIMARY KEY、UNIQUE、INDEX 各司其职

一个成熟系统的数据正确性,应该“写死在表结构里”,而不是“祈祷代码不出错”。


本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-12-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 质量工程与测开技术栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、定义层面的区别:查询工具 vs 数据规则
    • 1. 普通索引(INDEX):纯粹的访问路径优化
    • 2. 唯一索引(UNIQUE):索引 + 约束的复合体
    • 3. 定义层面对比总结
    • 二、数据层面的差异:数据责任到底交给谁
      • 1. 普通索引:数据库对数据正确性“保持沉默”
      • 2. 唯一索引:数据库成为一致性仲裁者
      • 3. NULL 的语义
    • 三、执行与性能层面:读写路径的真实差异
      • 1. 查询路径:差异极小,不是决策点
      • 2. 写入路径:这是 DBA 关注的核心差异
      • 3. 并发模型下的根本差异
    • 四、与 PRIMARY KEY 的关系:层级与职责划分
      • 1. PRIMARY KEY 的本质
      • 2. 三者关系总结
    • 五、同字段同时建 UNIQUE + INDEX
      • 1. InnoDB 的真实结果
      • 2. 带来的问题
    • 六、典型使用场景
      • 1. 必须使用 UNIQUE 的字段
      • 2. 适合普通索引的字段
    • 七、汇总结论
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档