EXPLAIN执行计划深度解读:从type到cost,彻底读懂SQL为什么慢

本文涉及的产品
RDS Agent(兼容OpenClaw),2核4GB
云数据库 PolarDB MySQL 版,列存表分析加速 4核8GB
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
简介: 本期深入解析`EXPLAIN`核心字段:用`key_len`判断索引使用列数,借`filtered`评估回表代价,并详解MySQL 8.0的`EXPLAIN ANALYZE`如何以真实执行数据替代估算,让SQL优化更精准、可验证。

大家好,我是小耶。上周讲了EXPLAIN的3个必看字段,评论区不少朋友说“够用但还想深入”。今天就把它彻底拆开,讲讲key_len怎么判断用了索引的哪几列,filtered如何评估回表代价,以及MySQL 8.0的EXPLAIN ANALYZE为什么比传统EXPLAIN更准。

1 问题背景:为什么只靠type还不够?

在日常优化中,typeALL变成rangeref固然能大幅提升性能,但当多个索引可选时,优化器的选择是否正确?索引用了但扫描行数依然很大怎么办?这些仅靠传统EXPLAIN难以回答。

MySQL 8.0引入了EXPLAIN ANALYZE,可以输出实际执行的成本和时间;FORMAT=JSON则能展示优化器的代价估算。掌握这些,才能真正理解SQL慢在哪里。

2 核心概念:EXPLAIN输出列详解

以下列是按重要性排序的必看项:

  • type​:访问类型。从优到劣:system > const > eq_ref > ref > range > index > ALLALL代表全表扫描,必须优化。
  • possible_keys​:可能用到的索引。若为NULL,说明无可用的索引。
  • key​:实际使用的索引。若为NULL,代表未走索引。
  • key_len​:实际使用的索引字节数。可推算索引中具体用了哪几列(例如utf8mb4每字符4字节,key_len=4表示只用了第一列)。
  • rows​:预估需要扫描的行数。数字越大越慢。但此为估算值,与filtered配合可估算回表行数。
  • filtered​:存储引擎层返回的数据经过WHERE条件过滤后剩余的比例。例如rows=1000filtered=10.00,表示最终大约返回100行。如果filtered很低且索引不包含所有WHERE列,说明需要回表过滤大量数据,可考虑覆盖索引。
  • Extra​:附加信息。常见的有:

    • Using index:覆盖索引,不回表,好。
    • Using index condition:索引下推,较好。
    • Using where:需要回表过滤,通常正常。
    • Using filesort:需要额外排序,应优化。
    • Using temporary:使用临时表,应优化。
  • EXPLAIN ANALYZE​(MySQL 8.0.18+):实际执行查询并输出每个步骤的实际耗时、循环次数、返回行数等,比估算准确。格式示例:
    text

    -> Nested loop inner join  (actual time=0.1..0.2 rows=10 loops=1)
    

    注意:它会真实执行,生产环境慎用。

3 案例解析:从执行计划定位一个真实慢查询

3.1 问题SQL

SELECT * FROM orders WHERE user_id = 123 ORDER BY order_date DESC;

原索引为 (user_id)EXPLAIN结果:

type key rows Extra
ref idx_user_id 5000 Using filesort

rows=5000(该用户有5000条订单),Extra=Using filesort(因为order_date没有索引,需要额外排序)。经验证该查询耗时0.8秒。

3.2 优化过程

添加联合索引 (user_id, order_date)后:

type key rows Extra
ref idx_user_date 5000 (空)

无需filesort,耗时降至0.05秒。这里rows仍为5000,但Extra已无排序,且key_len可判断实际用了两列。

若需进一步优化,可改为覆盖索引 (user_id, order_date, status, amount) 避免回表,Extra会显示Using index

3.3 使用FORMAT=JSON查看代价

EXPLAIN FORMAT=JSON SELECT ...;

输出中的cost_info块展示了read_costeval_costprefix_cost,可比较不同索引的代价估算,帮助理解优化器决策。

4 总结与建议

  • 日常慢查询分析,先看typerows;若type不是ALLrows很大,检查filteredkey_lenExtra中出现Using filesortUsing temporary几乎总是需要优化。
  • MySQL 8.0用户可将EXPLAIN ANALYZE用于测试环境,获取真实执行成本。
  • 掌握这些,就不只是“能看懂”,而是能根据执行计划精准加索引或改写SQL。

