MySQL之explain 的type列 & Extra列

explain 可以分析 select 语句的执行,即 MySQL 的“执行计划。

一、type 列

MySQL 在表里找到所需行的方式。包括(由左至右,由最差到最好):

| All | index | range | ref | eq_ref | const,system | null |

ALL(所有)

全表扫描,MySQL 从头到尾扫描整张表查找行。

mysql> explain select * from a\G

...
         type: ALL

如果加上 limit 如 select * from a limit 100 MySQL 会扫描 100 行,但扫描方式不会变,还是从头到尾扫描。

index(索引)

根据索引来读取数据,如果索引已包含了查询数据,只需扫描索引树,否则执行全表扫描和All类似;

create table a(a_id int not null, key(a_id));

insert into a value(1),(2);

mysql> explain select a_id from a\G
...
         type: index

range(范围)

以范围的形式扫描索引

建表:

create table a(a_id int not null, key(a_id));

insert into a values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10);

mysql> explain select * from a where a_id > 1\G
...
         type: range

...

IN 比较符也会用 range 表示:

mysql> explain select * from a where a_id in (1,3,4)\G
...
         type: range
...

`

ref(引用)

非唯一性索引访问

建表:

create table a(a_id int not null, key(a_id));

insert into a values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10);

mysql> explain select * from a where a_id=1\G
...
         type: ref

...

eq_ref(等值引用)

使用有唯一性索引查找(主键或唯一性索引)

建表及插入数据:

create table a(id int primary key);

create table a_info(id int primary key, title char(1));

insert into a value(1),(2);

insert into a_info value(1, ‘a‘),(2, ‘b‘);

mysql> explain select * from a join a_info using(id);
...+--------+--------+...
...| table  | type   |...
...+--------+--------+...
...| a      | index  |...
...| a_info | eq_ref |...
...+--------+--------+...

此时 a_info 每条记录与 a 一一对应,通过主键 id 关联起来,所以 a_info 的 type 为 eq_ref。

删除 a_info 的主键:ALTER TABLE  `a_info` DROP PRIMARY KEY;

现在 a_info 已经没有索引了:

mysql> explain select * from a join a_info using(id);
+----+...+--------+--------+...

| id |...| table  | type   |...

+----+...+--------+--------+...

|  1 |...| a_info | ALL    |...

|  1 |...| a      | eq_ref |...

+----+...+--------+--------+...

这次 MySQL 调整了执行顺序,先全表扫描 a_info 表,再对表 a 进行 eq_ref 查找,因为 a 表 id 还是主键。

删除 a 的主键:alter table a drop primary key;

现在 a 也没有索引了:

mysql> explain select * from a join a_info using(id);
...+--------+------+...
...| table  | type |...
...+--------+------+...
...| a      | ALL  |...
...| a_info | ALL  |...
...+--------+------+...

现在两个表都使用全表扫描了。

建表及插入数据:

create table a(id int primary key);

create table a_info(id int, title char(1), key(id));

insert into a value(1),(2);

insert into a_info value(1, ‘a‘),(2, ‘b‘);

现在 a_info 表 id 列变为普通索引(非唯一性索引):

mysql> explain select * from a join a_info using(id) where a.id=1;
...+--------+-------+...
...| table  | type  |...
...+--------+-------+...
...| a      | const |...
...| a_info | ref   |...
...+--------+-------+...

a_info 表 type 变为 ref 类型了。

所以,唯一性索引才会出现 eq_ref (非唯一性索引会出现 ref ),因为唯一,所以最多只返回一条记录,找到后无需继续查找,因此比 ref 更快。

const(常量连接)

被称为“常量”,这个词不好理解,不过出现 const 的话就表示发生下面两种情况:

在整个查询过程中这个表最多只会有一条匹配的行,比如主键 id=1 就肯定只有一行,只需读取一次表数据便能取得所需的结果,且表数据在分解执行计划时读取。返回值直接放在 select 语句中,类似 select 1 AS f 。可以通过 extended 选择查看内部过程:

建表及插入数据:

create table a(id int primary key, c1 char(20) not null, c2 text not null, c3 text not null);

insert into a values(1, ‘asdfasdf‘, ‘asdfasdf‘, ‘asdfasdf‘), (2, ‘asdfasdf‘, ‘asdfasdf‘, ‘asdfasdf‘);

mysql> explain extended select * from a where id=1\G
...
         type: const
possible_keys: PRIMARY
          key: PRIMARY
...

用 show warnings 查看 MySQL 是如何优化的:

mysql> show warnings\G
...
Message: select ‘1‘ AS `id`,‘asdfasdf‘ AS `c1`,‘asdfasdf‘ AS `c2`,‘asdfasdf‘ AS
`c3` from `test`.`a` where 1

查询返回的结果为:

mysql> select * from a where id=1;
+----+----------+----------+----------+
| id | c1       | c2       | c3       |
+----+----------+----------+----------+
|  1 | asdfasdf | asdfasdf | asdfasdf |
+----+----------+----------+----------+

可以看出,返回结果中的字段值都以“值 AS 字段名”的形式直接出现在优化后的 select 语句中。

修改一下查询:

mysql> explain select * from a where id in(1,2)\G
...
         type: range

...

当返回结果超过 1 条时, type 便不再为 const 了。

重新建表及插入数据:

create table a (id int not null);

insert into a value(1),(2),(3);

mysql> explain select * from a where id=1\G
...
         type: ALL

目前表中只有一条 id=1 的记录,但 type 已为 ALL ,因为只有唯一性索引才能保证表中最多只有一条记录,只有这样 type 才有可能为 const 。

为 id 加普通索引后, type 变为 ref ,改为加唯一或主键索引后, type 便变为 const 了。

二、Extra 列

Extra表示附加信息,常见的有如下几种(也按查询效率从高到低排列):

  • Using index:表示使用索引,如果只有 Using index,说明他没有查询到数据表,只用索引表就完成了这个查询,这个叫覆盖索引。如果同时出现Using where,代表使用索引来查找读取记录, 也是可以用到索引的,但是需要查询到数据表。
  • Using where:表示条件查询,如果不读取表的所有数据,或不是仅仅通过索引就可以获取所有需要的数据,则会出现 Using where。如果type列是ALL或index,而没有出现该信息,则你有可能在执行错误的查询:返回所有数据。
  • Using filesort:不是“使用文件索引”的含义!filesort是MySQL所实现的一种排序策略,通常在使用到排序语句ORDER BY的时候,会出现该信息。
  • Using temporary:表示为了得到结果,使用了临时表,这通常是出现在多表联合查询,结果排序的场合。

如果EXPLAIN出现后面两个信息(Using filesort,Using temporary),而rows又比较大,通常意味着你需要调整查询语句,或者需要添加索引,总之需要尽量消除这两个信息。

时间: 2024-11-10 11:01:03

MySQL之explain 的type列 & Extra列的相关文章

MySQL的EXPLAIN的type

连接操作的类型 (1)SYSTEM CONST的特例,当表上只有一条元组匹配 (2)CONST WHERE条件筛选后表上至多有一条元组匹配时,比如WHERE ID = 2 (ID是主键,值为2的要么有一条要么没有) (3)EQ_REF 参与连接运算的表是内表(在代码实现的算法中,两表连接时作为循环中的内循环遍历的对象,这样的表称为内表). 基于索引(连接字段上存在唯一索引或者主键索引,且操作符必须是"="谓词,索引值不能为NULL)做扫描,使得对外表的一条元组,内表只有唯一一条元组与之

mysql中explain的type的解释

导语: 很多情况下,有很多人用各种select语句查询到了他们想要的数据后,往往便以为工作圆满结束了.这些事情往往发生在一些学生亦或刚入职场但之前又没有很好数据库基础的小白身上,但所谓闻道有先后,只要我们小白好好学习,天天向上,还是很靠谱的. 当一个sql查询语句被写出来之后,其实你的工作只完成了一小半,接下来更重要的工作是评估你自己写的sql的质量与效率.mysql为我们提供了很有用的辅助武器explain,它向我们展示了mysql接收到一条sql语句的执行计划.根据explain返回的结果我

MySQL中explain的type类型

|  ALL              |  全表扫描 |  index            |  索引全扫描 |  range            |  索引范围扫描,常用语<,<=,>=,between等操作 |  ref                |  使用非唯一索引扫描或唯一索引前缀扫描,返回单条记录,常出现在关联查询中 |  eq_ref           |  类似ref,区别在于使用的是唯一索引,使用主键的关联查询 |  const/system  |  单条记录

mysql explain中的type列含义和extra列的含义

很多朋友在用mysql进行调优的时候都肯定会用到explain来看select语句的执行情况,这里简单介绍结果中两个列的含义. 1 type列 官方的说法,说这列表示的是“访问类型”,更通俗一点就是:mysql找到需要的数据行的方式.一下就是从效率最差到最好顺序分别介绍下: All 这个就是所谓的全表扫描,没有用到任何的index,mysql就是从头到尾把整个表遍历一边,找到所需要的数据行.效率是最差的.如下图,这个表中的usertype不是索引,这个查询中没有用到任何索引,所以就出现了全表扫描

解析MYsql explain执行计划extra列输出

EXPLAIN Extra 列信息: explain Extra列输出包含了关于mysql如何解决query的额外信息,特别是出现Using filesort 和 using temporary时,应当格外注意: 1:Child of  'table' pushed [email protected] 在做join时下推到NDB存储引擎中,引用子表‘table’,当下推join支持时,应用与Mysql cluster: 2: const row not found 通过一个query sql 例

MySQL,排序,统计行转列

表 -- ------------------------------ Table structure for a-- ---------------------------- DROP TABLE IF EXISTS `a`; CREATE TABLE `a` ( `type` varchar(255) DEFAULT NULL, `name` varchar(255) DEFAULT NULL, `val` varchar(255) DEFAULT NULL ) ENGINE=InnoDB

MySQL插入数据时插入无效的列

1.错误描述 com.mysql.jdbc.exception:jdbc4.MySQLSyntaxErrorException:Unknown column 'man' in 'field list' 2.错误原因 数据库表中的字段:sno     sname    sage     ssex 插入数据时:          sno     sname    sage     man          本来是想插入ssex这个字段的值为"man",结果将man弄成了ssex字段名 3.

MySQL的explain

> 一.Explain 二.各项值 1.id 每个被独立执行的操作的标识,表示对象被操作的顺序:id值大,先被执行:如果相同,执行顺序从上到下. 若没有子查询和联合查询,id则都是1.Mysql会按照id从大到小的顺序执行query,在id相同的情况下,则从上到下执行. 2.select_type 查询中每个select子句的类型,提供了各种表示table列引用的使用方式的类型. (1)SIMPLE 简单的SELECT语句(不包括UNION操作或子查询操作) (2)PRIMARY/UNION P

MySQL中EXPLAIN详解

MySQL中EXPLAIN详解 explain显示了mysql如何使用索引来处理select语句以及连接表.可以帮助选择更好的索引和写出更优化的查询语句. 使用方法,在select语句前加上explain就可以了: 如:explain select username,first_name form hx,itlearner where a.id=b.id EXPLAIN列的解释: id:本次 select 的标识符.在查询中每个 select都有一个顺序的数值. select_type :查询类