索引类型详解:从主键到全文,你该选哪个?
索引的类型,说白了就是给数据建目录的不同方式。每种类型都有它的脾气和适用场景。我这些年调过不少慢查询,有一半的问题出在索引选型上——不是没建,而是建错了类型。
咱们一个一个来看。
1. 主键索引(Primary Key)
这玩意儿是强制要求数据行唯一的。一张表最多只有一个主键索引。在 InnoDB 引擎里,它还是个聚簇索引。什么意思呢?就是数据本身跟索引长在一起。
特点:
- 自动创建:建表时指定 PRIMARY KEY,MySQL 就会自动建成这个聚簇索引
- 非空唯一:主键列不能为 NULL,值必须全局唯一
- 物理排序:数据行按主键顺序物理存储
我遇到过的一个坑:
有次接手一个老系统,表里根本没有自增主键,用的是 UUID 做为主键。插入数据时页面卡死,查了一下,原因是 UUID 无序,每次插入都要大量页分裂。后来我改成自增 BIGINT,性能直接翻了三倍。
-- 创建表时指定主键
CREATE TABLE users (
id BIGINT AUTO_INCREMENT,
name VARCHAR(50),
PRIMARY KEY (id)
);
2. 唯一索引(Unique Index)
唯一索引允许 NULL,但非空值必须唯一。你想想看,它跟主键索引的区别在哪?主键只能一个,唯一索引可以建多个。主键不能 NULL,唯一索引允许多个 NULL——嗯,这里要注意,MySQL 认为 NULL != NULL,所以多个 NULL 是允许的。
- 约束数据:确保列值的唯一性(业务上常用,比如邮箱、身份证号)
- 非聚簇:如果是二级唯一索引,不会改变数据物理存储
- 可以联合:多列组合成唯一索引
我的习惯:
只要是业务上不能重复的字段,我都会建唯一索引。不只是为了查询,更多的是为了约束——让数据库替你把关,比业务层加锁靠谱得多。
-- 建唯一索引
CREATE UNIQUE INDEX idx_email ON users(email);
-- 或者建表时指定
CREATE TABLE users (
id INT,
email VARCHAR(100) UNIQUE
);
3. 普通索引(普通索引 / INDEX)
也叫非唯一索引,最常见,没有唯一性限制。说白了就是个单纯的加速器。允许重复值,允许 NULL。
我建议,凡是经常出现在 WHERE 条件里的列,都考虑建个普通索引。但别贪多——索引不是越多越好,写操作有代价。
适用场景:
- 高频查询字段,如订单表的 user_id
- 排序字段(ORDER BY)
- 连接字段(JOIN)
曾经踩过的雷:
有一次我在一张 2000 万行的日志表上,对每个可能查询的列都建了普通索引,结果插入变慢,磁盘占用暴涨。后来我做了索引合并和冗余分析,删掉了一半的索引,性能才稳下来。
-- 创建普通索引
CREATE INDEX idx_order_time ON orders(created_at);
4. 全文索引(Fulltext Index)
全文索引是专为文本搜索设计的,你不用它去查数字或日期。它支持分词、停用词、相关度排序。MyISAM 和 InnoDB 都支持(MySQL 5.6 以后 InnoDB 才支持)。
我当时做一个新闻搜索模块,直接用 LIKE '%关键字%' 查,数据量一上来慢得要命。换成全文索引后,秒级出结果。
注意事项:
- 只适用于 CHAR、VARCHAR、TEXT 类型
- 默认最短分词长度:InnoDB 是 3 个字符
- 需要使用 MATCH … AGAINST 语法,不是普通的 WHERE
-- 创建全文索引
CREATE FULLTEXT INDEX ft_content ON articles(content);
-- 查询用法
SELECT * FROM articles
WHERE MATCH(content) AGAINST('数据库性能' IN NATURAL LANGUAGE MODE);
5. 其他索引补充
除了上面四种,实际工作中还有几个不得不提的:
- 复合索引:多列组合成一个索引,最左前缀原则。我建议把选择性高的列放左边。
- 空间索引(SPATIAL):用于地理数据类型(POINT、LINESTRING 等),MyISAM 支持,InnoDB 从 MySQL 5.7 开始支持。
- 哈希索引(HASH):Memory 引擎默认,等值查询极快,但不支持范围查询和排序。
一句话总结:
主键索引管物理存储,唯一索引管业务约束,普通索引负责提速,全文索引管文本搜索。选型之前一定想清楚:你要的是什么能力?
各类型对比表
| 索引类型 | 唯一性 | 允许多个 | 允许NULL | 聚簇 | 典型引擎 | 主要用途 |
|---|---|---|---|---|---|---|
| 主键索引 | 是 | 否(只能一个) | 否 | 是(InnoDB) | InnoDB | 数据物理组织 + 唯一标识 |
| 唯一索引 | 是 | 是 | 多个NULL | 否 | InnoDB/MyISAM | 业务唯一约束 + 查询加速 |
| 普通索引 | 否 | 是 | 是 | 否 | InnoDB/MyISAM | 查询加速 |
| 全文索引 | 否 | 是 | 是 | 否 | InnoDB/MyISAM | 文本搜索(分词匹配) |
这张图把索引类型分成了四大类。每个大类下面,我又补充了实际使用时的核心要点。你可能会问:我实际建索引时该选哪个?我的建议是——先看业务需求。要唯一性约束吗?要文本搜索吗?要覆盖查询吗?想清楚这些,选型自然就有了。
最后分享一个小原则:能用普通索引解决的问题,就不要用唯一索引;只有确实需要约束唯一性时,才建唯一索引。因为唯一索引在插入时多了一次唯一性检查的代价。