第41讲:MySQL内置的QL性能分析工具

news2024/11/28 22:37:33

文章目录

    • 1.SQL性能分析的概念
    • 2.分析数据库中SQL的执行频率
    • 3.数据库中的慢查询日志
      • 3.1.开启慢查询日志功能
      • 3.2.模拟慢SQL查询观察日志内容
    • 4.Profile查看SQL每个阶段的耗时
      • 4.1.开启Profile操作
      • 4.2.随便执行一些查询语句
      • 4.3.查询执行SQL的耗时
      • 4.4.查询某一条SQL每个阶段的耗时
      • 4.5.查询某条SQL的CPU使用情况
    • 5.Explain分析SQL的执行计划
      • 5.1.Explain执行计划中各个字段的含义
      • 5.2.分析几个SQL的执行计划重点演示id字段的含义
      • 5.3.分析几个SQL的执行计划重点演示什么样的SQL会产生什么样的访问表类型

1.SQL性能分析的概念

在做SQL优化这类的操作时,我们首先要明确什么类型的SQL语句在数据库中的执行频率最高,往往要做SQL优化的都是SELECT查询语句,增删改的写入基本是固定的格式,也不需要优化。

例如当一个表中的数据量很大,但是基本上都是写入和更新的动作,那么我们大可不必去对表的索引和查询语句优化,是没有太大必要的,往往的优化都是对大量的查询进行优化的。

在SQL优化过程中,索引的优化占据了主导的地方,往往会对频繁查询的字段建立一个索引,增大查询的速度。

2.分析数据库中SQL的执行频率

在性能分析中,首先要明确数据库中哪类的SQL操作占的比例比较大,从而对症下药。

通过以下指令可以查询数据库中各项SQL操作的占比。

mysql> show global status like 'Com_______';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Com_binlog    | 0     |
| Com_commit    | 30    |
| Com_delete    | 23    |
| Com_import    | 0     |
| Com_insert    | 192   |
| Com_repair    | 0     |
| Com_revoke    | 5     |
| Com_select    | 4325  |
| Com_signal    | 0     |
| Com_update    | 67    |
| Com_xa_end    | 0     |
+---------------+-------+
11 rows in set (0.00 sec)

Com后面是7个下划线,表示后面的内容是7个,查询SQL的执行频率可以是全局下的统计,也可以是当前会话中的统计。

global是查询全局的SQL执行频率,session是查询当前会话中的SQL查询频率。

我们重点关注Com_select、Com_insert、Com_update、Com_delete四类SQL的频率。

根据上面输出的结果,可以分析出该数据库的查询操作占比很高。

3.数据库中的慢查询日志

通过前面的SQL执行频率,我们能得知,在数据库中查询的频率最为频繁,那么应该如何定位哪些查询语句需要优化呢?针对这些需求可以通过MySQL的慢查询日志,从中得到应该对那些SQL进行优化。

慢查询日志记录了所有执行时间超过指定参数的所有SQL查询语句,通过long_query_time参数可以设置SQL执行的超时时间,当超过该参数值的所有SQL语句将被记录到慢查询日志中,该参数的单位是秒,默认是10秒。

慢查询日志默认情况下没有开启,可以通过下面的指令查看有没有开启慢查询日志。

mysql> show variables like 'slow_query_log';
+----------------+-------+
| Variable_name  | Value |
+----------------+-------+
| slow_query_log | OFF   |
+----------------+-------+
1 row in set (0.00 sec)

3.1.开启慢查询日志功能

1.配置MySQL的配置文件开启慢查询日志
[root@mysql ~]# vim /etc/my.cnf
slow_query_log=1						#开启慢查询日志
long_query_time=2						#设置查询SQL的超时时间,当超过2秒后,就被记录到慢查询日志中

2.重启MySQL
[root@mysql ~]# systemctl restart mysqld

3.慢SQL日志文件路径
[root@mysql ~]# ll /var/lib/mysql/mysql.sock.lock
-rw------- 1 mysql mysql 5 529 17:14 /var/lib/mysql/mysql.sock.lock

