MySQL 的索引类型有哪些?
- 标签:后端、MySQL、数据库
🏛 业务架构师
MySQL 索引类型我按业务承担的角色来分,而不是按数据结构背书:
- 主键索引:行的唯一标识。业务上要用与领域相关的代理键(自增或雪花 ID),保证分布式场景下可追溯、可分库路由;
- 唯一索引:我把它看作业务规则的最后防线,不只是性能工具。手机号注册判重、订单号防重发、一券一码,靠应用层判重永远有并发窗口,唯一索引 + 捕获冲突异常才是闭环——资损类防重必须落在这里;
- 普通索引:为高频查询条件服务,遵循最左前缀,用慢查询数据驱动增删;
- 联合索引:多个业务条件的组合,列顺序由查询模式决定(等值在前、范围在后);
- 前缀索引:长字符串(URL、邮箱)只索引前若干字符,省空间的折中,代价是无法覆盖索引和精确 order by;
- 全文索引:文本检索。但真实项目中中文全文检索我更推荐 ES,MySQL 全文索引的分词和相关性能力有限,只在轻量场景凑合。
架构上的原则:索引是为业务查询服务的成本项,每加一个都要回答"哪个高频查询受益、写放大多少",并且唯一性约束这类"规则型索引"优先级永远高于"性能型索引"——性能慢是体验问题,约束缺失是资损问题。
🏗 系统架构师
我从"按结构、按功能"两个维度给索引分类,面试时讲清分类不如讲清什么场景用什么:
按数据结构:B+ 树索引(InnoDB 默认,等值和范围都强);Hash 索引(Memory 引擎,仅等值 O(1),不支持范围);Full-Text 全文索引(倒排,文本检索,实际我更多用 ES);空间索引(GIS 场景)。
按物理/逻辑功能:
- 聚簇 vs 二级索引:聚簇索引叶子存整行,二级索引叶子存主键,需要回表;
- 主键 / 唯一 / 普通 / 联合索引:唯一索引同时承担业务约束(防重),联合索引靠最左前缀复用;
- 从 8.0 开始还有函数索引、隐藏索引(灰度删索引用,先 invisible 观察再 drop,这是我在线上做索引变更的标准动作)。
设计原则:单表索引控制在 5 个以内、联合索引列不超过 4~5 个,优先用联合索引替代多个单列索引——多个单列索引多数情况只有一棵被使用,另一个只做 index merge,效果远不如设计好的一棵联合树。
💻 全栈开发专家
我习惯从三个维度分类,面试和实操都清晰:
按数据结构:B+ 树(默认,99% 场景)、Hash(Memory 引擎,只等值查、不支持范围)、Full-text(全文索引,中文分词弱一般用 ES 替代)。
按物理存储:聚簇索引(主键,叶子存整行)、二级索引/辅助索引(叶子存主键值,查询可能回表)。
按功能语义:主键索引(唯一 + 非空)、唯一索引(防业务重复,如手机号)、普通索引、联合索引(多个列,最左前缀)、前缀索引(长字符串只索引前 N 个字符,省空间)。
工程实践两个点:
- 前缀索引的长度用区分度定:
SELECT COUNT(DISTINCT LEFT(email, n)) / COUNT(*) FROM user;,取曲线趋平的位置,但前缀索引不能用覆盖索引和 ORDER BY。 - 唯一索引是我做并发防重的首选手段,比如防重复下单,代码层判断 + 唯一索引兜底,比分布式锁更可靠。