干后端这些年,我优化过的慢查询没有一千也有八百条。很多朋友一听“SQL性能优化”就觉得高深,仿佛得懂什么玄学调优。实际上,90%的慢查询问题,靠一张 Execute计划(执行计划) 就能定位个七七八八。优化前后性能差百倍,真不是夸张的说法,我见过的案例里,从几十秒压到几百毫秒,甚至从十几秒压到几十毫秒的情况比比皆是。
这篇文章我就用三个真实案例,带你完整看透Execute计划在优化里的作用。这三个案例分别代表了三类最常见的性能杀手:索引失效、深分页排序、多表关联选错驱动表。我把当时的现场SQL、执行计划长什么样、怎么定位问题、最后怎么改的,全部复盘出来。无论你是刚接触数据库优化不久,还是已经在处理慢SQL但总感觉差点意思,这篇文章都能给你一套可以直接照抄的思路。
1. 为什么要死磕Execute计划?先搞清楚性能和成本差在哪
1.1 一个慢查询把你拖到怀疑人生的真实场景
我记得很清楚,有一年项目做活动大促,线上订单量蹭蹭往上涨。某天下午运营同学跑过来说,后台订单列表打不开了,点一下要转十几秒,最后直接超时。我第一反应不是去看服务器负载,而是先翻慢查询日志——果然,里面躺着几十条同款SQL,执行时间一条比一条离谱,最慢的一条跑了12秒多。
这种时刻你去看什么?看代码?代码本身逻辑很简单。看服务器?CPU内存都正常。真正能告诉你数据库内部在干什么的,只有Execute计划。MySQL里用EXPLAIN,SQL Server里直接看执行计划,本质都一样:它告诉你优化器打算怎么执行这条SQL,先读哪张表、怎么读、读多少行、要不要排序、要不要临时表。
不是跟你开玩笑,很多“性能问题”根本不是机器不行,是SQL把数据库的力气全花在了没意义的地方。你用全表扫描去查一个本该走索引的数据,数据库就得老老实实把几百万行翻一遍——这中间的浪费,往往就是几十倍到几百倍的时间差。
1.2 Execute计划到底在告诉你什么?(执行计划读法入门)
很多人看执行计划就是扫一眼有没有显示“Using index”,没显示就觉得要加索引。这是比较初级的状态。真正会读计划的人,重点看这么几个字段:
- type:访问类型。从好到差大概是 system > const > eq_ref > ref > range > index > ALL。看到ALL(全表扫描)就要警觉,这是性能差的最大元凶。
- key:实际用到的索引。如果是NULL,说明索引没生效。
- rows:优化器预估需要扫描的行数。这个数字是评估查询成本最直观的指标,从几十万行降到几十行,性能自然天差地别。
- Extra:额外信息。看到Using filesort说明要排序,看到Using temporary说明要建临时表,看到Using join buffer说明关联时可能出现了最糟糕的笛卡尔式匹配,这些都是危险的信号。
MySQL 5.7及以上还能用 EXPLAIN FORMAT=JSON 看到更细的成本估算值,MySQL 8.0.18以上干脆有 EXPLAIN ANALYZE,会真实执行一遍SQL并把每一步的实际耗时和行数打出来,定位问题时非常好用。后面案例里我会结合这些工具来拆。
1.3 优化前后的效果怎么量化?(什么叫“百倍差距”)
我经常跟团队里的小朋友说,优化不是看“感觉快了”,要有数据。怎么量化?很简单,两个指标:执行耗时和扫描行数。执行耗时你可以直接看SQL执行的毫秒数,扫描行数看执行计划里的rows字段。
比如案例一,优化前12秒,优化后0.08秒,12除以0.08等于150倍。案例二从11.5秒降到180毫秒,也接近64倍。案例三从7.8秒降到0.23秒,接近34倍。三个案例里有两个确实达到了“百倍”量级,更重要的是,操作其实并不复杂:调整SQL写法、补一个合适的索引、改变一下关联顺序,全都是在Execute计划里一眼就能看出来的问题。
所以这篇文章想传递的第一件事就是:性能优化不是靠猜,Execute计划是你唯一值得信赖的现场证据。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 案例一:一条索引失效的SQL,从12秒到0.08秒
2.1 现场还原:代码里查得好好的,生产上慢成PPT
第一个案例来自一个C端订单查询接口。业务逻辑很简单:用户的订单列表页,要求根据订单号精确查询某一条订单。对应订单表 orders,有约153万行数据。订单号字段 order_no 定义的是 varchar(32),也建了唯一索引 uk_order_no。
当时应用代码里写的是这样一条SQL:
sql复制SELECT * FROM orders
WHERE order_no = 2837491029384756;
你没看错,订单号老老实实有索引,SQL看起来也正常得不能再正常。但接口就是慢,慢到生产环境一调用就超时。本地连测试库怎么跑都挺快,一上生产就原形毕露。
为什么?因为测试库数据量只有几万行,全表扫描也能秒出结果。而生产库有153万行,全表扫描的开销完全不一样。这就是为什么我坚持要在生
