MYSQL执行计划

MySQL 执行计划(Execution Plan)是 MySQL 优化器为一条 SQL 语句生成的具体执行方案,它描述了数据库将如何执行这条语句,包括:

  • 如何读取表数据(全表扫描还是使用索引)
  • 表之间的连接顺序和连接方式(如嵌套循环、哈希连接)
  • 数据过滤和排序的方式等

简单来说,执行计划就像 SQL 语句的 “执行路线图”,通过分析它可以了解语句的性能瓶颈,进而优化查询效率。

如何查看执行计划?

使用 EXPLAIN 或 EXPLAIN ANALYZE 命令,在 SQL 语句前添加即可:

-- 查看执行计划(不实际执行语句) EXPLAIN SELECT * FROM users WHERE age > 30; -- 查看执行计划并实际执行(MySQL 8.0+,返回更精确的耗时数据) EXPLAIN ANALYZE SELECT * FROM users WHERE age > 30;

执行计划核心字段解析

执行计划返回的结果包含多个字段,其中关键字段如下:

字段名含义说明
id查询中每个操作的标识,值相同表示同一层级,值越大优先级越高
select_type查询类型(如 SIMPLE 简单查询、PRIMARY 主查询、SUBQUERY 子查询等)
table当前操作涉及的表名
type访问类型(最重要的字段之一),表示数据的读取方式,性能从好到差大致为:
system > const > eq_ref > ref > range > index > ALL
ALL 表示全表扫描,性能最差)
possible_keys可能使用的索引列表(仅供参考,不一定实际使用)
key实际使用的索引名称(NULL 表示未使用索引)
key_len使用的索引长度(越长表示使用的索引字段越多,如复合索引可能只用到部分字段)
rows预估需要扫描的行数(值越小越好)
Extra额外信息(非常重要),如:
Using index:使用覆盖索引(性能好)
Using where:需要过滤数据
Using filesort:需要额外排序(性能差)
Using temporary:使用临时表(性能差)

通过执行计划可以快速定位 SQL 性能问题,例如:

  • 若 type 为 ALL 且 key 为 NULL,说明发生了全表扫描,可能需要添加索引
  • 若 Extra 出现 Using filesort 或 Using temporary,说明需要优化排序或分组逻辑
  • 若 rows 远大于实际数据量,可能是统计信息过时,需要更新表统计信息(ANALYZE TABLE 表名

示例

下面有一个实际例子,我们可以通过执行计划就可以分析出来这句sql执行慢的原因

首先我们创建一张表,有多个索引

CREATE TABLE `book` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
  `creator` varchar(50) NOT NULL COMMENT '创建人',
  `content` text NOT NULL COMMENT '消息内容',
  `source` enum('api', 'user') NOT NULL COMMENT '来源(api或user)',
  PRIMARY KEY (`id`),
  KEY `idx_source_creator` (`source`, `creator`),
  KEY `idx_creator_create_time` (`creator`, `create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='消息表';

现在我们要执行一个查询语句

EXPLAIN
SELECT 
    source, 
    creator, 
    DATE(create_time) AS create_date,
    COUNT(*) AS message_count
FROM 
    book
WHERE 
    source = 'api'
    AND creator = 'specific_user'
GROUP BY 
    source, 
    creator, 
    DATE(create_time)
ORDER BY 
    create_date DESC;

我们想要分析这个语句的执行计划,可以这么写

-- 查看执行计划(不实际执行语句,快速分析索引和执行逻辑)
EXPLAIN
SELECT 
    source, 
    creator, 
    DATE(create_time) AS create_date,
    COUNT(*) AS message_count
FROM 
    book
WHERE 
    source = 'api'
    AND creator = 'specific_user'
GROUP BY 
    source, 
    creator, 
    DATE(create_time)
ORDER BY 
    create_date DESC;

结果如下:

这个执行计划中各个字段如下:

select_type:SIMPLE

table: book

partitions: NULL

type: ref

possible_keys:idx_source_creator,idx_creator_create_time

key:idx_source_creator

key_len:203

ref:const,const

rows:1

filtered:100.00

Extra: Using index condition; Using temporary; Using filesort

分析

我们可以看到在这个执行计划中最终选择的索引是idx_source_creator,我们知道在mysql索引选择的时候会选择可以忽略最多数据的,所以当我们多索引的时候就要固定查询条件,而且在mysql执行一条语句的时候仅仅只会走一个索引,因此当走了idx_source_creator索引后,即便我们给create_time建立了索引也不会走这个,所以在最后排序的时候Extra是要走多个的,特别是Using filesort这个是需要额外进行排序,那么在高并发的场景下,这样的排序方式会直接造成sql执行很慢堵塞系统,我们就可以按照执行计划来进行慢查询的排查

优化

选择id进行排序或者将create_time加入到sql选择的索引中才可以避免在高并发场景造成sql执行慢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值