3.2.模拟慢SQL查询观察日志内容

1)执行一个超长时间的查询SQL

找一张数据量大的表,执行查询指令。

select * from dabiao;

2)观察慢SQL日志

[root@mysql ~]# cat /var/lib/mysql/mysql-slow.log 
/usr/sbin/mysqld, Version: 8.0.26 (MySQL Community Server - GPL). started with:
Tcp port: 3306  Unix socket: /var/lib/mysql/mysql.sock
Time                 Id Command    Argument
# Time: 2022-05-29T09:17:14.628770Z
# User@Host: root[root] @  [192.168.20.118]  Id:     8
# Query_time: 38.426420  Lock_time: 0.000587 Rows_sent: 27126  Rows_examined: 27126
use db_1;
SET timestamp=1653815796;				#SQL执行的时间
select * from dabiao;					#完整的SQL语句

我们可以定期的翻一翻慢SQL日志,找出执行频繁且时间很长的SQL,进行优化。

4.Profile查看SQL每个阶段的耗时

在前面提到的慢SQL日志,虽然超过了我们指定时间,就会被记录到慢SQL里,但是也很有可能一些小的业务逻辑,SQL写的不是那么好,本来1秒就可以搞定的查询,结果用了七八秒,加入慢查询的时间是10秒,那么就不会记录到慢SQL里。

这时我们就可以通过Profile这个工具来分析当前会话或者全局模式下执行的SQL耗时,也可以指定查询某一条SQL每个阶段的耗时。

4.1.开启Profile操作

1)首先查一下当前数据库支不支持profile

mysql> select @@have_profiling;
+------------------+
| @@have_profiling |
+------------------+
| YES              |
+------------------+
1 row in set, 1 warning (0.00 sec)

2)查看当前MySQL是否开启profile

默认是关闭状态,0表示关闭,1表示开启。

mysql> select  @@profiling;
+-------------+
| @@profiling |
+-------------+
|           0 |
+-------------+
1 row in set, 1 warning (0.00 sec)

3)开启profile操作

可以针对当前会话session开启profile,也可以针对global开启。

mysql> set global profiling = 1;

mysql> select  @@profiling;
+-------------+
| @@profiling |
+-------------+
|           1 |
+-------------+
1 row in set, 1 warning (0.00 sec)

4.2.随便执行一些查询语句

mysql> select * from tb_user;
mysql> select * from tb_user where id = 1 ;
mysql> select * from tb_user where xm = '余伟' ;

4.3.查询执行SQL的耗时

通过以下指令可以看到每条SQL语句的耗时,可以看到查询同样的一条数据,例如9和12,指定主键索引查询的耗时为0.00083750,指定常规索引查询的耗时为0.00100925,有明显的差距。

mysql> show profiles;
+----------+------------+---------------------------------------------+
| Query_ID | Duration   | Query                                       |
+----------+------------+---------------------------------------------+
|        1 | 0.00069850 | select @@version_comment limit 1            |
|        2 | 0.00041775 | select  @@profiling                         |
|        3 | 0.00039950 | SELECT DATABASE()                           |
|        4 | 0.00038075 | SELECT DATABASE()                           |
|        5 | 0.00381225 | show databases                              |
|        6 | 0.00467850 | show tables                                 |
|        7 | 0.00531375 | select * from db_user                       |
|        8 | 0.01484700 | select * from tb_user                       |
|        9 | 0.00083750 | select * from tb_user where id = 1          |
|       10 | 0.00070725 | select * from tb_user where name = 余伟     |
|       11 | 0.00044275 | select * from tb_user where name = '余伟'   |
|       12 | 0.00100925 | select * from tb_user where xm = '余伟'     |
+----------+------------+---------------------------------------------+
12 rows in set, 1 warning (0.00 sec)

4.4.查询某一条SQL每个阶段的耗时

查询刚刚show profiles结构中id为9的SQL每个执行阶段的耗时,主要看executing字段对应的耗时。

