MySQL性能分析工具——EXPLAIN

性能分析工具——EXPLAIN

1、概述

定位了查询慢的SQL之后,我们就可以使用EXPLAIN或DESCRIBE工具做针对性的分析查询语句 。 DESCRIBE语句的使用方法与EXPLAIN语句是一样的,并且分析结果也是一样的。

MySQL中有专门负责优化SELECT语句的优化器模块,主要功能:通过计算分析系统中收集到的统计信息,为客户端请求的Query提供它认为最优的执行计划(他认为最优的数据检索方式,但不见的是DBA认为最优的,这部分最耗费时间)。

这个执行计划展示了接下来具体执行查询的方式,比如多表连接的顺序是什么,对于每个表采用什么访问方法来具体执行查询等等。MySQL为我们提供了EXPLAIN语句来帮助我们查看某个语句的具体执行计划,大家看懂EXPLAIN语句的各个输出项,可以有针对性的提升我们查询语句的性能。

1.1、能做什么?
  • 表的读取顺序
  • 数据读取操作的操作类型
  • 哪些索引可以使用
  • 哪些索引被实际使用
  • 表之间的引用
  • 每张表有多少行被优化器查询
1.2、版本情况
  • MySQL 5.6.3以前只能EXPLAIN SELECT;MySQL 5.6.3以后就可以EXPLAIN SELECT,UPDATE,DELETE
  • 在5.7以前的版本中,想要显示pratitions需要使用explain partitions命令;想要显示filtered需要使用explain extended命令。在5.7版本后,默认explain直接显示partitions和filtered中的信。

2、基本语法

EXPLAIN和DESCRIBE语句的语法形式如下:

EXPLAIN SELECT * FROM `sys_user`
或者
DESCRIBE SELECT * FROM `sys_user`

在这里插入图片描述

EXPLAIN语句输出的各个列的作用如下:

列名描述
id在一个大的查询语句中每个SELECT关键字都对应一个唯一的id
select_typeSELECT 关键字对应的那个查询类型
table表名
partitions匹配的分区信息
type针对单表的访问方法
possible_keys可能用到的索引
key实际用到的索引
key_len实际使用到的索引长度
ref当使用索引列等值查询时,与索引列进行等值匹配的对象信息
rows预估的需要读取的记录条数
filtered某个表经过搜索条件过滤后剩余记录条数的百分比
Extra一些额外的信息

3、数据准备

#创建表
CREATE TABLE s1 (
    id INT AUTO_INCREMENT,
    key1 VARCHAR(100),
    key2 INT,
    key3 VARCHAR(100),
    key_part1 VARCHAR(100),
    key_part2 VARCHAR(100),
    key_part3 VARCHAR(100),
    common_field VARCHAR(100),
    PRIMARY KEY (id),
    INDEX idx_key1 (key1),
    UNIQUE INDEX idx_key2 (key2),
    INDEX idx_key3 (key3),
    INDEX idx_key_part(key_part1, key_part2, key_part3)
) ENGINE=INNODB CHARSET=utf8;
 
 
CREATE TABLE s2 (
    id INT AUTO_INCREMENT,
    key1 VARCHAR(100),
    key2 INT,
    key3 VARCHAR(100),
    key_part1 VARCHAR(100),
    key_part2 VARCHAR(100),
    key_part3 VARCHAR(100),
    common_field VARCHAR(100),
    PRIMARY KEY (id),
    INDEX idx_key1 (key1),
    UNIQUE INDEX idx_key2 (key2),
    INDEX idx_key3 (key3),
    INDEX idx_key_part(key_part1, key_part2, key_part3)
) ENGINE=INNODB CHARSET=utf8;
 
#创建存储函数:
DELIMITER //
CREATE FUNCTION rand_string1(n INT) 
	RETURNS VARCHAR(255) #该函数会返回一个字符串
BEGIN 
	DECLARE chars_str VARCHAR(100) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';
	DECLARE return_str VARCHAR(255) DEFAULT '';
	DECLARE i INT DEFAULT 0;
	WHILE i < n DO
		SET return_str =CONCAT(return_str,SUBSTRING(chars_str,FLOOR(1+RAND()*52),1));
		SET i = i + 1;
	END WHILE;
	RETURN return_str;
END //
DELIMITER ;
 
