MySQL explain SQL分析工具详解与最佳实践

news2024/11/26 11:25:43

目录

    • 一、explain工具介绍
    • 二、添加示例表和数据用于后续演示
    • 三、explain中的列
      • 3.1、id列
      • 3.2、select_type列
      • 3.3、table列
      • 3.4、partitions列
      • 3.5、type列
        • NULL
        • system
        • const
        • eq_ref
        • ref
        • range
        • index
        • ALL
      • 3.6、possible_keys列
      • 3.7、key列
      • 3.8、key_len列
      • 3.9、ref列
      • 3.10、rows列
      • 3.11、filtered列
      • 3.12、Extra列
        • Using index
        • Using where
        • Using index condition
        • Using temporary
        • Using filesort
        • Select tables optimized away

一、explain工具介绍

  • 使用explain关键字可以模拟优化器执行SQL语句,分析你的查询语句或是结构的性能瓶颈在 select 语句之前增加 explain 关键字,MySQL 会在查询上设置一个标记,执行查询会返回执行计划的信息,而不是执行这条SQL。

  • 通过explain执行SQL语句还能查看优化器优化之后的SQL,紧随其后通过 SHOW WARNINGS; 命令可以得到优化后的查询语句,从而看出优化器优化了什么

    # 例如
    EXPLAIN
    SELECT * FROM role;
    SHOW WARNINGS;
    

    在这里插入图片描述

二、添加示例表和数据用于后续演示

这里会使用角色加菜单关系三张表来做演示。

DROP TABLE IF EXISTS `menu`;
CREATE TABLE `menu`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '菜单ID',
  `menu_name` varchar(50) DEFAULT NULL COMMENT '菜单名称',
  `remark` varchar(255) DEFAULT NULL COMMENT '备注',
  `del_flag` tinyint(4) NULL DEFAULT 0 COMMENT '删除标识 0:已删除 1:未删除 默认0',
  `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '创建时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB COMMENT = '菜单表';

INSERT INTO `menu` VALUES (1, '系统管理', '管理系统用户角色菜单相关', 0, '2023-09-28 10:45:41');
INSERT INTO `menu` VALUES (2, '商品管理', '管理系统商品', 0, '2023-09-28 10:46:04');

DROP TABLE IF EXISTS `role`;
CREATE TABLE `role`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '角色ID',
  `role_name` varchar(50) DEFAULT NULL COMMENT '角色名称',
  `remark` varchar(255) DEFAULT NULL COMMENT '备注',
  `del_flag` tinyint(4) NULL DEFAULT 0 COMMENT '删除标识 0:已删除 1:未删除 默认0',
  `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '创建时间',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_roleName` (`role_name`)
) ENGINE = InnoDB COMMENT = '角色表';

INSERT INTO `role` VALUES (1, '超级管理员', '最大角色', 0, '2023-09-28 10:43:31');
INSERT INTO `role` VALUES (2, '普通人员', '小卡拉米', 0, '2023-09-28 10:45:14');

DROP TABLE IF EXISTS `role_menu`;
CREATE TABLE `role_menu`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '角色菜单关联ID',
  `role_id` bigint(20) NOT NULL COMMENT '角色ID',
  `menu_id` bigint(20) NOT NULL COMMENT '菜单ID',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_roleId_menuId` (`role_id`,`menu_id`)
) ENGINE = InnoDB COMMENT = '角色菜单关联表';

INSERT INTO `role_menu` VALUES (1, 1, 1);
INSERT INTO `role_menu` VALUES (2, 1, 2);
INSERT INTO `role_menu` VALUES (3, 2, 2);

三、explain中的列

explain中有12个列分别代表不同指标,这里会举例介绍。
在这里插入图片描述

3.1、id列

id列的编号是 select 的序列号,有几个 select 就有几个id,并且id的顺序是按 select 出现的顺序增长的,id列越大执行优先级越高,id相同则从上往下执行,id为NULL最后执行。