mysql> show profile for query 9;
+--------------------------------+----------+
| Status                         | Duration |
+--------------------------------+----------+
| starting                       | 0.000141 |
| Executing hook on transaction  | 0.000014 |
| starting                       | 0.000044 |
| checking permissions           | 0.000020 |
| Opening tables                 | 0.000113 |
| init                           | 0.000019 |
| System lock                    | 0.000024 |
| optimizing                     | 0.000029 |
| statistics                     | 0.000142 |
| preparing                      | 0.000038 |
| executing                      | 0.000112 |
| end                            | 0.000019 |
| query end                      | 0.000011 |
| waiting for handler commit     | 0.000023 |
| closing tables                 | 0.000023 |
| freeing items                  | 0.000033 |
| cleaning up                    | 0.000033 |
+--------------------------------+----------+
17 rows in set, 1 warning (0.00 sec)

4.5.查询某条SQL的CPU使用情况

mysql> show profile cpu for query 9;
+--------------------------------+----------+----------+------------+
| Status                         | Duration | CPU_user | CPU_system |
+--------------------------------+----------+----------+------------+
| starting                       | 0.000141 | 0.000000 |   0.000134 |
| Executing hook on transaction  | 0.000014 | 0.000000 |   0.000012 |
| starting                       | 0.000044 | 0.000000 |   0.000045 |
| checking permissions           | 0.000020 | 0.000000 |   0.000019 |
| Opening tables                 | 0.000113 | 0.000000 |   0.000115 |
| init                           | 0.000019 | 0.000000 |   0.000017 |
| System lock                    | 0.000024 | 0.000000 |   0.000024 |
| optimizing                     | 0.000029 | 0.000000 |   0.000029 |
| statistics                     | 0.000142 | 0.000000 |   0.000144 |
| preparing                      | 0.000038 | 0.000000 |   0.000036 |
| executing                      | 0.000112 | 0.000000 |   0.000116 |
| end                            | 0.000019 | 0.000000 |   0.000014 |
| query end                      | 0.000011 | 0.000000 |   0.000012 |
| waiting for handler commit     | 0.000023 | 0.000000 |   0.000023 |
| closing tables                 | 0.000023 | 0.000000 |   0.000023 |
| freeing items                  | 0.000033 | 0.000000 |   0.000033 |
| cleaning up                    | 0.000033 | 0.000000 |   0.000033 |
+--------------------------------+----------+----------+------------+
17 rows in set, 1 warning (0.00 sec)

5.Explain分析SQL的执行计划

在前面判定一个SQL的执行效率是否高,主要是根据执行的时长来决定的,但是不一定精准。

我们可以通过EXPLAIN或者DESC指令,去分析一条SQL的执行计划,可以根据执行计划返回的内容判断SQL执行的效率。

EXPLAIN的语法结构:EXPLAIN SELECT 字段列表 FROM 表名 WHERE 条件

5.1.Explain执行计划中各个字段的含义

下面是EXPLAIN分析一个SQL的执行计划所输出的内容,可以看到包含了很多字段,那么这些字段有什么含义呢?我们下面一起来看一下。

image-20220529225526299

