MySQL执行计划分析
# MySQL执行计划分析
在数据库性能优化中,分析和理解SQL语句的执行计划是非常重要的一步。MySQL 提供了 EXPLAIN
语句来查看查询的执行计划。通过 EXPLAIN
,我们可以了解查询是如何执行的,并找出可能的性能瓶颈。
# 使用 EXPLAIN
命令
你可以通过在查询前加上 EXPLAIN
关键字来查看执行计划。例如:
EXPLAIN SELECT * FROM users WHERE id = 1;
1
# 执行计划的各个字段解释
执行计划返回的结果包含多个字段,每个字段都有其特定的含义。以下是常见字段的解释:
- id:查询的序列号,表示查询中执行 select 子句或操作表的顺序。
- select_type:查询的类型,常见的有:
SIMPLE
:简单的 SELECT 查询,不包含子查询或 UNION。PRIMARY
:最外层的 SELECT。SUBQUERY
:子查询中的第一个 SELECT。DERIVED
:派生表(子查询的 FROM 子句中的子查询)。
- table:当前查询操作的表。
- type:连接类型,表示 MySQL 如何查找表中的行。常见类型有:
ALL
:全表扫描。index
:全索引扫描。range
:范围扫描。ref
:使用非唯一索引扫描。eq_ref
:使用唯一索引扫描。const
,system
:表中最多有一个匹配行。
- possible_keys:查询中可能使用的索引。
- key:实际使用的索引。
- key_len:使用的索引的长度。
- ref:列出索引的哪一列被使用。
- rows:MySQL 估计为找到所需行而需要读取的行数。
- Extra:额外信息,可能包含一些重要的提示信息,如
Using index
(使用索引覆盖扫描)、Using where
(使用WHERE子句来过滤)、Using temporary
(使用临时表)、Using filesort
(使用文件排序)等。
# 查询执行的类型
查询执行的类型描述了查询是如何执行的。所有值的顺序从最优到最差排序为:
笔记
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
- system:表仅有一行(等同于 system 表),这是最优的情况。
- const:表最多有一个匹配行,使用常量值对表进行查找。通常用于主键或唯一索引。
- eq_ref:对每个行组合,从其他表中读取一行。通常用于主键或唯一索引,并且使用的是连接查询。
- ref:非唯一索引扫描,对匹配某个单独值的所有行进行查找。常用于使用非唯一索引或唯一索引的前缀。
- range:范围扫描,检索指定范围内的行。通常用于
BETWEEN
、>、<
等范围条件。 - index:全索引扫描,扫描索引树中的所有行,而不读取表数据。与
ALL
类似,但速度更快,因为只需扫描索引。 - ALL:全表扫描,这是最差的情况。MySQL 必须读取整个表来找到匹配的行。
# key_len
:使用索引的长度
key_len
表示在查询中使用的索引的字节数。以下是 key_len
的几个重要方面:
- 计算方式:
key_len
是索引中列的长度总和,包括前缀长度(如果是前缀索引)。对于多列索引,key_len
是这些列长度的总和。 - 影响因素:
- 数据类型:不同的数据类型占用不同的字节数。例如,
INT
类型占用 4 个字节,CHAR(10)
类型占用 10 个字节。 - 字符集:对于字符串类型,字符集会影响
key_len
。例如,UTF-8 编码的字符占用更多字节。 - 列定义:如果索引是部分索引(即前缀索引),
key_len
会根据定义的前缀长度计算。
- 数据类型:不同的数据类型占用不同的字节数。例如,
# 示例分析
假设我们有如下查询:
EXPLAIN SELECT * FROM orders WHERE order_date = '2023-01-01';
1
结果可能如下:
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | orders | ref | order_date | order_date | 4 | const | 5 | Using where |
分析结果:
- id: 查询中只有一个 SELECT 语句,所以 id 为 1。
- select_type: 简单查询,没有子查询,类型为 SIMPLE。
- table: 查询的表是
orders
。 - type: 连接类型为
ref
,表示使用了非唯一索引。 - possible_keys: 可能使用的索引为
order_date
。 - key: 实际使用的索引为
order_date
。 - key_len: 使用索引的长度为 4。
- ref: 使用常量
const
进行查找。 - rows: 估计需要读取 5 行数据。
- Extra: 使用了 WHERE 子句来过滤数据。
# 优化建议
- 索引优化:确保查询条件中的列上有合适的索引。
- 避免全表扫描:尽量避免
type
为ALL
的全表扫描,可以通过增加索引来优化。 - 减少返回的列:尽量只选择需要的列,而不是使用
SELECT *
。 - 分析慢查询:使用
SHOW SLOW LOGS
或者SET long_query_time
参数来找出慢查询并优化。
上次更新: 8/28/2024
- 01
- GPT分区使用 parted 扩展分区的操作流程 原创08-28
- 02
- VictoriaMetrics 集群版安装与配置 原创08-24
- 03
- Kubernetes (k8s) 相关名词详解 原创06-27