mysql执行计划Explain解读

 更新时间:2024年10月24日 09:07:29   作者:Carver0808  
在数据库操作中,理解Explain执行计划对于性能优化至关重要,Explain展示了MySQL如何执行查询,包括选择哪些索引,如何连接表,以及估计的行数等,Select类型、访问表的方式、使用的索引、以及额外的执行信息,都是优化查询时需要考虑的因素

一、准备环境

1、新增用户表,方便后续测试使用

CREATE TABLE `t_login_user` (
	`id` INT (11) NOT NULL AUTO_INCREMENT,
	`dateint` INT (11) NOT NULL COMMENT '年月份',
	`user_id` VARCHAR (50) NOT NULL COMMENT '用户id',
	`login_name` VARCHAR (50) DEFAULT NULL COMMENT '登录名',
	`password` VARCHAR (255) DEFAULT NULL COMMENT '密码',
	`nick_name` VARCHAR (255) DEFAULT NULL COMMENT '用户名称',
	`fail_count` INT (11) NOT NULL DEFAULT '0' COMMENT '当前连续失败次数',
	`max_fail_count` INT (11) NOT NULL DEFAULT '6' COMMENT '允许的连续最大失败次数',
	`is_locked` CHAR (1) NOT NULL DEFAULT 'n' COMMENT '是否被锁定',
	PRIMARY KEY (`id`),
	UNIQUE KEY `unique_user_id` (`user_id`),
	KEY `idx_login_name` (`login_name`),
	KEY `dateint_login_name` (`dateint`, `login_name`)
) ENGINE = INNODB AUTO_INCREMENT = 19 DEFAULT CHARSET = utf8 COMMENT = '登录用户';

2、数据表索引结构

二、Explain执行计划中的列解释

1、id列

id列的编号是select的序列号,有几个select就有几个id,并且id的顺序是按select出现的顺序增长的。

id越大执行优先级越高,id相同则从上往下执行,id为NULL最后执行。

EXPLAIN SELECT * FROM	t_login_user 
WHERE	id = (
	SELECT id FROM t_login_user WHERE user_id = (
		SELECT user_id from t_login_user where nick_name = '张三')
);

案例分析

如上有3个select查询那么explain结果中有3个id,sql得执行顺序是先执行id为3的select(nick_name为张三作为条件查到user_id),在执行id为2的select(拿到上一步user_id作为条件查到id),最后在执行id为1的select (哪到上一步id作为条件查到数据)。

2、select type列

select type表示对应查询的类型,是简单还是复杂的查询

select type的值有:

  • 1、simple:简单查询。查询不包含子查询和union 2、primary:复杂查询中最外层的select
  • 3、subquery:包含在select中的子查询(不在from子句中)
  • 4、derived:包含在from子句中的子查询。MySQL会将结果存放在一个临时表中,也称为派生表
  • 5、union:在union关键字随后的selelct

案例演示:

1、simple:简单查询

2、primary:复杂查询中最外层的select 3、subquery:包含在select中的子查询(不在from子句中)

4、derived:包含在from子句中的子查询。MySQL会将结果存放在一个临时表中,也称为派生表

5、union:在union关键字随后的selelct

3、table列

这一列表示explain的一行正在访问哪个表。当from子句中有子查询时,table列是格式,表示当前查询依赖id=N的查询,于是先执行id=N的查询。

当有union时,UNION RESULT的table列的值为<union 1,2>,1和2表示参与union的select行id

4、partitions

partitions查询涉及到的分区

5、type列

这一列表示关联类型或访问类型,即MySQL决定如何查找表中的行,查找数据行对应的大概范围。

依次从最优到最差的分别为:system>const>eq_ref>ref>range>index>All一般来说,得保证查询达到range级别,最好达到ref。

1、NULL:MySQL能够在优化阶段分解查询语句,在执行阶段用不着在访问表或索引。例如:在索引列中选取最小值,可以单独查找索引来完成,不需在执行时访问表。

2、system

访问类型最高的,属于const类型的特例,表只有一条记录行(系统表)

3、const

表示通过索引一次就能找到, const 用于比较primary或者unique(值是唯一的)。

因为只匹配一条数据,所以很快。

如果将主键置于where 子句中,mysql就能将该查询转为一个常量

4、eq_ref:eq_ref用于联合表的查询。

primay key或 unique key索引的所有部分被连接使用,最多只会返回一条符合条件的记录

如下面sql,对于前表t_login_user表中的每一行(row),对应后dept 表只有一行被扫描

EXPLAIN select A.id from t_login_user A LEFT JOIN dept B USING(id) --  USING(id)等价于是 on A.id = B.id

5、ref:相比eq_ref,不适用唯一索引,而是使用普通索引或者唯一索引的部分前缀,索引要和某个值相比较,可能会找到多个符合条件的行。

简单select查询,name是普通索引(非主键索引或唯一索引)

EXPLAIN select id from t_login_user where login_name= "张三"

6、range:范围扫描通常出现在in(), between,>,<,>=等操作中。

使用一个索引来检索给定范围的行。

EXPLAIN select id from t_login_user where id > 1

7、index:扫描全表索引,通常比All快一些

8、all:即全表扫描,意味着MySQL需要从头到尾去查找所需要的行。

这种情况下需要增加索引来进行优化。

6、possible_keys列

