【MySQL】关于 SQL 语句执行分析的二三事

news2024/11/15 11:02:20

一、为什么要发生这件事

确实, 平时我们增删改查写的好好的, 各种业务代码,各种小接口写的不亦乐乎,正常是没时间干这个的,但是但是,这不是还有点技术追求嘛,假如我们平时测一个小接口,发现它的响应速度太慢了,当然这可能是有很多原因的,比如下面我能想到的这几种:

🌰 1. 换个操作系统部署试试,可能是在当前这个操作系统比较慢(硬件问题)
🌰 2. 考虑下是不是自己的代码写的太烂了,看看能不能优化一下
🌰 3. 可能是当前语句请求数据库的语句执行过慢了,出现了慢查询

下面是万能的 GPT 给我们的答案(太官方了,不是嘛,小傻 GPT …) :

请添加图片描述
假设,我们已经部署到了其他机器上,检查了代码,也确定了不是网络问题等等,那么下面我们就该分析一下我们的 SQL 了,本文就将介绍一下如何分析一条 SQL 语句 。

二、 MySQL 如何查看慢查询语句

1. 修改配置文件,开启慢查询日志

– 找到 MySQL 配置文件 my.cnf (linux) 或者 my.ini(window),在文件中添加以下配置

slow_query_log=1
   slow_query_log_file=/var/log/mysql/mysql-slow.log # 慢查询日志存放位置
   long_query_time=1 # 查询时间超过多长的作为慢查询被记录下来

– 重启 MySQL 服务。

– 打开 MySQL 命令行客户端,输入以下命令:

show variables like '%slow_query_log%';

– 确认慢查询日志已经开启,并查看日志文件的路径。

– 通过命令行或其他工具打开指定的日志文件,就可以看到所有的慢查询语句了。

2. mysql dump slow

使用 MySQL 自带的工具来对慢查询日志进行分析和统计,例如使用以下命令查看最慢的 10 条查询:

mysql dump slow -s t -t 10 /var/log/mysql/mysql-slow.log

三、拿到 SQL 后如何分析 —— explain

1. 稍稍说一点点原理

略略略,我不讨厌原理,但是原理真的很讨厌 , 所以就稍稍说一点点和 explain 有点关系的原理 。

首先,一条 SQL 来给 MySQL 执行了,MySQL 客户端先会连接到 MySQL 服务器,然后进行语法分析,看看是不是符合规则,不符合规则直接返回了,就是那个我们常见的错误 。

请添加图片描述

然后呢,假如没有出现问题 , 这条 SQL 就被交给 MySQL 查询优化器了,优化器会根据表的索引、表的大小、查询条件等因素来选择最优的执行方案 。然后就是熟悉的执行过程,返回结果,最后断开连接 。

通过上面,我们就能 get 到了决定我们的 SQL 如何执行的就是我们的查询优化器, 所以 explain 就是用来分析这个过程 , 其模拟了 MySQL 优化器是如何执行这个 SQL 语句的。

2. 进入正题 —— explain

以下面的 SQL 为例子,使用 explain 进行分析下面的 SQL 语句 (这里就假设我这个 SQL 是一条查询百万级数据的慢查询 SQL , 内心 OS: 连 100 条都没有, 还百万…) :

explain
(
    select *
    from hcm_hr_employee
    join hcm_abs_account
    on hcm_hr_employee.id = hcm_abs_account.employee_id
)

执行上面的分析语句后,输出下面的分析结果,我们可以看到结果有很多字段。虽然现在看起来乱七八糟的,但是通过我们下面的学习,我们就能看懂这个分析结果了 。

请添加图片描述

1. id

ps: 这个字段不咋重要,随便看看就行了
对一条 SQL 语句,虽然我们看上去是一条,但是其可以含有一些子查询,一些 join 连接,一些 union 组合,所以 MySQL 是将其拆成多个 SQL 执行的, 这些 SQL 的编号为 id。id 相同情况下,执行顺序自上向下。id 不同情况下,执行顺序为 id 值越大,优先级越高,先执行 。

2. select_type

这个字段指示了我们这条 SQL 的查询类型,含有简单查询、含复杂子查询、含 UNION 等类型,对分析慢查询也不咋重要 。

