news 2026/6/16 22:35:32

从索引设计到执行计划:一条慢查询的“体检”全流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从索引设计到执行计划:一条慢查询的“体检”全流程

大家好,我是小耶,写功课只是为了我踩过的坑,你们别再踩了!

慢查询优化,很多人的做法是:看到SQL慢,先猜是不是没索引,加一个试试;不行就再换一个;还不行就改写SQL碰运气。这种做法效率低,而且往往治标不治本。

真正的优化应该是一套“体检”流程:从索引设计是否合理,到执行计划如何解读,再到统计信息是否准确,最后到SQL改写验证——形成一个完整的闭环。今天我就用一条真实的慢查询,把这个流程完整走一遍。

第一步:索引设计——地基没打好,后面全白费

很多慢查询的根源,不是优化器选错了,而是压根没有合适的索引。

设计索引有几个基本原则,这些原则不是背口诀,而是有底层逻辑支撑的。

  • 等值查询的列放左边,范围查询的列放右边​。原因是在B+Tree结构中,索引首先按最左列排序,当遇到范围查询(><BETWEEN)时,后续列无法继续使用索引。所以设计复合索引时,要把=的条件放在前面,><等范围条件放在后面。
  • 高选择性的列优先​。选择性 = 不重复值数量 / 总行数。选择性越高,索引过滤效果越好。比如身份证号的选择性接近1,而性别只有0.5。把高选择性的列放在复合索引前面,能更快缩小扫描范围。
  • 考虑覆盖索引​。如果查询需要的所有列都包含在索引中,就不需要回表,Extra会显示Using index。这能减少一半以上的I/O。

假设我们有这样一张订单表,经常执行查询“查询某店铺某状态下,最近一段时间的订单”:

SELECT order_id, amount, create_time FROM orders WHERE shop_id = 123 AND status = 'PAID' AND create_time > '2026-01-01';

根据上述原则,推荐的复合索引是(shop_id, status, create_time)shop_idstatus是等值查询且选择性较好,放在前面;create_time是范围查询,放在最后。同时这个索引覆盖了查询所需的order_idamount(需要回表)、create_time,部分实现了覆盖。

第二步:执行计划解读——让数据库告诉你问题在哪

索引建好了,但优化器是不是真的用了?这就要看执行计划。

执行上面查询的EXPLAIN,我们可能会看到这样的输出:

typekeykey_lenrowsExtra
refidx_shop_status_time823Using where

逐列解读:

  • type=ref:用了普通索引,效率良好,不是ALLindex,说明索引生效。
  • key:实际使用了我们创建的复合索引。
  • key_len=8shop_id(4字节)+status(假设4字节),说明只用到了前两列,create_time没有参与索引过滤。这是因为create_time是范围条件,索引在遇到范围后停止匹配,这是正常现象。
  • rows=23:优化器预估只扫描23行,非常好。
  • Extra=Using where:需要回表后过滤create_time,但23行回表代价很小。

这个执行计划本身是健康的。但如果rows很大,或者type=ALL,就说明索引设计或使用出了问题。

第三步:统计信息——为什么优化器会“瞎”选

有时候明明有合适的索引,优化器却选择了全表扫描。原因往往是统计信息过旧。

优化器选择索引时,依赖表的统计信息(总行数、不同值数量、数据分布等)。如果统计信息没有及时更新,优化器就会误判。比如一张表实际有100万行,但统计信息显示只有1万行,优化器可能认为全表扫描更快。

更新统计信息的命令是ANALYZE TABLE。建议在批量导入、大量删除或数据分布发生明显变化后执行。对于MySQL 8.0,统计信息默认是持久化的,但仍可能需要手动触发。

检查统计信息是否准确的一个简单方法:EXPLAIN中的rows估算值与实际行数相差是否巨大。如果差了一个数量级,大概率是统计信息过旧了。

第四步:验证优化——从EXPLAIN到EXPLAIN ANALYZE

在测试环境,我们可以使用EXPLAIN ANALYZE(MySQL 8.0.18+)来获得真实的执行信息,而不只是估算。它会真正执行SQL,并输出每个操作的实际耗时、实际扫描行数、循环次数等。这可以帮助我们确认优化器的估算是否准确,以及哪个步骤最耗时。

