每一行都是一个执行步骤
id:执行顺序
select type:查询语句的操作类型
table:表
parititions:表分区
type:查询所用的访问类型
possible-keys:可能用到的索引
key:实际查询用到的索引
key-len:所使用的索引的长度(主要是看联合索引)
ref:使用索引时,与索引进行等值匹配的列或者常量
rows:预计扫描的行数(索引行数或者表记录行数)
filtered:表示符合查询条件的数据百分比
extra:额外信息
id列
id序号相同:顺序是从上往下
id序号不同,顺序是从大到小
id列为null,最后执行
table
表名
derived:派生表
派生表(derived table)在 MySQL 中主要是在服务器层面(server layer)管理的,而不是在存储引擎层面。
存储位置
服务器层面:派生表由 MySQL 服务器层管理。服务器层负责解析 SQL 查询、优化查询计划、生成派生表并使用它们。具体来说,服务器层负责将子查询的结果存储在临时表中。
存储引擎层面:存储引擎负责物理存储数据。在派生表的情况下,如果派生表的结果较大,需要写入磁盘,那么存储引擎(如 InnoDB 或 MyISAM)会参与存储这些临时数据。但是,派生表本身的管理和生命周期由服务器层负责。
生命周期
临时性:派生表在查询执行期间临时存在,一旦查询结束,派生表就被销毁。这意味着它们的生命周期仅限于生成它们的查询上下文。
销毁:查询执行完毕后,派生表及其数据会被立即销毁,不会保留在内存或磁盘上。
生成过程
遍历生成:派生表的生成确实需要遍历子查询中的相关表。例如,如果子查询中涉及到 users 表,MySQL 会遍历 users 表以生成派生表的结果集。如果条件可以使用索引来获得派生表,那么就会使用索引。
例子
csharp
+----+-------------+--------------+-------+---------------+---------+---------+------+--------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------+-------+---------------+---------+---------+------+--------+-----------------------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 2 | |
| 2 | DERIVED | users | range | age | age | 4 | NULL | 2 | Using where; Using filesort |
+----+-------------+--------------+-------+---------------+---------+---------+------+--------+-----------------------------+
id2的select_type为derived代表生成users的派生表,id为1的table为derived2代表使用id为2的派生表来遍历。
select type:查询类型
用来区分普通查询,子查询,联合查询(复杂查询)。
- SIMPLE:简单的SELECT查询,不包含子查询或UNION。
- PRIMARY:最外层的SELECT查询。如果查询中包含子查询或联合查询,则最外层的查询是PRIMARY类型。
- UNION:UNION中的第二个或后续的SELECT查询。
- DEPENDENT UNION:UNION中的第二个或后续的SELECT查询,依赖于外部查询。
- UNION RESULT:用于表示UNION的结果集。
- SUBQUERY:子查询中的第一个SELECT。
- DEPENDENT SUBQUERY:子查询中的第一个SELECT,依赖于外部查询。
- DERIVED:派生表的SELECT(例如,在FROM子句中使用的子查询)。
simple:不包含union和子查询,那么就是简单查询
连接查询也会被标记为simple
primary:复杂查询中的最外层的查询,通常union和子查询id为1的查询
subquery:子查询,不依赖于外部
csharp
explain select *,(select productName form products where id=1) from user.
dependent subquery:子查询,依赖于外部
例子:
csharp
explain select *,(select productName from products where products.id=user.product) from user;
derived:派生表,from中子查询
csharp
explain select * from (select * from user where user_id>=1);
派生表合并优化的基本思想是将派生表的查询嵌入到主查询中,直接生成一个更复杂的查询,从而避免创建临时表。
当派生表合并优化生效时,使用 EXPLAIN 来检查查询的执行计划时,不会显示 derived 类型的查询,而是会显示 simple 类型的查询。
union
csharp
select * from (
select * from user where id<3
union
select * from user where length(name)<6
union
sleect * from user where id>300
);
from子查询,第一个select会作为derived的派生表,其余都是union,然后最外层的是primary。
如果是union all 会生成一个临时表去重。
dependent union
possible_key:可能使用的索引
key:实际使用的索引
type:查询使用的访问类型
system:表只有一条数据(innodb没有)
const:就是条件为主键或者唯一索引的常量等于
eq_ref:使用两个表的主键或者唯一索引连接的select,使用主键或者唯一索引来访问
ref:ref就是使用非唯一索引进行查找或者使用非唯一索引连接的表,使用非唯一索引进行访问
range:有索引的范围查找
index:表示查询使用了覆盖索引,可以直接从索引中获取所需的数据,无需回表
all:全表扫描
ken_len:使用的索引的最大长度
主要看,覆盖索引使用了多长
CHAR(n):固定长度字符串,占据 n 字节的存储空间,不管实际存储的字符数是多少。
int:4字节
varchar:如果是utf-8,那就是3n+2,2用来存储实际varchar的字数
如果没有not null,那么会有一字节存储是否为null。
ref:显示使用的非唯一索引名称
rows:扫描的行数
filtered:符合查询条件的数据的百分比
Extra
using index:覆盖索引
using where:不使用索引
using index condition:用索引找到后回表
using filesort:在内存或者在磁盘中排序:需要添加索引从而直接取出排序后的行