MySQL 怎么给数据表添加索引?附 2 种方法及适用场景

编程狮(w3cschool.cn) 2026-08-11 14:29:19 浏览数 (19)
反馈

你建了一张订单表,数据涨到几十万行后,按用户 ID 查订单越来越慢,同事让你"加个索引"。但你打开 Navicat 只会建表,不知道索引该怎么加、加错了会不会把表搞坏。最直接的办法有两种:用 CREATE INDEX 语句新建一个索引,或者用 ALTER TABLE 语句给表加索引,两者都能让查询快起来。本文基于 MySQL 8.0 验证,讲清这两种加索引的方法、各自适合的场景,以及什么时候其实不该加索引。今天这篇文章,编程狮就把添加索引这件事讲透。

一、先弄懂索引是什么:给表配一本"目录"

索引,是数据库中用来加速查询的一种数据结构。你可以把它想象成书末尾的目录:没有目录时,你想找"第几章讲了索引"只能从头翻到尾;有了目录,直接按页码跳过去就行。数据库表也是一样,没建索引时,MySQL 只能逐行扫描(全表扫描)去匹配条件;建了索引,就能先查索引、再精准定位到那几行,对查询性能帮助很大。

从索引类型看,最常见的是普通索引(底层一般是 B+ 树),它适合绝大多数等值查询和范围查询;此外还有全文索引、空间索引等专用类型,但日常加索引九成都是普通索引。理解这一点,你就不会被各种名词吓到。添加索引本身并不危险,它只是多维护一份"目录",但目录也要占空间、也要在每次写入时更新,所以不是加得越多越好。如果你刚接触数据库,建议先过一遍 MySQL 入门教程,把表、列、查询这些概念理顺。

加索引是性价比很高的优化手段,但前提是用对地方,盲目加只会适得其反。

实际判断该给哪列加索引,可以看 WHERE、JOIN、ORDER BY 后面高频出现的列;这些列被查得越勤,建索引的性价比越高。反过来,几乎不出现在查询条件里的列,建了也用不上。

💡 小提示:可以用 EXPLAIN SELECT ... 查看一条查询是否用到了索引;结果里 type 列是 ALL 就代表走了全表扫描,该考虑加索引了。

二、方法一:CREATE INDEX 新建普通索引(最干净)

第一种做法,是用 CREATE INDEX 语句单独建索引,它不影响表结构本身,语义也最清楚——"我就想加个索引"。语法是 CREATE INDEX 索引名 ON 表名 (列名)

-- 在 orders 表的 user_id 列上建一个名为 idx_user 的普通索引
CREATE INDEX idx_user ON orders (user_id);

执行后,MySQL 会为 user_id 这列单独建一份有序的目录。之后你写 WHERE user_id = 123,查询就能走索引,不用再扫全表,查询性能会有肉眼可见的提升。建完可以用 SHOW INDEX FROM orders; 查看索引是否生效、叫什么名字。索引名建议带上 idx_ 前缀和列名,方便以后维护时一眼认出。常用的 SQL 语法记不住,MySQL 速查手册 可以常备在手边。

除了加速查询,索引有时还能帮上 ORDER BY 和 GROUP BY,因为数据已经是有序的,MySQL 不必再额外排一次序。

三、方法二:ALTER TABLE 给表加索引(可一次加多列)

第二种做法,是用 ALTER TABLE 修改表结构来加索引。它和 CREATE INDEX 效果等价,但 ALTER TABLE 还能顺带做很多事,比如一次加多列的组合索引:

-- 给 orders 表加一个普通索引
ALTER TABLE orders ADD INDEX idx_user (user_id);


-- 一次加多列的组合索引(常用于多条件查询)
ALTER TABLE orders ADD INDEX idx_user_status (user_id, status);

当你要按"用户 ID + 订单状态"两个字段一起查时,组合索引比单列索引更合适,因为它能一次性缩小范围。注意组合索引遵循"最左前缀"原则:查询条件要从最左列开始,才能用上这份索引。如果你还想系统学 SQL,SQL 基础教程 里对索引和查询优化有更完整的讲解。

如果索引建错了或不再需要,删掉也同样有两种写法:DROP INDEX idx_user ON orders;ALTER TABLE orders DROP INDEX idx_user;

四、唯一索引、主键索引怎么选,以及什么时候别加索引

除了普通索引,还有两类常用的:唯一索引要求这一列的值不能重复,适合邮箱、手机号这类天然唯一的字段;主键索引则是表的主键自带的,一张表只能有一个。语法上,唯一索引只是把 INDEX 换成 UNIQUE INDEX:

-- 邮箱不能重复,建唯一索引
CREATE UNIQUE INDEX idx_email ON users (email);

反过来,下面这些情况反而别急着加索引:写多读少的表(每次插入都要更新索引,会拖累写入性能);区分度很低的列(比如"性别"只有男女,建了索引 MySQL 也多半懒得用);还有数据量极小的表,全表扫描本来就快,加索引纯属多余。对很长的字符串列(如文章标题),可以只取前 N 个字符建前缀索引,既省空间又够用:CREATE INDEX idx_title ON articles (title(20));。主键索引其实也是一种特殊的唯一索引,只是整张表只能有一个,通常用来唯一标识每一行。

下面把两种加索引的方法对比一下:

方法 适用场景 优点 注意点
CREATE INDEX 只想单独加索引,不改其他结构 语义清晰、好维护 一次只能加一个索引
ALTER TABLE 要顺带改表、加组合索引 一条语句搞定多件事 改动表结构,上线需谨慎

总结

添加索引的本质,是给表配一份"目录"来加速查询,对读多写少的场景性能收益最明显。最常用的是两种做法:CREATE INDEX 单独建索引,语义最干净;ALTER TABLE 加索引,能顺带做组合索引等更多操作。记住三条:

  • 查询慢、EXPLAIN 显示全表扫描时,优先考虑加索引;
  • 唯一字段用唯一索引,多条件查询用组合索引;
  • 写多读少、区分度低、数据量小的表,别盲目加索引。

想继续深入数据库优化,可以顺着下面的路径走。

延伸学习

想把数据库这块补扎实,可以按这个顺序来:

  1. 想系统学 SQL,数据库学习路线 能帮你规划从基础到进阶的路径;
  2. 想动手练,编程实战课程 提供可上手的数据库小项目。

常见问题

Q:加索引会把原表数据搞丢吗?
A:不会。添加索引只额外维护一份目录,不改原有数据。但大表加索引会锁表一段时间,建议在低峰期操作。

Q:索引是不是加得越多查询越快?
A:不是。索引加速读,但拖慢写,还占空间。只对高频查询列建索引才划算,性能才划算。

Q:CREATE INDEX 和 ALTER TABLE 加索引有什么区别?
A:最终效果一样。CREATE INDEX 只建索引、语义单纯;ALTER TABLE 能顺带改表结构、加组合索引,但改动更大。

Q:怎么知道查询有没有用上索引?
A:在查询前加 EXPLAIN,看返回结果的 type 列;是 ALL 就是全表扫描没用索引,该建了。

0 人点赞