3.2、select_type列

select_type 表示对应行是简单还是复杂的查询。

  • 1、simple:简单查询,查询不包含子查询和union
EXPLAIN SELECT * FROM role  WHERE id = 1;

在这里插入图片描述

  • 2、primary:复杂查询中最外层的 select
  • 3、subquery:包含在 select 中的子查询(不在 from 子句中)
EXPLAIN SELECT t1.id,(SELECT menu_name FROM menu WHERE id=t1.menu_id ) AS menuName FROM role_menu t1

在这里插入图片描述

  • 4、union:在 union 中的第二个和随后的 select
EXPLAIN SELECT * FROM role WHERE id=1 UNION SELECT * FROM role WHERE id=2;

在这里插入图片描述

3.3、table列

这一列表示 explain 的一行正在访问哪个表,如果表设置了别名会显示表的别名。

3.4、partitions列

指分区信息。数据库优化有分库、分表、分区;这里的分区值表的分区信息。

3.5、type列

这一列表示关联类型或访问类型,即MySQL决定如何查找表中的行,查找数据行记录的大概范围。
依次从最优到最差分别为:system > const > eq_ref > ref > range > index > ALL
一般来说,得保证查询达到range级别,最好达到ref

NULL

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

EXPLAIN SELECT MIN(id) FROM role;

在这里插入图片描述

system

system是const的特例,表里只有一条元组匹配时为system,可以看SHOW WARNINGS;的结果。

EXPLAIN SELECT * FROM (SELECT '666' AS num FROM dual) t1;
SHOW WARNINGS;

在这里插入图片描述
在这里插入图片描述

const

mysql能对查询的某部分进行优化并将其转化成一个常量(可以看SHOW WARNINGS;的结果)。用于primary key 或 unique key 的所有列与常数比较时,所以表最多有一个匹配行,读取1次,速度比较快。

EXPLAIN SELECT * FROM role WHERE id=1;
SHOW WARNINGS;

在这里插入图片描述
在这里插入图片描述

eq_ref

primary key 或 unique key 索引的所有部分被连接使用 ,最多只会返回一条符合条件的记录。这可能是在const 之外最好的联接类型了,简单的 select 查询不会出现这种 type。

EXPLAIN
SELECT * FROM role t1 INNER JOIN role_menu t2 ON t1.id=t2.id where t1.id;

在这里插入图片描述

ref

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

EXPLAIN SELECT * FROM role where role_name = '超级管理员';

在这里插入图片描述

range

范围扫描通常出现在 in(), between ,> ,<, >= 等操作中。使用一个索引来检索给定范围的行。

EXPLAIN SELECT * FROM role where id < 3;

在这里插入图片描述

index

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

EXPLAIN SELECT role_name FROM role;

在这里插入图片描述

ALL

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

EXPLAIN SELECT * FROM role WHERE del_flag = 1;

在这里插入图片描述

3.6、possible_keys列

这一列显示查询可能使用哪些索引来查找。

  • explain 时可能出现 possible_keys 有列,而 key 显示 NULL 的情况,这种情况是因为表中数据不多,mysql认为索引
    对此查询帮助不大,选择了全表查询。
  • 如果该列是NULL,则没有相关的索引。在这种情况下,可以通过检查 where 子句看是否可以创造一个适当的索引来提
    高查询性能,然后用 explain 查看效果。

3.7、key列

这一列显示mysql实际采用哪个索引来优化对该表的访问。

  • 如果没有使用索引,则该列是 NULL。如果想强制mysql使用或忽视possible_keys列中的索引,在查询中使用 force
    index、ignore index。
    # 强制使用idx_roleName索引
    # 需要注意的就算我们指定了需要使用的索引,但是MySQL优化器觉得全表扫描更加高效或者我们指定的索引查询条件无法使用到,还是可能会忽略我们指定的索引。
    EXPLAIN SELECT * FROM role FORCE INDEX(idx_roleName) WHERE role_name = '超级管理员';
    # 忽略使用idx_roleName索引
    EXPLAIN SELECT * FROM role IGNORE INDEX(idx_roleName) WHERE role_name = '超级管理员';
    