MySQL 能在该表中可能使用的索引,显示的是索引的名称,多个索引用逗号隔开。

在explain时可能会出现possible_keys有索引key值,而key显示为NULL的情况,这种情况是因为表中的数据不多,MySQL认为索引对此查询帮助不大,选择了全表扫描。

如果该列为NULL,则没有相关的索引

7、key列

MySQL决定实际用到的索引,显示的是索引的名称,多个索引用逗号隔开,如果没有,则为null

8、key_len列

这一列显示了mysql在索引里使用的字节数,通过这个值可以估算出具体使用了索引中的哪些列。

ken_len计算规则如下: 

字符串

  • char(n):n字节长度
  • varchar(n):n字节存储字符串长度,如果是utf-8, 则长度是3n+2

数值类型

  • tinyint:1字节
  • smallint:2字节
  • int:4字节
  • bigint:8字节

时间类型

  • date:3字节
  • timestamp:4字节
  • datetime:8字节

如果字段允许为NULL,需要1字节记录是否为NULL

索引最大长度是768字节,当字符串过长时,MySQL会做一个类似做前缀索引的处理,将前半部分的字符串提取出来做索引。

9、ref

这一列显示了在key列记录的索引中,表查找值所用到的列或常量,常见的有: const(常量),字段名、表名等。

一般是查询条件或关联条件中等号右边的值,如果是常量那么ref列是const,非常量的话ref列就是字段名。

条件等号右边是常量 ref列就显示const,如下

条件等号右边是非常量 ref列就显示字段名或者表名

10、row列

这一列是mysql估计要读取并检测的行数,注意这个不是结果集的行数。

11、filtered

filtered表示返回结果的行数占需读取行数的百分比,filtered列的值依赖于统计信息。

12、Extra列

这一列是额外信息。

  • Using index:使用覆盖索引(查询的字段是索引字段)

  • Using where:使用where语句来处理结果,查询的列未被索引覆盖

  • Using temporary:mysql需要创建一张临时表来处理查询。出现这种情况一般要进行优化,首先要想到是索引优化。

  • Using filesort:将用外部排序而不是索引排序,数据较小时从内存排序,否则需要在磁盘完成排序。这种情况下一般也是要考虑使用索引来优化的。

  • select tables optimized away:使用某些聚合函数(比如:max、min)来访问存在索引的某个字段

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • mysql prompt的用法详解

    mysql prompt的用法详解

    本篇文章是对mysql中prompt的用法进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • MYSQL实现排名及查询指定用户排名功能(并列排名功能)实例代码

    MYSQL实现排名及查询指定用户排名功能(并列排名功能)实例代码

    这篇文章主要给大家介绍了关于MYSQL实现排名及查询指定用户排名功能(并列排名功能)的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起看看吧
    2018-10-10
  • MySQL下PID文件丢失的相关错误的解决方法

    MySQL下PID文件丢失的相关错误的解决方法

    这篇文章主要介绍了MySQL下PID文件丢失的相关错误的解决方法,具体的提示可能会是"mysql PID file not found and Can’t connect to MySQL through socket mysql.sock",需要的朋友可以参考下
    2015-07-07
  • 浅析MySQL replace into 的用法

    浅析MySQL replace into 的用法

    在向表中插入数据的时候,经常遇到这样的情况:1. 首先判断数据是否存在; 2. 如果不存在,则插入;3.如果存在,则更新。
    2014-06-06
  • 教你使用VS Code的MySQL扩展管理数据库的方法

    教你使用VS Code的MySQL扩展管理数据库的方法

    这篇文章主要介绍了使用VS Code的MySQL扩展管理数据库,在本文告诉你如何用VS Code的扩展程序管理MySQL数据库,包括连接到MySQL、新建数据库和表、修改字段定义、简单的查询方法以及导入导出,需要的朋友可以参考下
    2022-01-01
  • 为什么MySQL数据库索引选择使用B+树?

    为什么MySQL数据库索引选择使用B+树?

    今天小编就为大家分享一篇关于为什么MySQL数据库索引选择使用B+树?,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • 如何查看MySQL连接的root密码

    如何查看MySQL连接的root密码

    前几天在用Navicat去连本地的MySQL的时候发现我已经忘了密码了,试了网上很多方式都不行…后来发现其实可以自己直接去看当初设置的密码,下面将方法总结出来分享给大家,有需要的朋友们可以参考借鉴,下面来一起看看吧。
    2017-01-01
  • 深入理解MySQL主从复制线程状态转变

    深入理解MySQL主从复制线程状态转变

    这篇文章主要给大家介绍了关于MySQL主从复制线程状态转变的相关资料,文中介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-02-02
  • mysql 8.0.11 压缩包版安装配置方法图文教程

    mysql 8.0.11 压缩包版安装配置方法图文教程

    这篇文章主要为大家详细介绍了mysql 8.0.11 压缩包版安装配置方法图文教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-05-05
  • Mysql8主从复制解读(兼容低高版本)

    Mysql8主从复制解读(兼容低高版本)

    文章详细介绍了MySQL主从复制的理论知识、必要前提、实现原理、binlog的三种类型以及主从同步的具体步骤,通过配置主库和从库的MySQL配置文件,并创建用于主从同步的用户,可以实现主从复制,最后,文章还讨论了主从同步的验证和故障切换的方法
    2025-02-02

最新评论