MySQL性能优化explain关键字详解

系列文章目录

一、MySQL数据结构选择
二、MySQL性能优化explain关键字详解
三、MySQL索引优化


文章目录

  • 系列文章目录
  • 一、explain是什么?
  • 二、explain字段详解
    • 2.1、ID
    • 2.2、select_type
    • 2.3、table
    • 2.4、partitions
    • 2.5、type(重点)
    • 2.6、key
    • 2.7、key_len
    • 2.8、ref
    • 2.9、rows
  • 三、索引失效解析
    • 3.1、索引失效场景一:在索引列上进行计算
    • 3.2、索引失效场景二:使用索引中范围条件右边的列
    • 3.3、索引失效场景三:使用< 、> 、 <=、>=、!=
    • 3.4、索引失效场景四:使用'%字段'或'%字段%'
    • 3.5、索引失效场景五:字符串未加单引号


一、explain是什么?

  EXPLAIN 关键字在MySQL中,主要用于分析查询语句的性能,以及执行过程:

explain select * from actor;

在这里插入图片描述  通过explain select 语句,可以得到一个结果集。

二、explain字段详解

  以下面的三张表为例:

-- 删除并重新创建 actor 表
DROP TABLE IF EXISTS `actor`;
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;-- 插入数据到 actor 表
INSERT INTO `actor` (`id`, `name`, `update_time`) 
VALUES (1, 'a', '2017-12-22 15:27:18'), (2, 'b', '2017-12-22 00:00:00');-- 删除并重新创建 film 表
DROP TABLE IF EXISTS `film`;
CREATE TABLE `film` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(10) DEFAULT NULL,PRIMARY KEY (`id`),KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- 插入数据到 film 表
INSERT INTO `film` (`id`, `name`) 
VALUES (3, 'film1'),(1, 'film1'),(2, 'film2');-- 删除并重新创建 film_actor 表
DROP TABLE IF EXISTS `film_actor`;
CREATE TABLE `film_actor` (`id` int(11) NOT NULL AUTO_INCREMENT,`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;

2.1、ID

  查询的标识符。每个查询(尤其是多表连接查询)都有一个唯一的 id,表示查询的执行顺序。id越大,优先级越高,如果id相同,则按照先后顺序。若是简单查询,id 只会有一个值。

2.2、select_type

  查询类型。表示查询的不同组成部分,例如简单查询、联合查询、子查询等。其常见的值:

  • SIMPLE:简单查询,没有使用子查询。
explain select * from actor;

在这里插入图片描述

  • PRIMARY:复杂查询中最外层的查询。
  • SUBQUERY:子查询中的查询。
  • DERIVED:派生表(即在 FROM 子句中嵌套的查询)。
explain select (select 1 from actor where id = 1) from (select * from film where id = 1) der

在这里插入图片描述  即上面的sql语句,依照优先级,最先执行的一定是from后面的子句,因为前面的查询条件都是依赖此。from后的子句即是DERIVED类型。然后执行的是最外层select后的子查询,因为最外层select的目标字段即是子查询的结果,为SUBQUERY类型。最后执行的是最外层的select语句,为PRIMARY类型。

  • UNION:联合查询的第二个及以后的部分。
  • UNION ALL:与 UNION 类似,但不去重结果。
explain select 1 union all select 1;

在这里插入图片描述

2.3、table

  正在访问的表的名称。如果是联合查询或者多表查询,table 会列出每个表。当 from 子句中有子查询时,table列是 格式,表示当前查询依赖 id=N 的查询,于是先执行 id=N 的查询。

2.4、partitions

  如果表使用了分区,这一列会显示正在扫描的分区。分区是将表分成多个物理部分,以便更高效地管理和查询。注意,实际开发中很少用到分区,而是使用分库分表。

2.5、type(重点)

  连接类型,表示 MySQL 执行查询时访问表的方式。连接类型是评估查询效率的重要指标,性能越差的连接类型排序越靠后,是explain中的关键信息,sql优化正是基于此字段的值:
在这里插入图片描述

  • ALL:全表扫描,表示没有使用索引,性能最差。
explain select * from actor

  actor表只有一个id主键索引,*中不仅包含了id,还有其他两个字段,由于 actor 表的其他字段没有索引,查询需要扫描整个表来返回所有记录。
在这里插入图片描述

  • index:索引扫描,扫描整个索引,但不需要访问表中的数据行。
explain select * from film;

在这里插入图片描述

  • range:范围扫描,扫描索引中的某个范围(如 BETWEEN 或 > 操作符)。
explain select * from actor where id > 1;

在这里插入图片描述

  • ref:通过非唯一索引查找匹配的记录。
explain select * from film where name = 'film1';

在这里插入图片描述

  • eq_ref:通过唯一索引查找记录。对于每个表的记录,都只返回一行。
explain select * from film_actor left join film on film_actor.film_id = film.id;

在这里插入图片描述

  • const:常量表访问,通常是常量查询,只有一行结果。非常高效。
explain SELECT * FROM actor WHERE id = 1 AND name = 'a';

在这里插入图片描述

  • system:单行表扫描,类似于 const,但表大小为 1 行。

2.6、key

  实际使用的索引。这个字段告诉你在查询执行过程中,MySQL 实际上选择了哪个索引。如果值为 NULL,表示没有使用索引,可能导致全表扫描。

2.7、key_len

  表示使用的索引的长度。这个值帮助判断 MySQL 是否使用了索引的全部部分。越大的值表示索引的使用越完整。

2.8、ref

  显示查询中索引列与常量值、其他表的列或表达式的匹配方式。通常是通过列与列、列与常量匹配。

  • const:表示索引查找的常量值。
  • func:通过函数操作进行的匹配。
  • table_name.column_name:表示某个表的列与另一个表的列进行比较。

2.9、rows

  表示 MySQL 估算查询需要扫描的行数。这个数字是估算值,表示为了找到查询结果,MySQL 需要扫描的行数。(非准确值)

  此外还有filtered:表示查询在扫描过程中应用了多少过滤器,通常是以百分比的形式表示。例如,50 表示查询中 50% 的行被筛选掉。extra也是一个关键的指标,常见的如下所示:

  • Using index:表示查询是通过索引访问的,且没有回表。
explain SELECT id, name FROM film

在这里插入图片描述

  • Using where:表示使用了 WHERE 子句进行额外的过滤,并且查询的列未被索引覆盖
explain select * from actor where name = 'a';

在这里插入图片描述

  • Using temporary:表示 MySQL 创建了临时表来处理查询。
explain select distinct name from actor;

在这里插入图片描述

  • Using filesort:表示 MySQL 在查询结果上进行了文件排序
explain select * from actor order by name;

在这里插入图片描述

  • no matching row in const table:表示 WHERE 子句的条件永远无法满足,查询会返回空结果。
explain select * from film where id = 10000

在这里插入图片描述

三、索引失效解析

  首先我们创建了一张表,表中有一个id主键索引,以及name,age,position组成的联合索引:

CREATE TABLE `employees` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(24) NOT NULL DEFAULT '' COMMENT '姓名',`age` int(11) NOT NULL DEFAULT '0' COMMENT '年龄',`position` varchar(20) NOT NULL DEFAULT '' COMMENT '职位',`hire_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '入职时间',PRIMARY KEY (`id`),KEY `idx_name_age_position` (`name`, `age`, `position`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='员工记录表';INSERT INTO employees(name, age, position, hire_time) VALUES('LiLei', 22, 'manager', NOW());
INSERT INTO employees(name, age, position, hire_time) VALUES('HanMeimei', 23, 'dev', NOW());
INSERT INTO employees(name, age, position, hire_time) VALUES('Lucy', 23, 'dev', NOW());

  联合索引在B+树中的结构大致如下:
在这里插入图片描述  导致联合索引失效的场景,最主要的是没有遵守最左前缀法则。为何跳过中间列会导致索引失效?还是回到前篇中的那句话,索引是帮助MySQL高效获取数据的排好序的数据结构。如果跳过中间某一列,那后续的字段必然是没有排序完成的。联合索引中,后列的排序是依赖前列的排序结果的。除此之外,还有一些常见的索引失效场景:

3.1、索引失效场景一:在索引列上进行计算

  例如:

EXPLAIN SELECT * FROM employees WHERE left(name,3) = 'LiLei';

  如果对索引列进行函数计算,例如截取,转换,也就是索引字段发生了改变,则在B+树的数据结构中就无法匹配,导致索引失效。也就是索引依赖于列的原始值。并且如果在查询中使用了算术计算或函数(如 +, -, *, DIV, YEAR(), DATE() 等),则 MySQL 必须对每一行数据进行计算,才能与查询条件进行匹配,因为函数使初始B+树维护的索引中的值/类型发生了改变。这使得索引失去了作用,因为索引的目的是避免访问表中的每一行,快速定位到符合条件的行。如果需要计算索引列的值,MySQL就无法直接使用索引,而是需要扫描所有数据行。

3.2、索引失效场景二:使用索引中范围条件右边的列

  例如:

EXPLAIN SELECT * FROM employees WHERE name= 'LiLei' AND age > 22 AND position ='manager';

在这里插入图片描述  虽然没有违背最左前缀法则,但是范围查询放在了中间的位置,也是导致了position 索引的失效(观察key_len字段的值,如果联合索引生效,则应该为140),在执行这条sql时:

  • MySQL 会先根据 name = ‘LiLei’ 来定位到符合的记录(如果 name 上有索引)。
  • 然后,它会应用 age > 22 条件,这时会扫描符合 name = ‘LiLei’ 条件的所有记录,并对 age 列进行范围筛选。
  • 由于 position = ‘manager’ 是等值查询,并且出现在范围条件之后,它无法在 索引扫描阶段 利用 position 列。

  因为一旦范围条件被处理,索引的扫描只能停止在范围条件的位置,因此后面的列(如 position)的条件必须通过其他方式处理,可能会导致索引的部分失效或者需要回表扫描。

3.3、索引失效场景三:使用< 、> 、 <=、>=、!=

  例如:

EXPLAIN SELECT * FROM employees WHERE name != 'LiLei';

  但是此条并非绝对,mysql内部优化器会根据检索比例、表大小等多个因素整体评估是否使用索引。

3.4、索引失效场景四:使用’%字段’或’%字段%’

  例如:

EXPLAIN SELECT * FROM employees WHERE name like '%Lei'

在这里插入图片描述  原因在于,在B+树中,索引依赖于从左到右的顺序匹配,% 表示任意数量的字符,MySQL 无法利用索引从开始位置快速定位到符合条件的数据行,而是必须逐行扫描表中的每一行以进行模糊匹配。
  为什么使用’字段%'索引不会失效?因为最左边的部分已经确定了。

3.5、索引失效场景五:字符串未加单引号

  例如:

SELECT * FROM employees WHERE name = John;

  在 SQL 中,字符串 值必须被 单引号包围。这是 SQL 的语法要求,用来明确区分字符串列名其他数据类型。如果不加单引号,MySQL 会尝试将它们解析为列名、表名或其他可能的数据类型。

在这里插入图片描述

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

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

相关文章

【Go学习】-01-5-网络编程

【Go学习】-01-5-网络编程 1 互联网协议介绍1.1 互联网分层模型 2 Go网络编程2.1 socket编程2.1.1 socket图解2.2.2 TCP编程2.2.3 UDP编程 2.3 http编程2.3.1 web工作流程2.3.2 HTTP协议 2.4 WebSocket编程2.5 聊天室的小例子2.5.1 server.go文件代码2.5.2 hub.go文件代码2.5.3…

推荐系统重排:MMR 多样性算法

和谐共存&#xff1a;相关性与多样性在MMR中共舞 推荐系统【多样性算法】系列文章&#xff08;置顶&#xff09; 1.推荐系统重排&#xff1a;MMR 多样性算法 2.推荐系统重排&#xff1a;DPP 多样性算法 引言 在信息检索和推荐系统中&#xff0c;提供既与用户查询高度相关的文…

简历_熟悉缓存高并发场景处理方法,如缓存穿透、缓存击穿、缓存雪崩

系列博客目录 文章目录 系列博客目录1.缓存穿透总结 2.缓存雪崩3.缓存击穿代码总结 1.缓存穿透 缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在&#xff0c;这样缓存永远不会生效&#xff0c;这些请求都会打到数据库。 常见的解决方案有两种&#xff1a; 缓存空对…

Rabbitmq追问1

如果消费端代码异常&#xff0c;未手动确认&#xff0c;那么这个消息去哪里 2024-12-31 21:19:12 如果消费端代码发生异常&#xff0c;未手动确认&#xff08;ACK&#xff09;的情况下&#xff0c;消息的处理行为取决于消息队列的实现和配置&#xff0c;以下是基于 RabbitMQ …

STM32-笔记37-吸烟室管控系统项目

一、项目需求 1. 使用 mq-2 获取环境烟雾值&#xff0c;并显示在 LCD1602 上&#xff1b; 2. 按键修改阈值&#xff0c;并显示在 LCD1602 上&#xff1b; 3. 烟雾值超过阈值时&#xff0c;蜂鸣器长响&#xff0c;风扇打开&#xff1b;烟雾值小于阈值时&#xff0c;蜂鸣器不响…

2、pycharm常用快捷命令和配置【持续更新中】

1、常用快捷命令 Ctrl / 行注释/取消行注释 Ctrl Alt L 代码格式化 Ctrl Alt I 自动缩进 Tab / Shift Tab 缩进、不缩进当前行 Ctrl N 跳转到类 Ctrl 鼠标点击方法 可以跳转到方法所在的类 2、使用pip命令安装request库 命令&#xff1a;pip install requests 安装好了…

SpringCloud系列教程:微服务的未来(八)项目部署、DockerCompose

本博客将重点介绍如何在 Docker 环境中部署一个 Java 项目&#xff0c;并使用 Docker Compose 来简化和管理多个服务的协调部署。我们将通过一个典型的 Java Web 应用&#xff08;如基于 Spring Boot 的应用&#xff09;为例&#xff0c;演示如何构建、配置和运行 Docker 容器&…

微信小程序滑动解锁、滑动验证

微信小程序简单滑动解锁 效果 通过 movable-view &#xff08;可移动的视图容器&#xff0c;在页面中可以拖拽滑动&#xff09;实现的简单微信小程序滑动验证 movable-view 官方说明&#xff1a;https://developers.weixin.qq.com/miniprogram/dev/component/movable-view.ht…

Conda 安装 Jupyter Notebook

文章目录 1. 安装 Conda下载与安装步骤&#xff1a; 2. 创建虚拟环境3. 安装 Jupyter Notebook4. 启动 Jupyter Notebook5. 安装扩展功能&#xff08;可选&#xff09;6. 更新与维护7. 总结 Jupyter Notebook 是一款非常流行的交互式开发工具&#xff0c;尤其适合数据科学、机器…

【小程序开发】- 小程序版本迭代指南(版本发布教程)

一&#xff0c;版本号 版本号是小程序版本的标识&#xff0c;通常由一系列数字组成&#xff0c;如 1.0.0、1.1.0 等。版本号的格式通常是 主版本号.次版本号.修订号 主版本号&#xff1a;当小程序有重大更新或不兼容的更改时&#xff0c;主版本号会增加。 次版本号&#xff1a…

【保姆级】sql注入之堆叠注入

一、堆叠注入的原理 mysql数据库sql语句的默认结束符是以";"号结尾&#xff0c;在执行多条sql语句时就要使用结束符隔 开,而堆叠注入其实就是通过结束符来执行多条sql语句 比如我们在mysql的命令行界面执行一条查询语句,这时语句的结尾必须加上分号结束 select * fr…

Word如何设置整段背景色

1&#xff09; 不是1&#xff09;&#xff0c;也不是2&#xff09;&#xff0c;而是3&#xff09;的样式 2&#xff09; 红色标出这个地方有上边框&#xff0c;点击“边框和底纹” 3&#xff09;点击底纹Tab页&#xff0c;再填充&#xff0c;选择要的颜色就OK啦。

Nginx:性能优化

性能优化是确保 Nginx 在高负载下依然能够高效运行的关键部分。通过合理的配置和调优,可以显著提升 Web 服务的响应速度、吞吐量以及资源利用率。 1. 调整工作进程数、并发连接数以及cpu亲和性 worker_processes:根据 CPU 核心数设置适当的工作进程数。一般cpu有多少核,就设…

分布式事务介绍 Seata架构与原理+部署TC服务 示例:黑马商城

1. 什么是分布式事务? 在分布式系统中&#xff0c;如果一个业务需要多个服务合作完成&#xff0c;而且每一个服务都有事务&#xff0c;多个事务必须同时成功或失败&#xff0c;这样的事务就是分布式事务。其中的每个服务的事务就是一个分支事务。整个业务称为全局事务。 打个比…

C#运动控制系统:雷赛控制卡实用完整例子 C#雷赛开发快速入门 C#雷赛运动控制系统实战例子 C#快速开发雷赛控制卡

雷赛控制技术 DMC系列运动控制卡是一款新型的 PCI/PCIe 总线运动控制卡。可以控制多个步进电机或数字式伺服电机&#xff1b;适合于多轴点位运动、插补运动、轨迹规划、手轮控制、编码器位置检测、IO 控制、位置比较、位置锁存等功能的应用。 DMC3000 系列卡的运动控制函数库功…

快速上手LangChain(四)LangChain Hub和LangSmith

文章目录 快速上手LangChain&#xff08;四&#xff09;LangChain Hub和LangSmith什么是LangChain HubLangChain Hub功能 LangSmith使用 快速上手LangChain&#xff08;四&#xff09;LangChain Hub和LangSmith 什么是LangChain Hub LangChain Hub官网地址&#xff1a;https:…

学英语学压测:03jmeter组件-采样器、逻辑控制器

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#xff1a;先看关键单词&#xff0c;再看英文&#xff0c;最后看中文总结&#xff0c;再回头看一遍英文原文&#xff0c;效果更佳&#xff01;&#xff01; 关键词 assertion断言/əˈsɜrʃən/configuration element配置元素/ˌkɒ…

配置嵌入式服务器

一、如何定制和修改Servlet容器的相关配置 修改和server有关的配置&#xff08;ServerProperties&#xff09; server.port8081 server.context‐path/tx server.tomcat.uri-encodingUTF-8二、注册servlet三个组件【Servlet、Filter、Listener】 由于SpringBoot默认是以jar包…

文献分享:RoarGraph——跨模态的最邻近查询

文章目录 1. \textbf{1. } 1. 导论 1.1. \textbf{1.1. } 1.1. 研究背景 1.2. \textbf{1.2. } 1.2. 本文的研究 1.3. \textbf{1.3. } 1.3. 有关工作 2. \textbf{2. } 2. 对 OOD \textbf{OOD} OOD负载的分析与验证 2.1. \textbf{2.1. } 2.1. 初步的背景及其验证 2.1.1. \textbf{2…

智慧工地信息管理与智能预警平台

建设背景与政策导向 智慧工地信息管理与智能预警平台的出现&#xff0c;源于工地管理面临的诸多挑战&#xff0c;如施工地点分散、危险区域多、监控手段落后等。随着政府对建筑产业现代化的积极推动&#xff0c;各地纷纷出台政策支持智慧工地的发展&#xff0c;旨在通过信息技…