3.8、key_len列

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

举例来说,role_menu的联合索引 idx_roleId_menuId由 role_id 和 menu_id 两个bigint列组成,并且每个bigint是8字节。通
过结果中的key_len=8可推断出查询使用了第一个列:role_id 列来执行索引查找。

EXPLAIN SELECT * FROM role_menu WHERE role_id = 1;

在这里插入图片描述

  • key_len计算规则如下:
    • 字符串,char(n)和varchar(n),5.0.3以后版本中,n均代表字符数,而不是字节数,如果是utf-8,一个数字或字母占1个字节,一个汉字占3个字节
      • char(n):如果存汉字长度就是 3n 字节
      • varchar(n):如果存汉字则长度是 3n + 2 字节,加的2字节用来存储字符串长度,因为varchar是变长字符串
    • 数值类型
      • tinyint:1字节
      • smallint:2字节
      • int:4字节
      • bigint:8字节
    • 时间类型
      • date:3字节
      • timestamp:4字节
      • datetime:8字节
    • 如果字段允许为 NULL,需要1字节记录是否为 NULL
    • 索引最大长度是768字节,当字符串过长时,mysql会做一个类似左前缀索引的处理,将前半部分的字符提取出来做索引。

3.9、ref列

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

3.10、rows列

这一列是MySQL估计要读取并检测的行数,注意这个不是结果集里的行数,这个只是预估值和实际值可能有偏差。

3.11、filtered列

filtered指标表示扫描行数和条件过滤结果集的百分比,比如我们这边查询 role_name = ‘超级管理员’,全表扫描总扫描数据集2条过滤出1条得到比值50%。

EXPLAIN SELECT * FROM role  WHERE  role_name = '超级管理员';

在这里插入图片描述

3.12、Extra列

这一列展示的是额外信息。常见的重要值如下:

Using index

使用覆盖索引,mysql执行计划explain结果里的key有使用索引,如果select后面查询的字段都可以从这个索引的树中获取,这种情况一般可以说是用到了覆盖索引,extra里一般都有using index;覆盖索引一般针对的是辅助索引,整个查询结果只通过辅助索引就能拿到结果,不需要通过辅助索引树找到主键,再通过主键去主键索引树里获取其它字段值

EXPLAIN SELECT role_name FROM role WHERE role_name = '超级管理员';

在这里插入图片描述

Using where

使用 where 语句来处理结果,并且查询的列未全部被索引覆盖

EXPLAIN SELECT * FROM role WHERE role_name = "超级管理员" AND remark = "最大角色";

在这里插入图片描述

Using index condition

尝试只使用索引来获取数据,即能用索引就用;

EXPLAIN SELECT * FROM role WHERE role_name > '超级管理员';

在这里插入图片描述

Using temporary

用临时表存储中间结果,常用于DISTINCT、GROUP BY、ORDER BY 等操作。

EXPLAIN SELECT DISTINCT remark FROM role;

在这里插入图片描述

Using filesort

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

EXPLAIN SELECT * FROM role ORDER BY create_time;

在这里插入图片描述

Select tables optimized away

使用某些聚合函数(比如 max、min)来访问存在索引的某个字段。

EXPLAIN SELECT MIN(id) FROM role;

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《视觉 SLAM 十四讲》V2 第 11 讲 回环检测【消除累积误差】

待做: 习题整理 相关文献【新的综述】等 P283 文章目录 11.2 词袋 模型11.3.2 Code&#xff1a; 创建字典11.4.2 Code&#xff1a; 相似度 计算训练 自己的字典 报错 习题√ 题1√ 题2题3 DBoW3库题4题5 基于 词袋 的外观式 回环检测 SLAM主体(前端后端)&#xff1a; 估计相机…