类型含义
SIMPLE简单的select 查询,即 SQL 语句中不包含子查询语句 或者 UNION。
PRIMARY查询中包含复杂的子查询部分,最外层查询语句被标记为 PRIMARY
SUBQUERY在 select 或者 where 列表中包含了子查询
DERIVED在 from 列表中包含的子查询会被标记为DERIVED(衍生表)
UNION如果第二个 select 出现在 union 之后,则被标记位 UNION
UNION RESULT从 union 后的表获取结果的 select

3. table

该行数据关于哪张表(更不重要了,为了完整性,写一下)

4. type *

数据访问类型,即我们这个数据是如何访问的,这个字段非常重要,我们可以通过这个字段判断我们当前的 SQL 语句是否出现了索引失效。数据访问类型性能由好到差为 system , const , eq_ref , ref ,range , index 和 ALL 。对 system 一听这个名字就知道用不到了,其他的多多少少都会出现,下面是其介绍:

  1. system : 平时业务中不会出现
  2. const :通过索引一次查到数据,该类型主要用于比较primary key 或者unique 索引等值查询,因为只匹配一行数据 (InnoDB 进行二分查找,快速定位到该行数据位置,然后直接返回),所以很快。
  3. eq_ref :唯一索引扫描,对于每个索引键,表中只有一条记录与之匹配,常见于主键或者唯一索引扫描。
  4. ref :非唯一索引扫描,返回匹配某个单独值得所有行,本质上是一种索引访问,它返回所有匹配某个单独值的行,就是说它可能会找到多条符合条件的数据,所以他是查找与扫描的混合体。
  5. range :只检索给定范围的行,使用一个索引来选出行。一般在你的WHERE 语句中出现between 、< 、> 、in 等查询,这种给定范围扫描比全表扫描要好。因为他只需要开始于索引的某一点,而结束于另一点,不用扫描全表索引。
  6. index :Full Index Scan 扫描遍历索引树(扫描全表的索引,从索引中获取数据)。
  7. ALL :全表扫描 ,从磁盘中获取数据 ,百万级别的数据ALL类型的数据尽量优化。

5. possible_keys

显示可能应用在这张表的索引,一个或者多个。查询涉及的字段若存在该索引,该索引就将被列出,但不一定被查询实际使用。 这是由 MySQL 自己决定的,其在某个字段唯一性差, 频繁更新的字段, 索引性能低于全表扫描(回表太多了)等时,就会选择不用索引 。

6. keys

实际使用到的索引。如果为NULL,则没有使用索引。

7. ken_len

表示索引中使用的字节数,可通过该列计算查询中使用的索引长度。在不损失精确性的情况下,长度越短越好。

8. ref

显示索引的哪一列被使用了,如果可能的话,是一个常数。

9. rows

每张表有多少行被优化器查询,根据表统计信息及索引选用的情况,大致估算出的找到所需记录需要读取的行数。

10. Extra

一些重要的扩展信息

  1. Using filesort(文件排序):无法按照既定的索引的顺序进行读取
  2. Using temporary:Mysql使用了临时表保存中间结果,常见于排序 order by 和分组查询 group by。
  3. Using index :表示相应的select 操作使用了覆盖索引,避免了回表查询的出现,性能较好 。
  • 如果同时出现Using where ,表明索引被用来执行索引键值的查找。
  • 如果没有同时出现using where 表明索引用来读取数据而非执行查找动作。
  1. Using where
  2. Using join buffer :表示当前 SQL 使用了连接缓存。
  3. impossible where :where 字句总是false ,MySQL 无法获取数据行。
  4. select tables optimized away
  5. distinct

四、举个栗子🌰

1. or 操作一定会导致索引失效吗 ,导致全表扫描吗? —— index_merge

很多网上的文章都说, or 操作会导致索引失效,但是我实际运行一下 explain 分析,发现数据访问类型变为了 index_merge ,而不是完全的失效, 索引合并表示对两个独立的索引过滤之后,再将结果合并在一起,当然这样也是非常慢的,优化方式为 : 对使用到的索引建立联合索引,再进行查询 。

请添加图片描述

2. 有索引的时候一定走索引吗 ?

来吧,展示

请添加图片描述