几个主要字段的含义如下:

  • id字段:

    • 代表select查询的序列号,表示查询语句中select语句或者操作表的顺序。
    • 单表查询只有一行数据,id永远为1。
    • 多表查询时,如果id相同,那么执行顺序从上到下依次执行。
    • 如果没有多表查询,例如子查询,一条SQL语句中有多个select语句,那么此时id显示的就会不同,id的值越大,那么就会越先执行。
  • select_type字段:

    • 表示该条SQL语句的查询类型,常见的取值有SIMPLE(简单表查询,不使用表连接或者子查询,只是单表查询)、PRIMARY(主查询)、UNION(联合查询)、SUBQUERY(SELECT/WHERE之后包含的子查询)。
  • table字段:

    • 查询的表名。
  • type字段:

    • 连接表的类型、访问表的类型,性能由好到差的连接类型为:NULL、system、const、eq_ref、ref、range、index、all。
    • 其中性能最好的是NULL,性能最差的是all,但是几乎在业务数据库中不可能会出现NULL类型的表连接,因为NULL表示不访问任何表。
    • system表示查询的是系统表,访问系统表时才会看到类型是system。
    • conset类型可以说是性能很好的类型了,当使用主键索引、唯一索引作为条件访问表时就会出现conset类型,此时性能是最好的。
    • 当使用常规索引,也就是我们创建的索引作为条件访问表时,类型就是ref。
    • 当出现index类型时,表示虽然也是用索引查询表了,但是对索引进行了全部扫描,性能也不高。
    • 在优化SQL时,尽量将连接类型优化到前面几个类型访问表,性能是最好的,当然也需要根据业务的自身逻辑去优化,尽量不要出现all,当出现all时就表示要全表扫描了。
  • possible_keys字段:

    • 显示可能会使用到表中的那些索引,一个或者多个。
  • key字段:

    • 实际使用哪个索引查询的数据,如果为NULL,就表示没有使用使用索引。
  • key_len字段:

    • 索引使用的字节数,该值为索引字段最大的可能长度,但是也非实际使用的长度,虽然不是特别精准,但是长度越短越好。
  • rows字段:

    • 认为要执行查询的行数,也就是认为要查询多少行才能拿到对应的结果,也是一个估值,不是那么精准。
  • filtered字段:

    • 表示返回结果的行数占读取行数的百分比,该字段的值越大越好,越大表示我们读取的行就是我们要查询结果的行,更加精准,性能高。

在这么多字段中,我们重点关注id、type、possible_key、key、key_len、filtered这几个字段的值,根据这些值就有了优化SQL的因素。

5.2.分析几个SQL的执行计划重点演示id字段的含义

id字段:代表select查询的序列号,表示查询语句中select语句或者操作表的顺序。

  • 单表查询只有一行数据,id永远为1。
  • 多表查询时,如果id相同,那么执行顺序从上到下依次执行。
  • 如果没有多表查询,例如子查询,一条SQL语句中有多个select语句,那么此时id显示的就会不同,id的值越大,那么就会越先执行。

1)单表查询只有一行数据,id永远为1。

explain select * from tb_user where id = '1';

image-20220529233828219

2)多表查询时,如果id相同,那么执行顺序从上到下依次执行。

只要是多表查询,那么多行记录的id不会自增,而是显示相同的值,并且执行顺序是从上到下依次执行的。

下面这条SQL是查询每个人员属于哪个部门的,共用到两张表分别是人员信息表和部门信息表。

SELECT
	r.xm,
	r.zw,
	b.bmmc 
FROM
	ryxxb AS r
	LEFT OUTER JOIN bmxxb AS b 
	ON r.bm_id = b.id;

下面我们通过EXPLAIN来分析该条SQL的执行顺序。

explain select r.xm,r.zw,b.bmmc from ryxxb as r left outer join bmxxb as b on r.bm_id = b.id; 

分析结果如下,id值相同,表的执行顺序从上到下,首先查询部门表,然后再查询人员信息表。

image-20220529234641209

一般情况下from之后的表都是先执行的,如果是三张表的多表查询,其中包含中间表,那么中间表一定是第二个执行的。

3)ID值不同,谁的ID值大谁先执行。

我们执行一个子查询的SQL,分析他的执行计划。

下面这个子查询的SQL是要查询人员信息表中薪资大于销售部全部人员薪资的其他人员信息。

下面这个SQL中select执行的顺序首先是SELECT id FROM bmxxb WHERE bmmc = '销售部',然后是SELECT xz FROM ryxxb WHERE bm_id IN这一条,最后是select * from ryxxb

SELECT
	* 
FROM
	ryxxb 
WHERE
	xz > ALL (SELECT xz FROM ryxxb WHERE bm_id IN ( SELECT id FROM bmxxb WHERE bmmc = '销售部' ));

通过explain观察执行计划。

