索引类型:聚簇索引与非聚簇索引、唯一索引、联合索引、全文索引

索引这东西,说白了就是数据库的「目录」。没有它,查询就是全表扫描——数据量小还好,上了百万级你就等着报警吧。我这些年调过的慢查询,十有八九都是索引没用好。

但索引也不是随便建的。建错了,写操作变慢,磁盘空间暴涨。建对了,查询速度能提升几个数量级。今天咱们就把几种核心索引类型掰开揉碎讲清楚。

核心观点:索引类型的选择,取决于你的查询模式。没有银弹,只有匹配。

聚簇索引 vs 非聚簇索引

这是最基础、也最容易混淆的一对概念。我面试时经常问,能讲清楚的人不多。

聚簇索引,表数据的物理存储顺序和索引顺序一致。一张表只能有一个聚簇索引。InnoDB 里,主键就是聚簇索引。如果你没定义主键,它会选一个唯一非空索引;还没有,就隐式生成一个 6 字节的 rowid。

聚簇索引的叶子节点存的是整行数据。所以通过主键查数据,一次 B+ 树搜索就能拿到全部字段,不需要回表。这就是为什么主键查询那么快。

非聚簇索引,叶子节点存的是主键值(InnoDB)或行指针(MyISAM)。查询时先找到主键,再回聚簇索引取数据——这个过程叫「回表」。回表一次还好,回表几百次性能就崩了。

对比维度 聚簇索引 非聚簇索引
每表数量 1 个 多个
叶子节点内容 整行数据 主键值(InnoDB)
是否需要回表 否 是
物理顺序 与索引顺序一致 与索引顺序无关
适用场景 主键查询、范围查询 非主键列的精确匹配

我的经验:建表时一定要选对聚簇索引的列。我见过有人用 UUID 做主键,结果插入时频繁页分裂,写入性能惨不忍睹。自增整数做主键,在大多数场景下是最稳的选择。

唯一索引

唯一索引保证索引列的值全局唯一。它和主键的区别在于:唯一索引允许 NULL 值(而且可以多个 NULL),主键不允许。

唯一索引有两个作用:一是约束数据完整性,二是加速查询。MySQL 对唯一索引的查询优化优先级很高,因为它知道最多只返回一条记录。

-- 创建唯一索引
CREATE UNIQUE INDEX idx_user_email ON users(email);

-- 或者建表时指定
CREATE TABLE users (
    id INT PRIMARY KEY,
    email VARCHAR(255) UNIQUE,
    name VARCHAR(100)
);

我曾经踩过的坑:在业务代码里先查再插来「模拟」唯一约束,高并发下总有重复数据漏进去。后来改成唯一索引 + INSERT IGNORE,问题彻底解决。数据库能做的事,别让应用层做。

联合索引

联合索引,也叫复合索引,是多个列组合成一个索引。它遵循「最左前缀原则」——查询条件必须从索引的最左列开始匹配,才能用到索引。

举个例子,索引 (a, b, c) 能匹配的查询模式:

  • WHERE a = 1 ✅ 用到索引
  • WHERE a = 1 AND b = 2 ✅ 用到索引
  • WHERE a = 1 AND b = 2 AND c = 3 ✅ 用到索引
  • WHERE b = 2 ❌ 用不到索引
  • WHERE a = 1 AND c = 3 ⚠️ 只用到了 a 列

为什么会这样?因为 B+ 树是按索引列的顺序构建的。先按 a 排序,a 相同再按 b 排序,b 相同再按 c 排序。跳过前面的列直接查后面的,树就不知道怎么走了。

我建议:设计联合索引时,把区分度高的列放前面。比如 (status, created_at) 和 (created_at, status),前者通常更优——因为 status 枚举值少,created_at 区分度高。你想想看,先过滤掉 90% 的数据,再处理剩下的 10%,效率肯定更高。

全文索引

全文索引专门用来处理文本搜索。LIKE '%keyword%' 这种写法,数据量一大就废了——它不走索引,全表扫描。全文索引用倒排索引(Inverted Index)实现,把文档拆成词条,再映射到文档 ID。

MySQL 的全文索引只支持 MyISAM 和 InnoDB(5.6 以后)。用法很简单:

-- 创建全文索引
CREATE FULLTEXT INDEX idx_content ON articles(content);

-- 查询
SELECT * FROM articles
WHERE MATCH(content) AGAINST('数据库优化' IN NATURAL LANGUAGE MODE);

全文索引有三种搜索模式:

  • 自然语言模式:默认模式,按相关性排序
  • 布尔模式:支持 +、-、* 等操作符,精确控制搜索逻辑
  • 查询扩展模式:先搜一次,再用结果中的高频词扩展搜索

注意:全文索引有最小词长度限制(InnoDB 默认 3 个字符)。搜「Go」或「C++」这种短词,默认是搜不到的。需要修改 innodb_ft_min__size 参数。我之前做技术博客搜索时就栽过这个坑。

一张图看懂索引体系

下面这张图把几种索引的关系和适用场景串起来了。我建议你保存下来,面试前看一眼就够了。

索引类型体系与适用场景 数据库索引 聚簇索引 非聚簇索引 主键查询 范围查询 唯一索引 联合索引 数据完整性约束 最左前缀匹配 全文索引 倒排索引 文本搜索 一张表只能有一个 聚簇索引

如何选择索引类型

选索引类型,其实就是在问自己三个问题:

  1. 查询频率最高的列是什么?——优先建索引
  2. 查询是精确匹配还是范围查询?——精确匹配用唯一索引或普通索引,范围查询用聚簇索引或联合索引
  3. 是否需要文本搜索?——是的话上全文索引,别用 LIKE

我个人习惯:先跑一遍慢查询日志,找到 TOP 5 的慢 SQL。针对每个慢 SQL 的 WHERE 条件、JOIN 列、ORDER BY 列来设计索引。不要凭感觉建索引,要拿数据说话。