图片处理后再保存为图片到文件夹中,文件夹下文件名不变改格式保存

首先读取图片&#xff1b; 然后处理&#xff0c;得到cv:Mat类型&#xff1b; 对cv:Mat类型图片写入文件夹&#xff0c;保存到指定路径。 像raw图等不能直接读取显示&#xff0c;需要先进行解码&#xff0c;转换为可以显示的图片。 下面举例读入本来可以显示的图。以下代码加…

哈弗猛龙实力登场,「方盒子猛改派对」掀起越野改装新热潮

9月22日-24日&#xff0c;哈弗猛龙“方盒子猛改派对”在北京751 D-PARK 火车头广场成功举办。活动现场盛况空前&#xff0c;不仅有官方展出的11台不同风格的猛改车型&#xff0c;更吸引了不同领域的博主大咖及越野达人前来参与活动。 与此同时&#xff0c;哈弗猛龙用户大定权益…

【EI会议征稿】第三届信号处理与通信技术国际学术会议(SPCT 2023)

第三届信号处理与通信技术国际学术会议&#xff08;SPCT 2023&#xff09; 2023 3rd International Conference on Signal Processing and Communication Technology 第三届信号处理与通信技术国际学术会议&#xff08;SPCT 2023&#xff09;将于2023年12月1-3日在长春召开。S…

【AIPOD案例操作教程】斜流风扇轮毂优化

AIPOD是由天洑软件自主研发的一款通用的智能优化设计软件&#xff0c;致力于解决能耗更少、成本更低、重量更轻、散热更好、速度更快等目标的工程设计寻优问题。针对工业设计领域的自动化程度低、数值模拟计算成本高等痛点&#xff0c;基于人工智能技术、自研先进的智能代理学习…

MySQL存储引擎以及InnoDB、MyISAM、Memory特点介绍

存储引擎介绍和基本使用 基本介绍&#xff1a; 存储引擎是数据库的核心&#xff0c;存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式 。存储引擎是基于表的&#xff0c;而不是基于库的&#xff0c;所以存储引擎也可被称为表类型。我们可以在创建表的时候&…

U盘植马之基于arduino的badusb实现及思考

引言 曾经有这么一段传说&#xff0c;在某次攻防演练时&#xff0c;某攻击队准备了一口袋U盘前往了目标单位的工作园区&#xff0c;在园区围墙外停下了脚步&#xff0c;然后开始不停扔U盘进去&#xff0c;最后发现有大量的“猎奇者”上线。 U盘植马是常见的近源渗透方式之一&am…

若依不分离+Thymeleaf select选中多个回显

项目中遇到的场景&#xff0c;亲测实用 表单添加时&#xff0c;select选中多个&#xff0c;编辑表单时&#xff0c;select多选回显&#xff0c;如图 代码&#xff1a; // 新增代码 <label class"col-sm-3 control-label">通道&#xff1a;</label><…

再学C++ | std::set 的原理

std::set 是C标准库中的容器之一&#xff0c;它基于红黑树实现。std::set 利用红黑树的特性来实现有序的插入、查找和删除操作&#xff0c;并且具有较好的平均和最坏情况下的时间复杂度。 当向 std::set 插入元素时&#xff0c;它会按照特定的比较函数&#xff08;bool less<…

软件可靠性基础

软件可靠性基础 软件可靠性基本概念串并联系统可靠性计算软件可靠性测试软件可靠性建模软件可靠性管理软件可靠性设计容错&#xff0c;检错的技术 选择题考基本概念&#xff08;MTBF&#xff09;&#xff0c;很少考 非重点 软件可靠性基本概念 这个章节中&#xff0c;第一个…

Leetcode算法题练习(一)

目录 一、前言 二、移动零 三、复写零 四、快乐数 五、电话号码的字母组合 六、字符串相加 一、前言 大家好&#xff0c;我是dbln&#xff0c;从本篇文章开始我就会记录我在练习算法题时的思路和想法。如果有错误&#xff0c;还请大家指出&#xff0c;帮助我进步。谢谢&…

