MySQL执行计划
# MySQL 执行计划 EXPLAIN
# 介绍
使用 EXPLAIN 命令来查看某查询语句的执行计划,如:
EXPLAIN select name from Student where id = 2;
1
可以查看到执行结果:
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | lecture | (NULL) | const | PRIMARY | PRIMARY | 8 | const | 1 | 100.00 | (NULL) |
下面解释一下这些参数的含义:
- id:查询序列号,几个查询语句就有几行。id 越前优先级越高,越先执行
- select_type:查询中每个 SELECT 子句的类型
- SIMPLE:简单 SELECT 查询,未使用 UNION 和子查询
- PRIMARY:查询包含任何复杂的子部分则被标记为 PRIMARY,PRIMARY 为最外层查询,最后执行
- SUBQUERY:在 SELECT 或 WHERE 中包含的子查询
- UNION:第 2 个 SELECT 在 UNION 只会,则被标记为 UNION
- DEPENDENT UNION:含有 UNION 查询的第二个或最后一个表,依赖外部的查询
- table:此处查询访问的表
- partitions:该参数用于记录使用的分区信息,NULL 表示该表是不是分区表
- type:连接类型,优化 sql 的重要字段,是判断 sql 性能和优化程度重要指标
- 执行效率 system > const > eq_ref > ref > range > index > ALL
- system:是 const 的一种特例,只有一行满足条件。例如:只有一条数据的系统表
- const:主键索引或者唯一索引,只能查到一条数据的 SQL
- eq_ref:通常出现在多表的 join 查询,表示对于前表的每一个结果,,都只能匹配到后表的一行结果。一般是唯一性索引的查询(UNIQUE 或 PRIMARY KEY)。
- system,const,eq_ref,都是可遇而不可求的,基本上很难优化到这个状态
- ref:查询用到了非唯一性索引,或者关联操作只使用了索引的最左前缀
- range:索引范围扫描,如果 where 后面是 between and 或 <或 > 或 >= 或 <=或 in 这些,type 类型就为 range
- index:Full Index Scan,查询全部索引中的数据(比不走索引要快)
- all:Full Table Scan,如果没有索引或者没有用到索引,type 就是 ALL。代表全表扫描。
- possible keys:可能会走的索引
- key:真正走的索引
- key_len:索引长度,估计值,可能用于联合索引走了几个索引的判断,较长的索引长度可能会导致较慢的查询性能。
- ref:命中索引的字段名,等值查询会是 const
- rows:读取的数据量,越少越优
- filterd:是百分比参数,估计值,命中字段占总行数比例,越高越好
- extra:其他信息,比如是否排序,是否覆盖索引等待
# 简单案例
假设 corpID 类型为 varchar(20),charset:utf8mb4,并且建立索引执行以下命令:
explain select * from platform_company_info where CorpID=1297689;
或
explain select corpName from platform_company_info where CorpID=1297689;
1
2
3
2
3
执行结果
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | xxxxxxx | (NULL) | ALL | ix_xx | (null) | (null) | (null) | 9000 | 10 | Using where |
- select_type:简单 SELECT 查询,未使用 UNION 和子查询
- type:ALL 全表扫描
- possible_keys:可能会走的索引,但是没有走
- rows:读取的数据量,读取了9000条,全表都读取了
- filtered:命中比例,应该远小于1,不准确
explain select * from platform_company_info where CorpID='1297689';
或
explain select corpName from platform_company_info where CorpID='1297689';
1
2
3
2
3
执行结果
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | xxxxxxx | (NULL) | ref | ix_xx | ix_xx | 82 | const | 1 | 100 | (NULL) |
- type:ref,查询用到了非唯一性索引
- possible_keys:可能会走的索引,与真实走的相同
- key:真正走的索引 ix_xx
- key_len:索引的长度,估计值,82个字节,估计索引长度应该为:20 * 4 + 1 = 81,utf8mb4中一个字符占4个字节,一个字节用于存储字段长度。
- ref:命中索引的字段名,等职查询是 const
- rows:命中行数,1行
- filtered:命中比例,100%
GBK编码:1个字符占用2个字节
UTF8编码:1个字符占用3个字节
UTF8MB4编码:1个字符占用4个字节
explain select * from platform_company_info where CorpID>='1297689';
1
执行结果
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | xxxxxxx | (NULL) | range | ix_xx | ix_xx | 82 | const | 555 | 100 | Using index condition |
type:range 索引范围扫描
编辑 (opens new window)
上次更新: 2024/04/26, 17:38:20