首页 > 数据库 >MySQL的执行计划详解(Explain)

MySQL的执行计划详解(Explain)

时间:2023-07-22 16:23:42浏览次数:37  
标签:Explain actor 查询 索引 详解 select MySQL id film

MySQL的执行计划详解(Explain)

1、MySQL执行计划的定义

在 MySQL 中可以通过 explain 关键字模拟优化器执行 SQL语句,从而知道 MySQL 是如何处理 SQL 语句的。

2、MySQL整个查询的过程
• 客户端向 MySQL 服务器发送一条查询请求
• 服务器首先检查查询缓存,如果命中缓存,则立刻返回存储在缓存中的结果。否则进入下一阶段
• 服务器进行 SQL 解析、预处理、再由优化器生成对应的执行计划
• MySQL 根据执行计划,调用存储引擎的 API 来执行查询
• 将结果返回给客户端,同时缓存查询结果
注意:只有在8.0之前才有查询缓存,8.0之后查询缓存被去掉了

3、如何启动执行计划
explain select 投影列 FROM 表名 WHERE 条件

4、Explain分析示例

CREATE TABLE `actor` (
`id` int(11) NOT NULL,
`name` varchar(45) DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `film` (
`id` int(11) NOT NULL,
`name` varchar(10) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `film_actor` (
`id` int(11) NOT NULL,
`film_id` int(11) NOT NULL,
`actor_id` int(11) NOT NULL,
`remark` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_film_actor_id` (`film_id`,`actor_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

1 EXPLAIN select * from actor;

 

注意:如果有join连接查询,会输出两行

4、explain的 两个变种(我的版本是5.7)
explain extended:会在 explain 的基础上额外提供一些查询优化的信息。紧随其后通过 show warnings 命令可以得到优化后的查询语句,从而看出优化器优化了什么。额外还有 filtered 列,是一个半分比的值,rows *filtered/100 可以估算出将要和 explain 中前一个表进行连接的行数(前一个表指 explain 中的id值比当前表id值小的表)。

EXPLAIN EXTENDED select * from actor where id=1;
show WARNINGS;

 

explain partitions:相比 explain 多了个 partitions 字段,如果查询是基于分区表的话,会显示查询将访问的分区。
5、explain中的列
5.1、id
查询执行顺序:
id 值相同时表示从上向下执行
id 值相同被视为一组
如果是子查询,id 值会递增,id 值越高,优先级越高
id为NULL最后执行。

5.2、select_type
simple:表示查询中不包含子查询或者 union
EXPLAIN select * from actor where id=1;

 

primary:当查询中包含任何复杂的子部分,最外层的查询被标记成 primary
derived:在 from 的列表中包含的子查询被标记成 derived
subquery:在 select 或 where 列表中包含了子查询,则子查询被标记成 subquery

用个例子来了解primary、subquery和derived
set session optimizer_switch='derived_merge=off';#关闭mysql5.7新特性对衍生表的合并优化
explain select (select 1 from actor where id = 1) from (select * from film where id = 1) der;

set session optimizer_switch='derived_merge=on'; #还原默认配置

 



 

union:两个 select 查询时前一个标记为 PRIMARY,后一个标记为 UNION。union 出现在 from 从句子查询中,外层 select 标记为 PIRMARY,union 中第一个查询为 DERIVED,第二个子查询标记为 UNION
explain select 1 union all select 1;

unionresult:从 union 表获取结果的 select 被标记成 union result 。
5.3、table
显示这一行的数据是关于哪张表的。
当 from 子句中有子查询时,table列是 格式,表示当前查询依赖 id=N 的查询,于是先执行 id=N 的查询。
当有 union 时,UNION RESULT 的 table 列的值为<union1,2>,1和2表示参与 union 的 select 行id。

5.4、type
这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为 system > const > eq_reg > ref > range > index > ALL。
一般来说,得保证查询达到range级别,最好达到ref

NULL:mysql能够在优化阶段分解查询语句,在执行阶段用不着再访问表或索引。例如:在索引列中选取最小值,可以单独查找索引来完成,不需要在执行时访问表
explain select min(id) from film;

 

system:表中只有一行数据。属于 const 的特例。如果物理表中就一行数据为 ALL
const :查询结果最多有一个匹配行。因为只有一行,所以可以被视为常量。const 查询速度非常快,因为只读一次。一般情况下把主键或唯一索引作为唯一条件的查询都是 const
explain select * from (select * from film where id = 1) tmp;

eq_ref:查询时查询外键表全部数据。且只能查询主键列或关联列。且外键表中外键列中数据不能有重复数据,且这些数据都必须在主键表中有对应数据(主键表中数据可以有没有用到的)

explain select * from film_actor left join film on film_actor.film_id = film.id

ref:比 eq_ref,不使用唯一索引,而是使用普通索引或者唯一性索引的部分前缀,索引要和某个值相比较,可能会找到多个符合条件的行。
简单 select 查询,name是普通索引(非唯一索引)
explain select * from film where name = 'film1';

关联表查询,idx_film_actor_id是film_id和actor_id的联合索引,这里使用到了film_actor的左边前缀film_id部分
explain select film_id from film left join film_actor on film.id = film_actor.film_id;

 

range:把这个列当作条件只检索其中一个范围。常见 where 从句中出现 between、<、>、>=、in 等。主要应用在具有索引的列中
explain select * from actor where id > 1;

 

index:扫描全索引就能拿到结果,一般是扫描某个二级索引,这种扫描不会从索引树根节点开始快速查找,而是直接对二级索引的叶子节点遍历和扫描,速度还是比较慢的,这种查询一般为使用覆盖索引,二级索引一般比较小,所以这种通常比ALL快一些
explain select * from film;

 

ALL:即全表扫描,扫描你的聚簇索引的所有叶子节点。通常情况下这需要增加索引来进行优化了。
explain select * from actor;

 

5.5、possible_keys
查询条件字段涉及到的索引,可能没有使用。
explain 时可能出现 possible_keys 有列,而 key 显示 NULL 的情况,这种情况是因为表中数据不多,mysql认为索引对此查询帮助不大,选择了全表查询。
如果该列是NULL,则没有相关的索引。在这种情况下,可以通过检查 where 子句看是否可以创造一个适当的索引来提高查询性能,然后用 explain 查看效果
5.6、key
实际使用的索引。如果为 NULL,则没有使用索引。
如果想强制mysql使用或忽视possible_keys列中的索引,在查询中使用 forceindex、ignore index。

5.7、key_len
表示索引中使用的字节数,查询中使用的索引的长度(最大可能长度),并非实际使用长度,理论上长度越短越好。key_len 是根据表定义计算而得的,不是通过表内检索出的。
举个例子来说:
film_actor的联合索引 idx_film_actor_id 由 film_id 和 actor_id 两个int列组成,并且每个int是4字节。通过结果中的key_len=4可推断出查询使用了第一个列:film_id列来执行索引查找。
explain select * from film_actor where film_id = 2;

 

 

 

5.8、ref
显示索引的哪一列被使用了,如果可能的话,是一个常量 const。

5.9、rows
根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数。注意这个不是结果集里的行数。

5.10、fitered
显示了通过条件过滤出的行数的百分比估计值。

5.11、Extra
MYSQL 如何解析查询的额外信息。

Distinct:MySQL 发现第 1 个匹配行后,停止为当前的行组合搜索更多的行。
Not exists:MySQL 能够对查询进行 LEFT JOIN 优化,发现 1 个匹配 LEFT JOIN 标准的行后,不再为前面的的行组合在该表内检查更多的行。
range checked for each record (index map: #):MySQL 没有发现好的可以使用的索引,但发现如果来自前面的表的列值已知,可能部分索引可以使用。
Using filesort:MySQL 需要额外的一次传递,以找出如何按排序顺序检索行。将用外部排序而不是索引排序,数据较小时从内存排序,否则需要在磁盘完成排序。这种情况下一般也是要考虑使用索引来优化的。
4.1. actor.name未创建索引,会浏览actor整个表,保存排序关键字name和对应的id,然后排序name并检索行记录
explain select * from actor order by name;

 

4.2. film.name建立了idx_name索引,此时查询时extra是using index
explain select * from film order by name;

 

Using index:从只使用索引树中的信息而不需要进一步搜索读取实际的行来检索表中的列信息。(使用覆盖索引)
5.1、覆盖索引定义:mysql执行计划explain结果里的key有使用索引,如果select后面查询的字段都可以从这个索引的树中获取,这种情况一般可以说是用到了覆盖索引,extra里一般都有using index;覆盖索引一般针对的是辅助索引,整个查询结果只通过辅助索引就能拿到结果,不需要通过辅助索引树找到主键,再通过主键去主键索引树里获取其它字段值
explain select film_id from film_actor where film_id = 1;

 

Using temporary:为了解决查询,MySQL 需要创建一个临时表来容纳结果。
6.1. actor.name没有索引,此时创建了张临时表来distinct
explain select distinct name from actor;

 

6.2. film.name建立了idx_name索引,此时查询时extra是using index,没有用临时表
explain select distinct name from film;

 

Using where:WHERE 子句用于限制哪一个行匹配下一个表或发送到客户,并且查询的列未被索引覆盖
explain select * from actor where name = 'a';

 

Using sort_union(…), Using union(…), Using intersect(…): 这 些 函 数 说 明 如 何 为index_merge 联接类型合并索引扫描。
Using index for group-by:类似于访问表的 Using index 方式,Using index for group-by 表示MySQL发现了一个索引,可以用来查 询GROUP BY或DISTINCT查询的所有列,而不要额外搜索硬盘访问实际的表。
--------------------------
版权声明:本文为CSDN博主「zhz小白」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zhouhengzhe/article/details/112272134

标签:Explain,actor,查询,索引,详解,select,MySQL,id,film
From: https://www.cnblogs.com/itljl/p/17573570.html

相关文章

  • spring batch 框架进行元数据管理表 mysql
    使用SpringBatch框架进行元数据管理表MySQL的实现1.简介在进行大规模数据处理时,SpringBatch框架是一个非常有用的工具。它提供了一个强大的批处理框架,可以轻松地处理大量的数据,并具备事务管理、监控、错误处理等功能。为了进行元数据管理,我们可以使用MySQL数据库来存储和管理S......
  • 修改MySQL读写模式
    修改MySQL读写模式MySQL是一个开源的关系型数据库管理系统,广泛应用于互联网应用和企业级应用中。在MySQL中,存在着读写模式的设置,可以根据实际需求来调整数据库的读写性能和一致性。本文将介绍如何修改MySQL的读写模式,并提供代码示例。1.了解MySQL读写模式在MySQL中,有两种常见的......
  • 写shell脚本一键编译安装MySQL
    一键编译安装MySQL的Shell脚本在Linux系统中,MySQL是一个非常常见的数据库管理系统。它提供了强大的功能和可靠的性能,因此在许多应用程序中被广泛使用。为了在Linux系统上运行MySQL,我们需要先进行编译安装。为了简化这个过程,我们可以编写一个Shell脚本来自动完成MySQL的编译和安装......
  • 在mysql底下导出表数据
    在MySQL数据库中导出表数据是一个常见的任务,它允许我们将表数据以可移植的方式保存到文件中,以便在需要时重新导入到数据库中。这对于数据备份、数据迁移和与其他数据库系统的交互非常有用。在MySQL中,我们可以使用mysqldump命令来导出表数据。这是一个命令行工具,可以在终端中使用。......
  • Linux权限详解
    一、文件、目录权限和所有者简介:用户对一个文件或目录具有访问权限,这些访问权限决定了谁能访问,以及如何范围这些文件和目录。通过设置权限可以限制或允许以下三种用户访问:文件的用户所有者(属主)文件的组群所有者(用户所在组的同组用户)系统中的其他用户在linux系统中,每一位用......
  • MySQL之视图检查选项
    MySQL之视图检查选项视图的检查选项当使用WITHCHECKOPTION子句创建视图时,MySQL会通过视图检查正在更改的每个行,例如插入,更新,删除,以使其符合视图的定义。MySQL允许基于另一个视图创建视图,它还会检查依赖视图中的规则以保持一致性。为了确定检查的范围,mysql提供了两个选项:CASC......
  • file /usr/share/mysql/charsets/macroman.xml from install of MySQL-server-5.6
    MySQL服务器和字符集在使用MySQL数据库时,字符集是一个非常重要的概念。它决定了数据库中存储的数据如何表示和解释。MySQL支持多种字符集,每个字符集都有自己的编码方式和规则。在安装MySQL服务器时,我们可能会遇到如下错误提示信息:file/usr/share/mysql/charsets/macroma......
  • MySQL之视图CRUD
    MySQL之视图CRUD介绍视图(View)是一种虚拟存在的表。视图中的数据并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的。通俗的讲,视图只保存了查询的SQL逻辑,不保存查询结果。所以我们在创建视图的时候,主要的工作就落在创建这条SOL查询......
  • Mysql 幻读
    总结下:简单的事务操作,例如快照读,通过系统提供的mvcc机制——创建版本号、删除版本号,避免幻读。而复杂的事务操作,例如当前度,则需要通过加锁进行控制。参考一:幻读的基本概念什么是幻读事务不是独立执行造成的一种现象。一个事务对数据表进行了全面的修改,而后另一个事务增加了一......
  • 安装 MySQL ZIP 版本
    安装MySQL的ZIP版本相对于安装包版本稍微复杂一些,因为它需要手动解压和配置。以下是在Windows上安装MySQLZIP版本的步骤:下载MySQLZIP文件:前往MySQL官方网站(https://dev.mysql.com/downloads/mysql/)下载适合您Windows版本的MySQLZIP文件。选择与您系统......