MySQL知识总结
《MySQL是怎样运行的》知识总结
15 Explain
表结构
-- auto-generated definition
create table single_table (
id int auto_increment primary key,
key1 varchar(100) null,
key2 int null,
key3 varchar(100) null,
key_part1 varchar(100) null,
key_part2 varchar(100) null,
key_part3 varchar(100) null,
common_field varchar(100) null,
constraint uk_key2
unique (key2)
);
create index idx_key1
on single_table (key1);
create index idx_key3
on single_table (key3);
create index idx_part
on single_table (key_part1, key_part2, key_part3);
MySQL优化器基于成本、规则对查询语句进行优化后,就会生成一个执行计划,使用explain
语句可以查看某个查询语句的执行计划
explain select 1;
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
explain表格解释
列名 | 描述 |
---|---|
id | 每个select 关键字对应一个唯一Id |
select_type | select关键字对应的查询类型 |
table | 对应单表访问的表名 |
partitions | 匹配的分区信息,不介绍 |
type | 对单表进行访问的访问方法 |
possible_keys | 查询可能用到的索引 |
key | 实际使用的索引 |
key_len | 实际使用索引的长度 |
ref | 使用索引列进行等值匹配时,与索引列进行匹配的信息 |
rows | 预估读取记录的条数 |
filtered | 对预计读取的记录,进行查询条件过滤后,满足条件的记录的比值 |
Extra | 执行计划的额外信息 |
id
查询语句可能出现多个
select
子句,每出现一个select
子句,MySQL都会为他分配一个唯一的Id。
对于连接查询来说,一个
select
子句后面的from
子句可以跟着多个表,在连接查询的执行计划中
,每个表都对应一条记录,但这些记录的id
是相同的,出现在前面的记录对应的表是驱动表
explain
select *
from single_table s1
join single_table s2;
id | 1 |
1 |
select_type | SIMPLE | SIMPLE |
table | s1 | s2 |
partitions | NULL | NULL |
type | ALL | ALL |
possible_keys | NULL | NULL |
key | NULL | NULL |
key_len | NULL | NULL |
ref | NULL | NULL |
rows | 9937 | 9937 |
filtered | 100 | 100 |
Extra | NULL | Using join buffer (Block Nested Loop) |
包含子查询的查询语句,就可能涉及到多个select关键字,所以在包含子查询的查询语句的执行计划中,每个
select
子句都对应一个唯一id。
explain
select *
from single_table s1
where key1 in (select key1 from single_table s2)
or key3 = 'a';
id | 1 |
2 |
select_type | PRIMARY | SUBQUERY |
table | s1 | s2 |
partitions | NULL | NULL |
type | ALL | index |
possible_keys | idx_key3 | idx_key1 |
key | NULL | idx_key1 |
key_len | NULL | 303 |
ref | NULL | NULL |
rows | 9937 | 9937 |
filtered | 100 | 100 |
Extra | Using where | Using index |
优化器可能会对涉及子查询的查询语句进行重写,从而转换为
半连接
explain
select *
from single_table s1
where key1 in (select common_field from single_table s2 where s1.key3 = 'a');
id | 1 |
1 |
select_type | SIMPLE | SIMPLE |
table | s2 | s1 |
partitions | NULL | NULL |
type | ALL | ref |
possible_keys | NULL | idx_key1,idx_key3 |
key | NULL | idx_key1 |
key_len | NULL | 303 |
ref | NULL | mysql_run.s2.common_field |
rows | 9937 | 2 |
filtered | 100 | 2.1 |
Extra | Using where; Start temporary | Using where; End temporary |
使用union时,会把多个查询得到的结果进行去重操作,MySQL会在内部创建一个
临时表
。id为
Null
,表明这个临时表是为了合并两个查询结果而创建的。
explain
select *
from single_table s1
union
select *
from single_table s2;
id | 1 | 2 | NULL |
select_type | PRIMARY | UNION | UNION RESULT |
table | s1 | s2 | <union1,2 > |
partitions | NULL | NULL | NULL |
type | ALL | ALL | ALL |
possible_keys | NULL | NULL | NULL |
key | NULL | NULL | NULL |
key_len | NULL | NULL | NULL |
ref | NULL | NULL | NULL |
rows | 9937 | 9937 | NULL |
filtered | 100 | 100 | NULL |
Extra | NULL | NULL | Using temporary |
使用
union all
,不会对结果集进行去重,不需要创建临时表
explain
select *
from single_table s1
union all
select *
from single_table s2;
id | 1 | 2 |
select_type | PRIMARY | UNION |
table | s1 | s2 |
partitions | NULL | NULL |
type | ALL | ALL |
possible_keys | NULL | NULL |
key | NULL | NULL |
key_len | NULL | NULL |
ref | NULL | NULL |
rows | 9937 | 9937 |
filtered | 100 | 100 |
Extra |