例如,执行EXPLAIN ANALYZE SELECT ...后,输出中会包含类似actual time=0.123..0.456 rows=23 loops=1的信息。如果actual time远超预期,或者rows与估算值差距很大,就需要进一步调查。

完整的优化闭环

从索引设计到执行计划,再到统计信息和验证,优化是一个不断迭代的过程:

  1. 根据业务查询模式,设计合理的索引(遵循等值在前、高选择性在前、覆盖索引等原则)。
  2. 执行EXPLAIN,检查执行计划是否符合预期。关注typekeyrowsExtra
  3. 如果优化器没选对索引,先ANALYZE TABLE更新统计信息。如果仍不对,检查是否有隐式类型转换、函数包裹索引列等失效原因。
  4. 在测试环境使用EXPLAIN ANALYZE验证真实执行情况,确认优化效果。
  5. 上线后持续监控慢查询日志,观察是否有新的慢查询出现。

这个闭环的核心思想是:​不要靠猜,要让数据库告诉你它需要什么​。执行计划就是数据库的“体检报告”,读懂它,你就能从被动救火变成主动预防。

小耶在手,SQL 不愁

还有什么想了解的,欢迎留言!小耶一定知无不言言无不尽……我们下次见~

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/16 22:32:02

ASP.NET乱码问题全链路排查与UTF-8统一配置指南

1. 项目概述&#xff1a;为什么ASP.NET乱码问题总在凌晨三点找上门“页面中文显示成问号”“POST过来的汉字变成”“数据库存进去是乱码&#xff0c;查出来还是乱码”——这三句话&#xff0c;几乎刻在每个做过ASP.NET Web Forms或MVC项目的开发者工位上。我带过六支后端团队&a…

作者头像 李华
网站建设 2026/6/16 22:31:12

深入解析MPC8308:PowerQUICC II Pro架构、外设集成与嵌入式通信系统设计实践

1. MPC8308&#xff1a;一款被低估的嵌入式通信处理“多面手”在嵌入式系统开发领域&#xff0c;尤其是工业控制、网络通信和物联网网关这类对集成度、功耗和实时性有严苛要求的场景&#xff0c;选择一颗合适的处理器往往是项目成败的关键。从业十多年&#xff0c;我接触过不少…

作者头像 李华
网站建设 2026/6/16 22:29:30

赛马娘DMM版本地化终极指南:轻松实现中文界面与性能优化

赛马娘DMM版本地化终极指南&#xff1a;轻松实现中文界面与性能优化 【免费下载链接】umamusume-localify Localify "ウマ娘: Pretty Derby" DMM client 项目地址: https://gitcode.com/gh_mirrors/um/umamusume-localify umamusume-localify 是一款专为赛马娘…

作者头像 李华
网站建设 2026/6/16 22:22:21

3分钟获取阿里云盘Refresh Token完整教程:扫码搞定自动化管理

3分钟获取阿里云盘Refresh Token完整教程&#xff1a;扫码搞定自动化管理 【免费下载链接】aliyundriver-refresh-token QR Code扫码获取阿里云盘refresh token For Web 项目地址: https://gitcode.com/gh_mirrors/al/aliyundriver-refresh-token 阿里云盘Refresh Token…

作者头像 李华
网站建设 2026/6/16 22:20:33

BiliTools:3分钟学会用这款开源工具箱管理你的B站收藏

BiliTools&#xff1a;3分钟学会用这款开源工具箱管理你的B站收藏 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱&#xff0c;支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools 还…

作者头像 李华
网站建设 2026/6/16 22:20:10

毫米级时间控制的交互式魔法系统设计

1. 项目概述&#xff1a;这不是魔术&#xff0c;是可复现的交互式叙事工程“Allen Lees Magic”——看到这个名字&#xff0c;很多人第一反应是某位海外魔术师的个人秀场&#xff0c;或是某个小众艺术项目的代号。但在我过去十年拆解过上百个类似命名的项目后&#xff0c;这个标…

作者头像 李华