MySQL 执行计划详解
(admin@g1-db-test-v07:5001)[jinhailan]>explain select * from t1; +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+ | 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100.00 | NULL | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
explain输出
id:在一个大的查询语句中每个SELECT
关键字都对应一个唯一的id
select_type:SELECT
关键字对应的那个查询的类型
table:表名
partitions:匹配的分区信息
type:针对单表的访问方法
possible_keys:可能用到的索引
key:实际使用的索引
key_len:实际使用到的索引长度
ref:当使用索引列等值查询时,与索引列进行等值匹配的对象信息
rows:预估的需要读取的记录条数
filtered:某个表经过搜索条件过滤后剩余记录条数的百分比
Extra:一些额外的信息
执行计划输出详解
table
不论我们的查询语句有多复杂,里边儿包含了多少个表,到最后也是需要对每个表进行单表访问的,EXPLAIN语句输出的每条记录都对应着某个单表的访问方法,该条记录的table列代表着该表的表名
id
查询语句中每出现一个SELECT
关键字,设计MySQL
的大叔就会为它分配一个唯一的id
值
对于连接查询来说,一个SELECT
关键字后边的FROM
子句中可以跟随多个表,所以在连接查询的执行计划中,每个表都会对应一条记录,但是这些记录的id值都是相同的
(admin@g1-db-test-v07:5001)[jinhailan]>EXPLAIN SELECT * FROM t1 INNER JOIN t2; +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------------+ | 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100.00 | NULL | | 1 | SIMPLE | t2 | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100.00 | Using join buffer (Block Nested Loop) | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------------+ 2 rows in set, 1 warning (0.00 sec)
在连接查询的执行计划中,每个表都会对应一条记录,这些记录的id列的值是相同的,出现在前边的表表示驱动表,出现在后边的表表示被驱动表
查询优化器可能对涉及子查询的查询语句进行重写,从而转换为连接查询
Extra
Using filesort:
很多情况下排序操作无法使用到索引,只能在内存中(记录较少的时候)或者磁盘中(记录较多的时候)进行排序,设计MySQL
的大叔把这种在内存中或者磁盘上进行排序的方式统称为文件排序(英文名:filesort
)
Using temporary:去重,排序.
执行许多包含DISTINCT
、GROUP BY
、UNION
等子句的查询过程中,如果不能有效利用索引来完成查询,MySQL
很有可能寻求通过建立内部的临时表来执行查询
MySQL
会在包含GROUP BY
子句的查询中默认添加上ORDER BY
子句
不想为包含GROUP BY
子句的查询进行排序,需要我们显式的写上ORDER BY NULL
Start temporary, End temporary:先看一下自查询优化部分
LooseScan:在将In
子查询转为semi-join
时,如果采用的是LooseScan
执行策略,则在驱动表执行计划的Extra
列就是显示LooseScan
提示
FirstMatch(tbl_name):在将In
子查询转为semi-join
时,如果采用的是FirstMatch
执行策略,则在被驱动表执行计划的Extra
列就是显示FirstMatch(tbl_name)
提示