explain select * from ryxxb where xz > all (select xz from ryxxb where bm_id in (select id from bmxxb where bmmc = '销售部'));

执行计划如下,可以看到ID有不一样的了,那么ID值越大就说明越先执行,那么bmxxb肯定是第一个执行,此时还有一个ID为2的表,相同ID,按照顺序执行,那么第二个执行的就是ryxxb表,ID为1最小,那么就会最后执行ryxxb表。

image-20220529235822084

5.3.分析几个SQL的执行计划重点演示什么样的SQL会产生什么样的访问表类型

1)NULL类型的访问表,性能最高。

NULL类型几乎在业务逻辑中出现的很少,因为不查询任何表时,才会返回NULL。

explain select 'A' ;

image-20220530000242114

2)conset类型的访问表,性能较好。

当使用主键索引或者唯一索引访问表时,都会出现conset类型。

explain select * from tb_user where id = '1' ;

image-20220530000413598

3)ref类型的访问表,性能略好。

当使用常规索引访问表时,会出现ref类型。

mysql> explain select * from tb_user where xm = '江睿基' ;

image-20220530000539396

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

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

相关文章

【ASM】字节码操作 工具类与常用类 InstructionAdapter 介绍

文章目录 1.概述1.1 为什么会有 InstructionAdapter类?2. InstructionAdapter2.1 class info2.2 fields2.3 构造方法2.4 methods3.示例3.1预期目标4.总结1.概述 在上一节:【ASM】字节码操作 工具类与常用类 AnalyzerAdapter 工作原理 我们学习了AnalyzerAdapter类的工作原理…

【OpenCV 例程 300篇】246. 特征检测之ORB算法

『youcans 的 OpenCV 例程300篇 - 总目录』 【youcans 的 OpenCV 例程 300篇】246. 特征检测之ORB算法 特征检测与匹配是计算机视觉的基本任务,包括检测、描述和匹配三个相互关联的步骤。广泛应用于目标检测、图像检索、视频跟踪和三维重建等诸多领域。 6.9.1 ORB 算…

【Hack The Box】linux练习-- SneakyMailer

HTB 学习笔记 【Hack The Box】linux练习-- SneakyMailer 🔥系列专栏:Hack The Box 🎉欢迎关注🔎点赞👍收藏⭐️留言📝 📆首发时间:🌴2022年11月23日🌴 &…

函数调用在嵌入式架构设计中的应用

函数调用很好理解,即使刚学没多久的朋友也知道函数调用是怎么实现的,即调用一个已经封装好的函数,实现某个特定的功能。 把一个或者多个功能通过函数的方式封装起来,对外只提供一个简单的函数接口,然后在其他地方调用即…

SpringCloud - Config分布式配置中心

文章目录一.概述1. 分布式系统面临的配置问题2. 什么是配置中心3. 配置中心怎么用4. 配置中心能做什么二.Config服务端配置与测试1. 搭建1.1 在github上创建一个springcloud_config的新仓库1.2 获得新仓库的地址:1.3 本地硬盘目录上新建git仓库并clone1.4 创建文件1…

设置一个不能被继承的类

小屋杂谈,记录日常 方法1: 如果想让这个类不能被继承,可以把这个类的构造函数设置成私有,这样子类去继承他构造就会报错,这样的话这个类就是不能被继承的,如果需要用这个类的对象的话,在基类里…

机器学习中的交叉熵

文章目录一、背景二、概率论基础知识三、熵≈信息熵(应用领域不同)、相对熵KL散度、交叉熵、softmax、sigmoid、交叉熵损失图像分割如何理解CrossEntropyLoss()参考资料一、背景 学习机器学习过程中,总是会遇到交叉熵这个名词。通过交叉熵损…

SpringBoot整合knife4j

1.1 Swagger 前后端分离开发:前端和后端分开进行开发,2个项目,一个是前端项目,一个是后端项目 目前基本上很多小项目都是前后端分离,除了后台管理系统 前后端分离开发,前端(app、小程序、智能硬件等)怎么…

