从索引设计到执行计划:一条慢查询的“体检”全流程
大家好我是小耶写功课只是为了我踩过的坑你们别再踩了慢查询优化很多人的做法是看到SQL慢先猜是不是没索引加一个试试不行就再换一个还不行就改写SQL碰运气。这种做法效率低而且往往治标不治本。真正的优化应该是一套“体检”流程从索引设计是否合理到执行计划如何解读再到统计信息是否准确最后到SQL改写验证——形成一个完整的闭环。今天我就用一条真实的慢查询把这个流程完整走一遍。第一步索引设计——地基没打好后面全白费很多慢查询的根源不是优化器选错了而是压根没有合适的索引。设计索引有几个基本原则这些原则不是背口诀而是有底层逻辑支撑的。等值查询的列放左边范围查询的列放右边。原因是在BTree结构中索引首先按最左列排序当遇到范围查询、、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_id和status是等值查询且选择性较好放在前面create_time是范围查询放在最后。同时这个索引覆盖了查询所需的order_id、amount需要回表、create_time部分实现了覆盖。第二步执行计划解读——让数据库告诉你问题在哪索引建好了但优化器是不是真的用了这就要看执行计划。执行上面查询的EXPLAIN我们可能会看到这样的输出typekeykey_lenrowsExtrarefidx_shop_status_time823Using where逐列解读typeref用了普通索引效率良好不是ALL或index说明索引生效。key实际使用了我们创建的复合索引。key_len8shop_id4字节status假设4字节说明只用到了前两列create_time没有参与索引过滤。这是因为create_time是范围条件索引在遇到范围后停止匹配这是正常现象。rows23优化器预估只扫描23行非常好。ExtraUsing where需要回表后过滤create_time但23行回表代价很小。这个执行计划本身是健康的。但如果rows很大或者typeALL就说明索引设计或使用出了问题。第三步统计信息——为什么优化器会“瞎”选有时候明明有合适的索引优化器却选择了全表扫描。原因往往是统计信息过旧。优化器选择索引时依赖表的统计信息总行数、不同值数量、数据分布等。如果统计信息没有及时更新优化器就会误判。比如一张表实际有100万行但统计信息显示只有1万行优化器可能认为全表扫描更快。更新统计信息的命令是ANALYZE TABLE。建议在批量导入、大量删除或数据分布发生明显变化后执行。对于MySQL 8.0统计信息默认是持久化的但仍可能需要手动触发。检查统计信息是否准确的一个简单方法EXPLAIN中的rows估算值与实际行数相差是否巨大。如果差了一个数量级大概率是统计信息过旧了。第四步验证优化——从EXPLAIN到EXPLAIN ANALYZE在测试环境我们可以使用EXPLAIN ANALYZEMySQL 8.0.18来获得真实的执行信息而不只是估算。它会真正执行SQL并输出每个操作的实际耗时、实际扫描行数、循环次数等。这可以帮助我们确认优化器的估算是否准确以及哪个步骤最耗时。例如执行EXPLAIN ANALYZE SELECT ...后输出中会包含类似actual time0.123..0.456 rows23 loops1的信息。如果actual time远超预期或者rows与估算值差距很大就需要进一步调查。完整的优化闭环从索引设计到执行计划再到统计信息和验证优化是一个不断迭代的过程根据业务查询模式设计合理的索引遵循等值在前、高选择性在前、覆盖索引等原则。执行EXPLAIN检查执行计划是否符合预期。关注type、key、rows、Extra。如果优化器没选对索引先ANALYZE TABLE更新统计信息。如果仍不对检查是否有隐式类型转换、函数包裹索引列等失效原因。在测试环境使用EXPLAIN ANALYZE验证真实执行情况确认优化效果。上线后持续监控慢查询日志观察是否有新的慢查询出现。这个闭环的核心思想是不要靠猜要让数据库告诉你它需要什么。执行计划就是数据库的“体检报告”读懂它你就能从被动救火变成主动预防。小耶在手SQL 不愁还有什么想了解的欢迎留言小耶一定知无不言言无不尽……我们下次见~