2023-9-27 JZ55 二叉树的深度

题目链接&#xff1a;二叉树的深度 import java.util.*; /** public class TreeNode {int val 0;TreeNode left null;TreeNode right null;public TreeNode(int val) {this.val val;}} */ public class Solution {public int TreeDepth(TreeNode root) {if(root null) ret…

续航605km,价格 11.77 万起带激光雷达,你卷我也卷

9 月 21 日&#xff0c;睿蓝 7 正式上市&#xff0c;新车提供 6 款车型&#xff0c;售价区间 11.77-17.37 万元。 权益方面&#xff0c;提供 701 元订金抵 2000 元车款、2000 元选装基金、终身 24 小时救援服务、10 万 3 年 0 息金融政策、3000 元置换/ 1000 元增购补贴、6 年/…

【Java 进阶篇】MySQL主键约束详解

MySQL是一个强大的关系型数据库管理系统&#xff0c;用于存储和管理大量数据。在数据库中&#xff0c;主键约束是一项非常重要的概念&#xff0c;它有助于确保数据的完整性和唯一性。本文将详细介绍MySQL主键约束&#xff0c;包括什么是主键、为什么需要主键、如何创建主键以及…

自增自减运算符i++与++i的区别

自增自减运算符用作前缀与用作后缀时略有不同。 i和i的区别&#xff1a; 1、i 返回原来的值&#xff0c;i 返回加1后的值。&#xff08; a i 是先给 a 赋值&#xff0c;然后 i 再自增&#xff1b;a i是 i 先自增&#xff0c;然后给 a 赋值。&#xff09; #include<iost…

(2023|ICLR,检索引导,交叉引导,EntityDrawBench)Re-Imagen:检索增强的文本到图像生成器

Re-Imagen: Retrieval-augmented text-to-image generator 公众号&#xff1a;EDPJ&#xff08;添加 VX&#xff1a;CV_EDPJ 或直接进 Q 交流群&#xff1a;922230617 获取资料&#xff09; 目录 0. 摘要 1. 简介 2. 相关工作 3. 模型 3.1 预备知识 3.2 用多模态知识…

msvcp140.dll丢失的解决方法与msvcp140.dll是什么东西详细解析

在使用电脑时&#xff0c;可能会遇到打开软件时提示“找不到 msvcp140.dll&#xff0c;无法继续执行代码”的问题。这通常意味着你的计算机上缺少 Microsoft Visual C Redistributable 的运行时库&#xff0c;或者该库的版本不正确。下面是我找了几天的修复方法&#xff0c;今天…

PBR的应用

项目拓扑与项目需求 项目需求&#xff1a;某企业网络拥有三个出口&#xff0c;分别使用AR1、AR2、AR3链接运营商网络。其中AR1为万兆出口&#xff0c;而AR2、AR3为千兆出口。现在需要实现以下需求&#xff1a; 希望vlan10的流量能够强制通过AR1作为业务的出口&#xff0c;vla…

iCloud邮箱怎么登录?看这里,2招教你搞定!

iCloud邮箱是苹果公司推出的一款功能强大的邮件服务。通过iCloud邮箱&#xff0c;用户可以实现接收和发送电子邮件。苹果强调保护用户的隐私和数据安全&#xff0c;所以icloud邮箱为用户提供了高度保密的邮件加密服务&#xff0c;能够确保用户的邮件在传输时得到保护。 但是&a…

Kotlin语言基础(三)- 函数

函数可以定义特定功能的代码块。 一、函数定义 Kotlin语言定义函数的基本形式&#xff1a; fun 函数名(【参数&#xff1a;参数类型,参数&#xff1a;参数类型…】)【:返回值类型】{ //函数体 } 如果函数体只有一条返回值&#xff0c;也可以简化成如下形式&#xff1a; fun 函…