就算是全是按照索引字段进行筛选,也可能不走索引,因为如果按照二级索引查出的记录太多,要对这里面每条记录去聚簇索引里做一次回表,回表次数太多了,还不如全表扫描效率高,这种情况下的优化依旧是建立一个联合索引,或者使用覆盖索引,从而避免回表 。

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

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

相关文章

【LeetCode】199.二叉树的右视图

1.问题 给定一个二叉树的 根节点 root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。 示例 1: 输入: [1,2,3,null,5,null,4] 输出: [1,3,4] 示例 2: 输入: [1,null,3] 输出: [1,3] 示例 3: 输入: [] 输出: []…

类加载过程

基本说明 反射机制是Java实现动态语言的关键&#xff0c;也就是通过反射实现类动态加载。 静态加载&#xff1a;编译时加载相关的类&#xff0c;如果没有则报错&#xff0c;依赖性太强动态加载&#xff1a;运行时加载需要的类&#xff0c;如果运行时不用该类&#xff0c;即使…

C++关于线程的一些操作

线程创建和接收 std::this_thread::get_id()获取当前线程的线程ID std::this_thread::yield()让步结束当前线程的时间片 int main() {vector<thread> threads(2);threads[0] thread([]() {cout << this_thread::get_id() << endl;});threads[1] thread([](…

Baumer工业相机中偏振相机如何使用Baumer堡盟GAPI SDK来进行偏振数据的计算转换输出(C#)

项目场景 Baumer工业相机堡盟相机是一种高性能、高质量的工业相机&#xff0c;可用于各种应用场景&#xff0c;如物体检测、计数和识别、运动分析和图像处理。 Baumer的万兆网相机拥有出色的图像处理性能&#xff0c;可以实时传输高分辨率图像。此外&#xff0c;该相机还具…

ansible自动运维——ansible使用临时命令通过模块来执行任务

大家好&#xff0c;这里是天亮之前ict&#xff0c;本人网络工程大三在读小学生&#xff0c;拥有锐捷的ie和红帽的ce认证。每天更新一个linux进阶的小知识&#xff0c;希望能提高自己的技术的同时&#xff0c;也可以帮助到大家 另外其它专栏请关注&#xff1a; 锐捷数通实验&…

【机器学习实战】Python基于SVD奇异值分解进行矩阵分解(八)

文章目录 1 前言1.1 奇异值分解1.2 奇异值分解的应用 2 简单计算SVD2.1 NumPy 计算 SVD2.2 scikit-learn 计算截断 SVD2.3 scikit-learn 计算随机 SVD 3 demo数据演示3.1 导入函数3.2 导入数据3.3 计算SVD 4 讨论 1 前言 1.1 奇异值分解 奇异值分解&#xff08;Singular Valu…

信息安全复习四:置换密码乘积密码隐写术

一、章节梗概 置换密码、Rail Fence密码、行置换密码、乘积密码、转子机、隐写术 二、置换技术 2.1 定义 重新排列明文字母&#xff0c;达到信息加密的目的。 与替代密码不同的是&#xff0c;原来明文中的字母同样出现在密文中&#xff0c;只是顺序被打断。 古典的置换密码…

.net6 core Worker Service项目发布部署到Linux,以守护进程服务的形式部署启动

一、发布项目 1、以文件夹形式 2、目标运行时选对应的平台&#xff08;Linux-x64&#xff09; 3、文件夹选项&#xff1a;在发布前删除所有现有文件 二、部署项目&#xff08;安装.net6环境&#xff1a;参考Linux安装 dotnet sdk 6.0&#xff09; &#xff08;1&#xff09;…

《Spring MVC》 第二章 让程序run起来

前言 Spring MVC 是 Spring 框架提供的一款基于 MVC 模式的轻量级 Web 开发框架。 Spring MVC 本质是对 Servlet 的进一步封装&#xff0c;其最核心的组件是DispatcherServlet&#xff0c;它是 Spring MVC 的前端控制器&#xff0c;主要负责对请求和响应的统一地处理和分发。C…

用好Python自然语言工具包-- 实例“基于本地知识库的自动问答”

首先鸣谢thomas-yanxin 本问中示例来自他在GitHub上的开源项目“基于本地知识库的自动问答”&#xff0c;链接如下&#xff1a; thomas-yanxin/LangChain-ChatGLM-Webui: 基于LangChain和ChatGLM-6B的针对本地知识库的自动问答 (github.com) 目录 1. 基础知识&#xff1a; …

JVM调优最佳参数

项目背景 C端的项目&#xff0c;用户量比较多&#xff0c;请求比较多。 启动参数表 Xmx指定应用程序可用的最大堆大小。 Xms指定应用程序可用的最小堆大小。 &#xff08;一般情况下&#xff0c;需要设置Xmx和Xms为相等的值&#xff0c;且为一个固定的值&#xff09; 如果该值…

HCIP之链路聚合、VRRP

链路聚合 链路聚合 --- 可以将多个物理接口绑定成一个逻辑接口&#xff0c;即将N条物理链路聚合为一条逻辑链路。可以在不升级硬件的条件下&#xff0c;达到增加带宽的效果 我们将逻辑链路&#xff0c;称为聚合链路&#xff0c;在华为设备中称为ETH-TRUNK链路&#xff08;这个技…

Vue表单进阶操作

多选框另类使用场景 这个复选框和上面爱好那个复选框是不一样的&#xff0c;它不需要收集value值&#xff0c;只需要知道是否被选择&#xff0c;也就是ture或false&#xff0c;这时候就可以安装输入框的方式去写&#xff0c;直接去定义字符串&#xff0c;而不是数组 然后把全部…

“esp8266mod模块连接机智云Arduino实现pwm调节led的亮度“+_+

经过几天的漫长的探索和调试&#xff0c;终于连上机智云了。 历经的困难&#xff1a;esp8266总是连接机智云app超时&#xff0c;连接无反应&#xff0c;无数据。 1、机智云开发者中心&#xff0c;新建数据点&#xff0c;生成muc代码包&#xff0c;具体配置可以参考其他文章。…

go破冰之旅·5·常量、变量、数据类型

成体系的、快速学通Go&#xff0c;就在此时&#xff0c;持续连载&#xff01; 上一篇&#xff1a; https://lan6193.blog.csdn.net/article/details/123454411https://lan6193.blog.csdn.net/article/details/123454411上文熟悉了Go的基础符号、基础规则&#xff0c;本文我们…

前端项目代码规范

一、变量与函数的命名&#xff08;变量名和函数名是最好的注释&#xff09; 通常情况下函数小陀峰、类名大陀峰、变量短横线/小陀峰、const全大写单词要表达出正确的语义&#xff0c;如&#xff1a;array类型或其它集合类型用英语复数格式、其它类型不要用复数格式区分函数为功…

async/await 在 C# 语言中是如何工作的?(下)

接《async/await 在 C# 语言中是如何工作的&#xff1f;&#xff08;上&#xff09;》、《async/await 在 C# 语言中是如何工作的&#xff1f;&#xff08;中&#xff09;》&#xff0c;今天我们继续介绍 SynchronizationContext 和 ConfigureAwait。 ▌SynchronizationContext…

【SVN已解决】修改svn服务端地址为ip或者域名地址的方法

介绍 这里是小编成长之路的历程&#xff0c;也是小编的学习之路。希望和各位大佬们一起成长&#xff01; 以下为小编最喜欢的两句话&#xff1a; 要有最朴素的生活和最遥远的梦想&#xff0c;即使明天天寒地冻&#xff0c;山高水远&#xff0c;路远马亡。 一个人为什么要努力&a…

Vue之指令详解与自定义指令

指令 想要了解自定义指令&#xff0c;那肯定得先明白什么是指令。 指令的本质&#xff1a;语法糖&#xff0c;标志位。在编译阶段 render 函数里&#xff0c;会把指令编译成 JavaScript 代码。 常见的Vue内置指令有&#xff1a; v-on 即 。v-on:click”function“&#xff…

Node【Express框架【二】】

文章目录 &#x1f31f;前言&#x1f31f;中间件&#x1f31f;中间件函数&#x1f31f;什么是中间件函数&#x1f31f;中间件函数可以做什么 &#x1f31f;Express中间件的类型&#x1f31f;应用级中间件&#x1f31f;路由器级中间件&#x1f31f;错误处理中间件&#x1f31f;内…