SET GLOBAL log_bin_trust_function_creators=1; 
 
#创建存储过程:
DELIMITER //
CREATE PROCEDURE insert_s1 (IN min_num INT (10),IN max_num INT (10))
BEGIN
	DECLARE i INT DEFAULT 0;
	SET autocommit = 0;
	REPEAT
	SET i = i + 1;
	INSERT INTO s1 VALUES(
    (min_num + i),
    rand_string1(6),
    (min_num + 30 * i + 5),
    rand_string1(6),
    rand_string1(10),
    rand_string1(5),
    rand_string1(10),
    rand_string1(10));
	UNTIL i = max_num
	END REPEAT;
	COMMIT;
END //
DELIMITER ;
 
 
DELIMITER //
CREATE PROCEDURE insert_s2 (IN min_num INT (10),IN max_num INT (10))
BEGIN
	DECLARE i INT DEFAULT 0;
	SET autocommit = 0;
	REPEAT
	SET i = i + 1;
	INSERT INTO s2 VALUES(
        (min_num + i),
		rand_string1(6),
		(min_num + 30 * i + 5),
		rand_string1(6),
		rand_string1(10),
		rand_string1(5),
		rand_string1(10),
		rand_string1(10));
	UNTIL i = max_num
	END REPEAT;
	COMMIT;
END //
DELIMITER ;
 
#调用存储过程
CALL insert_s1(10001,10000);
 
CALL insert_s2(10001,10000);
 
SELECT COUNT(*) FROM s1;
 
SELECT COUNT(*) FROM s2;

4、EXPLAIN各列作用

为了更好的理解,我们调整下EXPLAIN输出列的顺序。

1、table

不论我们的查询语句有多复杂,里边包含了多少个表,到最后也是需要对每个表进行单表访问的,所以MySQL规定EXPLAIN语句输出的每条记录都对应着某个单表的访问方法,该条记录的table列代表着该表的表名(有时不是真实的表名字,可能是简称)。

EXPLAIN SELECT * FROM `sys_user`

在这里插入图片描述

这个查询语句只涉及对s1表的单表查询,所以EXPLAIN输出的只有一条记录,其中的table列的值是sys_user,表明这条记录的是用来说明sys_user表的单表访问方法的。

2、id

select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序。

  • id如果相同,可以认为是一组,从上往下顺序执行
  • 在所有组中,id值越大,优先级越高,越先执行
  • 关注点:id号每个号码,表示一趟独立的查询,一个sql的查询趟数越少越好
3、select_type
4、type(重点)

执行计划的一条记录就代表着MySQL对某个表的执行查询时的访问方法,又称“访问类型”,其中的type列就表明了这个访问方法的是啥,是较为重要的一个指标。比如,看到type列的值是ref,着表明MySQL即将使用ref访问方法来执行对sys_user表的查询

完整的访问方法如下:system,const,eq_ref,ref,fulltext,ref_or_null,index_merge,unique_subquery,index_subquery,renge,index,All。

