MySQL 索引优化入门:从慢查询到覆盖索引

举报
yd_282444815 发表于 2026/10/27 09:31:32 2026/10/27
【摘要】 数据库用久了,最常见的抱怨就是“查询越来越慢”。表里只有几千行时一切正常,数据涨到几十万行后,原本毫秒级返回的接口开始频繁超时。很多人的第一反应是升级硬件,其实大多数慢查询问题都可以通过合理使用索引解决。 一、索引到底是什么可以把索引理解为一本书的目录。没有目录时,要找某个章节只能从第一页翻到最后一页,这就是全表扫描;有了目录,就可以直接定位到目标页码,代价是目录本身也要占用篇幅,并且每次增...

数据库用久了,最常见的抱怨就是“查询越来越慢”。表里只有几千行时一切正常,数据涨到几十万行后,原本毫秒级返回的接口开始频繁超时。很多人的第一反应是升级硬件,其实大多数慢查询问题都可以通过合理使用索引解决。

一、索引到底是什么

可以把索引理解为一本书的目录。没有目录时,要找某个章节只能从第一页翻到最后一页,这就是全表扫描;有了目录,就可以直接定位到目标页码,代价是目录本身也要占用篇幅,并且每次增删内容都要同步更新目录。

MySQL 的 InnoDB 引擎默认使用 B+ 树来组织索引。B+ 树是一种多路平衡查找树,叶子节点按顺序排列并用链表连接,因此既适合等值查询,也适合范围查询。主键索引的叶子节点直接存放整行数据,这叫聚簇索引;普通索引的叶子节点存放的是主键值,查到主键后再回表取整行数据,这叫二级索引。

二、先找到慢查询:EXPLAIN

优化之前要先定位问题。MySQL 提供了 EXPLAIN 语句,可以查看一条查询的执行计划:

EXPLAIN SELECT * FROM orders WHERE user_id = 1001 AND status = 'paid';

重点关注几个字段:type 表示访问类型,从好到差依次是 system、const、eq_ref、ref、range、index、ALL,出现 ALL 就意味着全表扫描;key 表示实际用到的索引,为 NULL 说明没有用上索引;rows 是预估扫描行数,这个数字越小越好;Extra 里的 Using filesort 和 Using temporary 则提示需要额外的排序或临时表,值得警惕。

三、最左前缀原则

联合索引是索引优化中最容易踩坑的地方。假设在 (user_id, status, created_at) 三列上建了联合索引,那么查询条件里必须从最左边的列开始匹配:只用 user_id 可以走索引,只用 status 则走不了;user_id 和 created_at 组合时,只能用到 user_id 这一列的部分索引。

一个实用的建索引顺序是:区分度高的列放前面,等值查询的列放前面,范围查询的列放后面。因为范围条件会截断后续列的索引使用,把范围列放在最后可以让前面的列充分发挥作用。

四、覆盖索引与回表

如果查询需要的列全部包含在索引里,MySQL 就不需要回表取数据,这种索引叫覆盖索引。比如下面的查询:

SELECT user_id, status FROM orders WHERE user_id = 1001;

如果存在 (user_id, status) 索引,这条查询可以直接从索引中拿到结果,Extra 会显示 Using index,速度通常比回表快一个数量级。设计索引时可以有意识地把高频查询的列组合进去,但也要注意索引列越多,写入成本和存储占用就越高。

五、索引不是越多越好

索引能加速查询,却会拖慢写入。每次 INSERT、UPDATE、DELETE 都要维护相关的索引树,索引越多,写入越慢,占用磁盘也越多。常见的反模式包括:给区分度极低的列建索引、在小表上建一堆索引、以及建了大量从未被使用过的索引。可以用慢查询日志定期检查索引的使用情况,把长期无人使用的索引删掉,保持索引精简,是数据库长期健康的习惯。

六、一个完整的优化例子

假设订单表 orders 有 200 万行,查询“某个用户最近三个月已支付的订单”原来要 2 秒多:

SELECT id, amount, created_at FROM orders
WHERE user_id = 1001 AND status = 'paid'
  AND created_at >= '2026-07-27'
ORDER BY created_at DESC;

优化思路是建一个 (user_id, status, created_at) 联合索引:前两列是等值条件,最后一列既是范围条件又是排序列。建好索引并用 EXPLAIN 验证后,这条查询通常可以降到几毫秒。记住:先验证,再上线,任何索引调整都要以执行计划为准。

结语

索引优化的核心并不复杂:理解 B+ 树的结构,用 EXPLAIN 定位问题,遵循最左前缀原则,善用覆盖索引,同时克制建索引的数量。把这几条原则用在日常开发里,大多数慢查询问题都能在萌芽阶段解决。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。