理解执行计划是SQL调优的基石。从3个字段到全解读,你的优化能力会上一个台阶。

小耶在手,SQL 不愁。

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

相关文章
|
16天前
|
SQL 关系型数据库 MySQL
EXPLAIN 执行计划:一眼看穿你的SQL慢在哪
数据库小学妹带你轻松掌握SQL性能诊断!通过EXPLAIN查看执行计划,精准识别索引失效、全表扫描(ALL)、key为NULL等瓶颈。聚焦type、key、rows等6个关键字段,结合实战案例与避坑指南(如函数滥用、最左前缀破坏),让优化有的放矢。学完即用,告别盲目调优!
|
8天前
|
SQL 关系型数据库 MySQL
一张5000万行的表,加索引从45秒到0.02秒——索引设计你真的会吗
本文实测5000万订单表:无索引查询45秒,加索引后仅0.02秒(提升2250倍)。详解索引原理、建索引时机、联合索引最左前缀、覆盖索引及隐式转换陷阱,干货不啰嗦!
|
15天前
|
SQL JSON 关系型数据库
慢SQL排查三板斧:SHOW PROCESSLIST + 慢查询日志 + EXPLAIN 实战
教你三招快速定位CPU 100%元凶:SHOW PROCESSLIST查活跃查询、开启慢日志+mysqldumpslow分析、EXPLAIN深度诊断SQL性能。干货不啰嗦,专治线上急症!
|
1月前
|
SQL 数据库
多表关联查询入门:LEFT JOIN、INNER JOIN一文搞懂|转行学DB第6天
本文通俗易懂地讲解了数据库多表查询的三种JOIN操作:INNER JOIN(内连接)只返回两表匹配的数据,适用于查询交集数据;LEFT JOIN(左连接)保留左表所有记录并匹配右表数据,适用于查询主表完整信息;RIGHT JOIN(右连接)则保留右表所有记录。
|
1月前
|
SQL 关系型数据库 MySQL
主键、外键和约束:让数据库“有规矩”才能不出错!|转行学DB第5天
本文用通俗易懂的语言讲解了主键(数据的唯一标识)、外键(表间关联)以及唯一约束、非空约束等其他常见约束规则。通过具体SQL示例展示了各种约束的使用方法,并分享了新手容易踩的坑和实用建议。
|
2天前
|
SQL 关系型数据库 MySQL
【MySQL百日打怪升级第14天】 LIMIT 分页的性能优化:深分页到底慢在哪?
本文深入剖析MySQL深分页(如`LIMIT 100000,20`)性能瓶颈:本质是OFFSET导致全量扫描与丢弃,页码越深,扫描行数线性增长。详解三种实战优化方案——游标分页(高效稳定,需有序唯一字段)、延迟关联(兼容OFFSET,索引覆盖减回表)、范围分页(极简但场景受限),并附EXPLAIN对比与避坑指南。(239字)
46 6
|
2天前
|
SQL 缓存 数据库
你还在用LIMIT 1000000,10?献上分页查询优化技巧
本文详解“深分页”陷阱:`LIMIT 1000000,10`为何慢?3种优化方案(游标法、子查询定位、延迟关联)实测提速数十倍,助你零成本提升SQL性能!
|
1天前
|
缓存 NoSQL 关系型数据库
告别低效COUNT(*)!数据库计数优化完全指南
本文详解`COUNT(*)`在千万级表中变慢的根源(InnoDB MVCC机制),对比`COUNT(*)`/`COUNT(1)`/`COUNT(列)`差异,并提供EXPLAIN估算、计数表、Redis缓存三大优化方案及选型建议。
|
23天前
|
SQL 人工智能 安全
AI圈开始“养马”了?聊聊龙虾退位、爱马仕登基
AI智能体“龙虾”(OpenClaw)的衰落与“爱马仕”(Hermes Agent)的崛起:前者因API限策与高危漏洞(CVSS 9.9)式微;后者以持久记忆、技能自生成、跨平台互通等实用能力破圈,成技术圈新“拐杖”。但技术无银弹,懂你的工具才是真助力。
|
15天前
|
SQL 算法 关系型数据库
两张百万级大表JOIN跑崩了?试试这3招
分享SQL优化干货:从2万亿次比较到秒级响应,三招搞定大表JOIN——先过滤再关联、JOIN字段必建索引、读多写少可反范式。附LEFT/INNER JOIN避坑、Hash Join启用指南及生产实操建议。