栈(C语言实现)

文章目录:1.栈的概念2.栈的结构3.接口实现3.1初始化栈3.2判断栈是否为空3.3压栈(入栈)3.4出栈3.5查看栈顶元素3.6统计栈内元素个数3.7销毁栈1.栈的概念 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操…

Credly 数字证书

Credly 数字证书 Credly 简介 通过 Credly 颁发的徽章是对学习成果、经验或能力的数字表述。Credly 数字证书包括常见的组织徽章,如:AWS, Adobe, Autodesk, Certiport, Microsoft, CISCO, IBM 等等,以一种简单和安全的方式在线分享和验证&a…

基于改进人工蜂群算法的K均值聚类算法(Matlab代码实现)

🍒🍒🍒欢迎关注🌈🌈🌈 📝个人主页:我爱Matlab 👍点赞➕评论➕收藏 养成习惯(一键三连)🌻🌻🌻 🍌希…

基于SEIRD和元胞自动机(CA)模型的传染病发展趋势预测

目录前言一、模型假设二、符号说明三、SEIRD模型1. 模型求解四、元胞自动机(CA)模型1. 模型求解2. 城市居民减少外出对疫情发展的影响3. 城市间人口流动对疫情发展的影响五 基于防疫政策的修正模型2 “全民戴口罩”“早发现,早隔离”“全民打疫苗”总结前…

Jsonp跨域的坑,关于jsonp你真的了解吗

先来介绍Jsonp跨域 Jsonp全称是Json with Padding,和Json没有关系 Json是一种数据交换格式,而Jsonp是一种依靠开发人员聪明才智创造出的一种费官方跨域数据交换协议。json是描述信息的格式,jsonp是信息传输的协议 在页面上直接发送一个跨域的…

树莓派之树莓派系统安装

树莓派系统安装 概述 树莓派(是为学习计算机编程教育而设计),只有信用卡大小的微型电脑,其系统基于Linux。随着Windows 10 IoT的发布,我们也将可以用上运行Windows的树莓派。2014年刚知道有树莓派的时候好奇买了一块,型号&#x…

DSP-IIR滤波器设计

目录 滤波器的性能指标: 常用的模拟滤波器: 巴特沃斯滤波器: 巴特沃斯滤波器设计——一般已知Ωp及其衰减指标,Ωs及其衰减指标求得A,ε,N,Ωc: 巴特沃斯滤波器设计例题: 切比…

Python系列-Django

文章目录Python系列-Django用django实现社交媒体 social_book基本演示,点击可查看视频整体项目的创建数据库设计,基本用户创建表的设计 models.py创建用户查看数据库插件 database navigator登录、注册的实现用djangovue实现社交媒体 social_bookPython系…

【Java集合】Collection接口常用方法

文章目录Collection接口和常用方法> Collection接口常用方法> Collection接口遍历元素:使用Iterator(迭代器)> Collection接口遍历元素:增强 for 循环Collection接口和常用方法 Collection接口实现类的特点:…

CPU中的核与进程,线程间的关系讲解(操作系统基础概念)

CPU中的核与进程,线程间的关系讲解(操作系统基础概念) CPU中的内核 概念 CPU内核(Die)是CPU中间的核心芯片,由单晶硅制成,用来完成所有的计算、接受/存储命令、处理数据等,是数字…

Node.js | 详解 JWT 登录验证 的工作原理

🧑‍💼 个人简介:一个不甘平庸的平凡人🍬 🖥️ 本系列专栏:Node.js从入门到精通 🖥️ TS知识总结:十万字超详细TS知识点总结 👉 你的一键三连是我更新的最大动力❤️&…

【Java系列】一篇文章快速了解Java语言概述

Java语言概述1.Java简介2.JVM2.1JVM介绍2.2JVM特性3.Java特性4.搭建Java程序开发环境5.编写第一个Java应用程序6.小结第一个程序1.Java简介 java是面向对象的一门程序设计语言随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。后台开发&#x…