详解:

  • system

    当表中只有一条记录并且该表使用的存储引擎的统计数据是精确的,比如MyISAM、Memory,那么对该表的访问就是system。

    create 	table a(i int) ENGINE = MyISAM
    INSERT INTO a(i) VALUES (1)
    EXPLAIN SELECT * from a
    

    在这里插入图片描述

  • const

    当我们根据主键或者唯一二级索列与常数进行等值匹配时,对单表的访问方法就是const

    EXPLAIN select * from s1 where id = 10002
    

    在这里插入图片描述

  • eq_ref

    在连接查询时,如果被驱动表是通过主键或者唯一二级索引列等值匹配的方式进行访问的(如果该主键或者唯一二级索引的联合索引的话,所有的索引列都必须进行等值匹配),则对该被驱动表的访问方法就是eq_ref

    EXPLAIN SELECT * FROM s1 inner join s2 ON s1.id = s2.id
    

    在这里插入图片描述

  • ref

    当通过普通的二级索引列与常量进行等值匹配时来查询某个表,那么对该表的访问方式就可能是ref

    EXPLAIN SELECT * FROM s1 where key1 = 'vLuQVg'
    

    在这里插入图片描述

  • ref_or_null

    当对普通二级索引进行等值匹配查询,该索引列的值也可以是NULL值时,那么对该表的访问方法就可能是ref_or_null

  • index_merge

    我们的 where 中可能有多个条件(或者join)涉及到多个字段,它们之间进行 OR,那么此时就有可能会使用到 index merge 技术。index merge 技术如果简单的说,其实就是:对多个索引分别进行条件扫描,然后将它们各自的结果进行合并(intersect/union)

    EXPLAIN SELECT * FROM s1  where s1.key1 = 'vLuQVg' or s1.key2 = 10036
    

    在这里插入图片描述

  • unique_subquery

    unique_subquery是针对在一些包含IN子查询的查询语句中,如果查询优化器决定将IN子查询转换为EXINST子查询,而且子查询可以用到主键进行等值匹配的话,那么该子查询执行计划的type列的值就是unique_subquery

  • renge

    如果使用索引获取某些范围区间的记录,那么就可能使用到renge

    EXPLAIN SELECT * FROM s1 where key2 in (10096,1)
    

    在这里插入图片描述

  • index

    当我们可以使用索引覆盖,但需要扫描全部的索引记录时,该表的访问方法就是index

    EXPLAIN SELECT key_part1 FROM s1 where key_part2 = 'aABgbNKlbz'
    

    在这里插入图片描述

  • all

    最熟悉的全表扫描

    EXPLAIN SELECT * FROM s1 
    

    在这里插入图片描述

小结

结果值从最好到最坏依次是:

system——>const——>eq_ref——>ref——>fulltext——>ref_or_null——>index_merge,unique_subquery——>index_subquery——>renge——>index——>All

其中比较重要的几个提取出来了。SQL性能优化的目标:至少要到达range级别,要求是ref级别,最好是const级别。(阿里巴巴开发手册要求)

5、possible_keys和key

在EXPLAIN语句输出的执行计划中,possible_keys列表示在某个查询语句中,对某个表执行单表查询时可能用到的索引有哪些。一般查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用。key列表示实际用到的索引有哪些,如果为Null,则没有使用索引。

在这里插入图片描述

6、ref列

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

7、rows

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

8、filtered

某个经过搜索条件过滤后剩余记录条数的百分比

如果使用的是索引执行的单表扫描,那么计算时需要估计出满足除使用到对应索引的搜索条件外的其他搜索条件的记录有多少条

对于单表查询来说,这个filtered列的值没什么意义,我们更关注在连接查询中驱动表对应的执行计划记录的filtered值,它决定了被驱动表要执行的次数(即rows * filtered)

9、Extra (重点)

