Mysql

关注公众号 jb51net

关闭
首页 > 数据库 > Mysql > mysql explain

MySQL EXPLAIN详细解析

作者:Java 码农

EXPLAIN是SQL性能优化的关键工具,它展示了MySQL如何执行一条SQL 语句,通过分析它的结果,你可以找出查询的瓶颈并进行优化,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧

EXPLAIN 是 SQL 性能优化的关键工具,它展示了 MySQL 如何执行一条 SQL 语句。通过分析它的结果,你可以找出查询的瓶颈并进行优化。

下面我将对 EXPLAIN 进行详细解析。

一、什么是 EXPLAIN?

EXPLAIN 关键字可以放在 SELECTDELETEINSERTREPLACE 或 UPDATE 语句之前,MySQL 会返回该语句的执行计划,而不是真正执行它。

执行计划揭示了 MySQL 优化器决定如何访问表、使用哪些索引、表之间的连接方式等信息。

基本语法:

EXPLAIN your_sql_statement;
-- 例如
EXPLAIN SELECT * FROM users WHERE name = 'John';

在 MySQL 8.0 之后,推荐使用 EXPLAIN FORMAT=TRADITIONAL(默认格式),或者更详细的 EXPLAIN ANALYZE(MySQL 8.0.18+ 引入,会实际执行查询并给出更精确的分析)。

二、EXPLAIN 输出列详解

执行 EXPLAIN 后,你会得到一个包含多列的结果集。以下是这些列的含义,其中前几列(type, key, rows, Extra)最为重要

列名描述重要性
id查询中每个 SELECT 子句的唯一标识符。如果相同,则按顺序执行;如果不同,id 越大优先级越高(先执行)。
select_type查询的类型,如 SIMPLE, PRIMARY, SUBQUERY, DERIVED 等。
table正在访问的表名。
partitions匹配的分区,非分区表则为 NULL。
type连接类型 或 访问类型。这是衡量查询性能的最关键指标之一。
possible_keys查询中可能用到的索引。
key查询中实际决定使用的索引。为 NULL 则表示未使用索引。
key_len使用的索引键的长度。可用于判断是否充分利用了复合索引。
ref显示索引的哪一列被使用了,通常是一个常量(const)或另一个表的列名。
rowsMySQL 估计为了找到所需的行而需要读取的行数。这个值越小越好。
filtered表示存储引擎返回的数据在服务器层过滤后,剩余多少比例满足查询条件。理想是 100。
Extra包含不适合在其他列显示的额外信息,非常多的重要信息在这里。

三、核心列深度解析

1.type(访问类型)

性能从最优到最差排序如下:

system > const > eq_ref > ref > range > index > ALL

system:表只有一行记录(等于系统表),是 const 类型的特例。

const:通过索引一次就找到了,用于比较 主键索引 或 唯一索引 与常数值。速度极快。

EXPLAIN SELECT * FROM users WHERE id = 1;
-- `id` 是主键

eq_ref:在连接查询时,使用 主键 或 唯一非空索引 进行关联。对于来自前表的每一行,从本表中只返回一行。这是除了 system 和 const 之外最好的连接类型。

EXPLAIN SELECT * FROM users u 
JOIN orders o ON u.id = o.user_id;
-- `o.user_id` 是 `users` 表的主键 `id` 的外键,并且是唯一索引

ref:使用 非唯一性索引 进行扫描,返回匹配某个单独值的所有行。

EXPLAIN SELECT * FROM users WHERE name = 'John';
-- `name` 字段上有一个普通索引(非唯一)

range:只检索给定范围的行,使用一个索引来选择行。关键运算符是 BETWEEN><IN 等。

EXPLAIN SELECT * FROM users WHERE id > 10;
EXPLAIN SELECT * FROM users WHERE id IN (1, 2, 3);

index全索引扫描。遍历整个索引树来查找数据,比 ALL 快一点,因为索引文件通常比数据文件小。

EXPLAIN SELECT id FROM users;
-- 查询的列 `id` 正好是索引的一部分,直接从索引中读取,无需回表

ALL全表扫描。性能最差,意味着 MySQL 会遍历整张表来找到匹配的行。必须优化

2.rows(预估行数)

这不是查询结果的行数,而是 MySQL 为了找到目标记录,预估需要扫描多少行。这是一个基于统计信息的预估值。这个值越小越好,说明查询效率高。

3.Extra(额外信息)

这里包含大量细节,是判断查询质量的另一个关键。

-- 假设在 `name` 和 `age` 上有一个复合索引 (name, age)
EXPLAIN SELECT name, age FROM users WHERE name = 'John';

四、实战分析示例

假设我们有两张表:

查询1:简单的等值查询

EXPLAIN SELECT * FROM users WHERE name = 'Alice';

可能的结果分析:

结论: 这是一个高效的查询。

查询2:连接查询

EXPLAIN SELECT u.name, o.amount 
FROM users u 
JOIN orders o ON u.id = o.user_id 
WHERE u.name = 'Bob';

可能的结果分析(对于 orders 表这一行):

结论: 连接效率很高,因为双方都使用了索引。

查询3:性能不佳的查询

EXPLAIN SELECT * FROM users WHERE email = 'alice@example.com' ORDER BY name;

可能的结果分析:

结论: 这是一个灾难性的查询。它进行了全表扫描,并且还有一个昂贵的文件排序。
优化建议:

五、进阶工具:EXPLAIN ANALYZE (MySQL 8.0.18+)

EXPLAIN ANALYZE 会实际执行查询,并提供一个更详细的、包含实际执行时间的分析报告。

EXPLAIN ANALYZE SELECT * FROM users WHERE name = 'John';

输出格式类似于:

-> Index lookup on users using idx_name (name='John')  (cost=0.35 rows=1) (actual time=0.025..0.027 rows=1 loops=1)

它提供了:

这比传统的 EXPLAIN 提供了更精确的性能视图。

总结

检查点目标
type 列至少达到 range 级别,最好能到 ref。避免 ALL
key 列确保查询实际使用了合适的索引,不为 NULL
rows 列预估扫描行数尽可能小。
Extra 列追求出现 Using index。警惕 Using temporary 和 Using filesort

熟练掌握 EXPLAIN 是每个后端开发者和 DBA 的必备技能,它能帮助你从“猜测”优化变为“数据驱动”的优化。

到此这篇关于MySQL EXPLAIN 详解与优化指南的文章就介绍到这了,更多相关mysql explain内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文