
MySQL EXPLAIN 命令详解
EXPLAIN 是 MySQL 中用于分析查询执行计划的关键命令,能够帮助开发者优化 SQL 查询性能。
通过 EXPLAIN,可以获取查询的执行顺序、使用的索引、扫描的行数等信息。
EXPLAIN 的基本用法
在 SQL 查询前加上 EXPLAIN 关键字即可查看执行计划:
EXPLAIN SELECT * FROM users WHERE id = 1;
EXPLAIN 的输出包含多个字段,每个字段提供了查询执行的不同信息:
- id:查询的序列号,表示查询中 SELECT 语句的执行顺序。
- select_type:查询类型,如 SIMPLE(简单查询)、PRIMARY(主查询)、SUBQUERY(子查询)等。
- table:查询涉及的表名。
- partitions:匹配的分区信息。
- type:访问类型,如 ALL(全表扫描)、index(索引扫描)、range(范围扫描)等。
- possible_keys:可能使用的索引。
- key:实际使用的索引。
- key_len:使用的索引长度。
- ref:显示索引的哪一列被使用。
- rows:预估需要扫描的行数。
- filtered:返回结果的行数占扫描行数的百分比。
- Extra:额外信息,如 Using where、Using index 等。
如何解读 EXPLAIN 结果
type 字段:这是优化查询的关键指标之一。
常见的类型按性能从高到低排序:
- system:表中只有一行数据。
- const:通过主键或唯一索引查询,返回一行数据。
- eq_ref:多表连接时使用主键或唯一索引作为关联条件。
- ref:使用非唯一索引查找。
- range:使用索引进行范围扫描。
- index:全索引扫描。
- ALL:全表扫描。
Extra 字段:提供额外的重要信息:
- Using index:表示查询使用了覆盖索引,无需回表。
- Using where:表示存储引擎检索行后再进行过滤。
- Using temporary:表示查询需要创建临时表。
- Using filesort:表示需要对结果进行外部排序。
使用 EXPLAIN 优化查询
识别全表扫描:如果 type 为 ALL,通常表示查询没有使用索引,需要检查是否可以为相关列添加索引。
检查索引使用情况:观察 possible_keys 和 key 字段,确保查询使用了合适的索引。如果 possible_keys 有值但 key 为 NULL,可能需要优化查询或索引。
减少扫描行数:rows 字段显示预估扫描的行数。数值过大可能意味着需要优化索引或查询条件。
避免临时表和文件排序:Extra 字段中出现 Using temporary 或 Using filesort 通常表示性能瓶颈,可以通过优化 GROUP BY 或 ORDER BY 子句来解决。
高级用法:EXPLAIN FORMAT=JSON
MySQL 8.0 及以上版本支持以 JSON 格式输出更详细的执行计划信息:
EXPLAIN FORMAT=JSON SELECT * FROM users WHERE id = 1;
JSON 格式的输出包含更多细节,如成本估算、子查询的执行计划等,适合深入分析复杂查询。


解析JSON格式的查询执行计划
该JSON结构展示了一个MySQL查询的执行计划(EXPLAIN输出),主要针对users 表的查询分析。以下是关键信息的拆解:
查询基础信息
- 查询成本:
query_cost 值为1.00,表示优化器估算的查询总成本较低。
- 表名:操作对象为
users 表,访问类型标记为const ,说明通过主键或唯一索引进行常量条件查询。
索引使用情况
- 可能使用的键:
possible_keys 仅包含PRIMARY ,说明查询仅考虑主键索引。
- 实际使用的键:
key 确认使用主键索引,且used_key_parts 显示仅用到id 列。
- 键长度:
key_length 为4字节,符合典型的INT类型主键存储大小。
数据访问细节
- 筛选效率:
rows_examined_per_scan 和rows_produced_per_join 均为1,结合filtered: 100.00% 表明精确命中一条记录。
- 引用类型:
ref 值为const ,说明WHERE条件使用常量值(如id = 123 )。
资源消耗
- 读取成本:
read_cost 为0.00,因数据可能已在缓存中。
- 计算成本:
eval_cost 为0.10,属于极低的计算开销。
- 前缀成本:
prefix_cost 为0.00,表示无多表连接时的累积成本。
涉及的列
used_columns 列出所有被访问的字段,包含用户权限、状态标记、时间戳等业务字段,如:
- 授权状态(
authorization )
- 封禁标记(
block )
- 黑白名单标识(
white , black )
- 时间信息(
created_at , updated_at )
性能优化建议
该查询已通过主键实现高效访问,无需额外优化。若需进一步验证,可检查:
- 表数据量是否影响缓存效率
- 高频查询是否适合使用覆盖索引
实际案例
假设有一个查询:
EXPLAIN SELECT u.name, o.amount
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE u.status = 'active'
ORDER BY o.created_at;
优化步骤:
- 确保 users 表的 status 字段和 orders 表的 user_id 字段有索引。
- 检查 ORDER BY 是否导致文件排序,考虑为 created_at 添加索引。
- 如果连接操作效率低,可以尝试调整连接顺序或使用 STRAIGHT_JOIN。
通过分析 EXPLAIN 结果并针对性优化,可以显著提升查询性能。
后续补充
... |
所有评论(0)