顾名思义,Extra列是用来说明一些额外的信息的,包含不适合在其他列中显示但十分重要的额外信息。我们可以通过这些额外信息来更准确的理解MySQL到底如何执行给定的查询语句。MySQL提供的额外信息有好几十个,这里就不一个一个介绍了,只挑比较重要的额外信息介绍给大家。

  • No tables use

    当查询语句的没有FROM子句将会提示该额外信息

    EXPLAIN SELECT 1
    

    在这里插入图片描述

  • Impossible WHERE

    查询语句的WHERE子句永远为FALSE时将会提示该额外信息

    EXPLAIN SELECT * FROM S1 WHERE 1 != 1;
    

    在这里插入图片描述

  • Using index

    当我们的查询列表以及搜索条件中只包含属于某个索引的列,也就是在可以使用覆盖索引的情况下,在Extra列将会提示该额外信息。比方说下边这个查询中只需要用到index_key1而不需要回表操作

    EXPLAIN SELECT key1 FROM S1 WHERE key1 = 'a'
    

    在这里插入图片描述

  • Not exists

    当我们使用左(外)连接时,如果WHERE子句中包含要求被驱动表的某个列等于NULL值的搜索条件,而且那个列又是不允许存储NULL值的,那么在该表的执行计划的Extra列就会提示NOT exists 额外信息。

    EXPLAIN SELECT * FROM s1 
    LEFT JOIN s2 ON s1.key1 = s2.key1 WHERE s2.id IS NULL;
    

    在这里插入图片描述

  • Using union(idx_key1,idx_key2)

    索引合并查询会提示该额外信息

    EXPLAIN SELECT * FROM s1  where s1.key1 = 'a' or s1.key2 = 'b'
    

    在这里插入图片描述

  • Zero limit

    当我们的LIMIT子句参数为0时,表示压根不打算从表中读出任何记录,将会提示该额外信息。

    EXPLAIN SELECT * FROM s1   limit 0 
    

    在这里插入图片描述

  • Using filesort

    很多情况下排序操作无法使用到索引,只能在内存中(记录较少的时候)或者磁盘中(记录较多的时候)进行排序,MySQL把这种在内存中或者磁盘上进行排序的方式统称为文件排序(filesort

    如果某个查询需要使用文件排序的方式进行查询,就会在执行计划中显示Using filesort

    EXPLAIN SELECT * FROM s1 order by common_field   limit 10 
    

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/668698.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

报表工具DataEase技术方案(二)

一、DataEase报表功能开发流程 1. 创建数据源 2. 创建数据集 可以创建多种来源的数据集&#xff0c;这里以SQL数据集为例。 数据集SQL中可以添加参数&#xff0c;仪表板展示数据时可以根据参数来筛选数据。 数据集添加计算字段 3. 创建仪表板 &#xff08;1&#xff09;组合…

关于Posix标准接口和Nuttx操作系统

基本介绍 主要参考&#xff1a; Linux 系统中的 POSIX 接口详细介绍_linux posix-CSDN博客 POSIX&#xff08;Portable Operating System Interface&#xff0c;可移植操作系统接口&#xff09;是由 IEEE&#xff08;Institute of Electrical and Electronics Engineers&#x…

LLVM入门教学——SanitizerCoverage插桩(Linux)

1、介绍 LLVM 的 SanitizerCoverage 是一种代码覆盖工具&#xff0c;设计用于支持基于 fuzzing 的测试和其他安全相关工具。SanitizerCoverage 在编译时插桩代码&#xff0c;以在运行时收集覆盖信息&#xff0c;从而帮助识别未覆盖的代码路径&#xff0c;提高测试的有效性和全…

详细介绍运算符重载函数,清晰明了

祝各位六一快乐~ 前言 1.为什么要进行运算符重载&#xff1f; C中预定义的运算符的操作对象只能是基本数据类型。但实际上&#xff0c;对于许多用户自定义类型&#xff08;例如类&#xff09;&#xff0c;也需要类似的运算操作。这时就必须在C中重新定义这些运算符&#xff…

摄影后期照片编辑工具:LrC2024 for Mac/win 中文激活版

LrC2024&#xff08;Lightroom Classic 2024&#xff09;是 Adobe 公司推出的一款专业级别的照片编辑和管理软件。它是 Lightroom Classic CC 的升级版&#xff0c;具有更多的功能和改进。 这款软件主要用于数字摄影师和摄影爱好者处理、编辑和管理他们的照片。它提供了一套强大…

锅炉智能制造工厂工业物联数字孪生平台,推进制造业数字化转型

在制造业快速发展的今天&#xff0c;数字化转型已经成为企业提升竞争力的关键途径。锅炉智能制造工厂工业物联数字孪生平台&#xff0c;作为一种创新的技术解决方案&#xff0c;正以其独特的优势&#xff0c;为制造业的数字化转型提供强大动力。锅炉智能制造工厂工业物联数字孪…

【网络研究观】-20240531

战争揭开美国武器优势的面纱 随着俄军在哈尔科夫地区稳步推进&#xff0c;乌克兰战争对美国国防机器而言是一场灾难&#xff0c;这一点越来越明显&#xff0c;这不仅是因为我们的援助未能挽救乌克兰的撤退和可能的失败。更重要的是&#xff0c;这场战争无情地暴露了我们国防体…

我用大模型校稿出书的经验心得

1. 第一本AI校稿的书 我的新书《云计算行业进阶指南》已经出版&#xff0c;本书使用了大模型进行AI校对书稿。 在本文稿发布前&#xff0c;我问了好几个AI&#xff0c;AI都说“还没有出版书籍宣称自己使用了AI校稿”&#xff0c;因此我可以说&#xff1a; 本书是第一本公开宣称…

Docker搭建Redis主从 + Redis哨兵模式(一主一从俩哨兵)

我这里是搭建一主一从&#xff0c;俩哨兵&#xff0c;准备两台服务器&#xff0c;分别安装docker 我这里有两台centos服务器 主服务器IP&#xff1a;192.168.252.134 从服务器IP&#xff1a;192.168.252.135 1.两台服务器分别拉取redis镜像 docker pull redis 2.查看镜像 d…

编写备份MySQL 脚本

目录 环境准备 增量备份 增量备份和差异备份 完整代码如下 测试脚本是否正常 星期天运行脚本&#xff08;完全备份&#xff09; 星期一运备份脚本&#xff08;增量备份&#xff09; 星期二备份数据&#xff08;其他天--增量备份&#xff09; 星期三备份数据&#xff08;差异备…

cobalt strike基础测试

下载链接4.3&#xff1a;https://pan.baidu.com/s/1E_0t30tFWRiE5aJ7F-ZDPg 链接4.0&#xff1a;https://pan.baidu.com/s/1SkMmDem3l6bePqIDgUz2mA 提取码&#xff1a;burp 一、简介&#xff1a; cobalt strike(简称CS)是一款团队作战渗透测试神器&#xff0c;分为客户端…

C++笔试强训day37

目录 1.旋转字符串 2.合并k个已排序的链表 3.滑雪 1.旋转字符串 链接https://www.nowcoder.com/practice/80b6bb8797644c83bc50ac761b72981c?tpId196&tqId37172&ru/exam/oj 如果 A 字符串能够旋转之后得到 B 字符串的话&#xff0c;在 A 字符串倍增之后的新串中&am…

linux驱动学习(二)之点灯

需要板子一起学习的可以这里购买&#xff08;含资料&#xff09;&#xff1a;点击跳转 如何实现对硬件控制 分析硬件原理图&#xff08;开发板的原理图&#xff09;----> 分析硬件的控制方法 ---> 控制硬件时&#xff0c;所要用到的寄存器 ----> 了解控制硬件寄存器的…

关于如何在Arch Linux上编写自己的第一个module

前一段时间一直想深入学习编写一个module插入到自己的内核当中&#xff0c;但是网上的资料基本上全都针对的Ubuntu和Debian等流行的Linux发行版&#xff0c;这里打算简单的记录一波博客。 啥是Module?(着急可不看) 众所周知&#xff1a;现代宏内核架构的操作系统都会借鉴微内核…

【stableDiffusion】HuggingFace模型下载(只要知道url,就直接开始下载)

一、方法 有人说&#xff0c;那我怎么知道 huggingface 上面我想要的资源的url&#xff0c;去哪儿找啊&#xff1f; 那就涉及到一些魔法手段了&#xff0c;或者你能在其他人的博客或者百度上搜索到合适的url。 我这个办法是用来节约我的魔法的流量的。 1.迅雷 1.1 打开迅雷&…

【Kotlin】简单介绍与使用kotlin

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;Kotlin ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 特点 变量和常量 数据类型和类型推断 函数 字符串模板 条件表达式 空安全 when 表达式 循环 我的其他博客 前言 Kotlin是…

PostgreSQL基础(六):PostgreSQL基本操作(二)

文章目录 PostgreSQL基本操作(二) 一、字符串类型 二、日期类型 三、

比较与深浅克隆

1.比较 &#xff08;1&#xff09;Comparable接口&#xff1a;&#xff08;重写compareTo方法&#xff09; 由于它是一个接口&#xff0c;而且在这个接口中只有一个compareTo方法&#xff0c;所以所有实现该接口的类都需要重写。这个compareTo方法相当于制定一个比较标准&…

Raid的全局热备和独立热备

目录 Hot Spare背景: 1.定义与功能 2.数据存储与容量 3.配置模式 4.数量限制&#xff1a; 5.数据重建: 6.管理与维护 实操全局热备和独立热备&#xff1a; 配置全局热备: 配置独立热备: Hot Spare背景: 在RAID配置中&#xff0c;Hot Spare(热备)是一个非常重要的概念…

【数据结构与算法 | 二叉树篇】二叉树的前中后序遍历(递归版本)

1. 二叉树的概念 (1). 二叉树的结构 借用了一下力扣的模板 public class TreeNode {int val;TreeNode left;TreeNode right;TreeNode() {}TreeNode(int val) { this.val val; }TreeNode(int val, TreeNode left, TreeNode right) {this.val val;this.left left;this.righ…