Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解

news2025/6/10 16:38:07

文章目录

    • 一、开启慢查询日志,定位耗时SQL
      • 1.1 查看慢查询日志是否开启
      • 1.2 临时开启慢查询日志
      • 1.3 永久开启慢查询日志
      • 1.4 分析慢查询日志
    • 二、使用EXPLAIN分析SQL执行计划
      • 2.1 EXPLAIN的基本使用
      • 2.2 EXPLAIN分析案例
      • 2.3 根据EXPLAIN结果优化SQL
    • 三、使用SHOW PROFILE分析SQL执行过程
      • 3.1 开启SHOW PROFILE功能
      • 3.2 使用SHOW PROFILE分析SQL
      • 3.3 根据SHOW PROFILE结果优化SQL
    • 四、总结

在实际的MySQL数据库应用中,随着数据量的增长和业务逻辑的复杂化,SQL执行效率逐渐成为影响系统性能的关键因素。慢SQL的出现会导致系统响应时间变长、吞吐量下降,甚至影响用户体验和业务正常运行。因此,如何快速诊断和分析慢SQL,成为了数据库管理员和开发人员必须掌握的技能。本文将围绕开启慢查询日志定位耗时SQL,以及使用EXPLAIN、SHOW PROFILE等工具分析SQL执行性能瓶颈展开详细介绍,并通过实际案例加深理解。

一、开启慢查询日志,定位耗时SQL

慢查询日志是MySQL提供的一个重要功能,它能够记录执行时间超过指定阈值的SQL语句。通过慢查询日志,我们可以快速定位到那些执行效率低下的SQL,为后续的优化提供依据。

1.1 查看慢查询日志是否开启

在开始配置慢查询日志之前,我们需要先查看当前MySQL是否已经开启了慢查询日志。可以通过以下SQL语句查看:

SHOW VARIABLES LIKE '%slow_query_log%';

执行上述语句后,会得到类似如下的结果:

+---------------------+--------------------------------------+
| Variable_name       | Value                                |
+---------------------+--------------------------------------+
| slow_query_log      | OFF                                  |
| slow_query_log_file | /var/lib/mysql/localhost-slow.log    |
+---------------------+--------------------------------------+

如果slow_query_log的值为OFF,则表示慢查询日志未开启;如果为ON,则表示已开启。同时,slow_query_log_file字段显示了慢查询日志的存储路径。

1.2 临时开启慢查询日志

如果慢查询日志未开启,我们可以通过以下方式临时开启。在MySQL命令行中执行:

SET GLOBAL slow_query_log = ON;

这种方式开启慢查询日志只在当前MySQL服务会话期间有效,当MySQL服务重启后,设置会失效。同样,我们也可以使用SET GLOBAL语句临时修改慢查询的时间阈值,例如将阈值设置为1秒(单位为秒):

SET GLOBAL long_query_time = 1;

这样,执行时间超过1秒的SQL语句都会被记录到慢查询日志中。

1.3 永久开启慢查询日志

为了确保慢查询日志在MySQL服务重启后依然生效,我们需要修改MySQL的配置文件。不同操作系统下MySQL的配置文件路径可能不同,常见的路径如下:

  • Linux系统:通常在/etc/my.cnf/etc/mysql/my.cnf
  • Windows系统:一般在MySQL安装目录下的my.ini文件

打开配置文件,在[mysqld]节点下添加或修改以下配置:

[mysqld]
slow_query_log = 1
slow_query_log_file = /var/lib/mysql/localhost-slow.log  # 根据实际情况修改日志存储路径
long_query_time = 1  # 设置慢查询时间阈值,单位为秒

修改完成后,保存配置文件,并重启MySQL服务,使配置生效。

1.4 分析慢查询日志

当慢查询日志开启后,随着系统的运行,符合条件的慢SQL会被记录到日志文件中。日志文件的内容格式大致如下:

# Time: 2024-12-10T14:23:45.000000Z
# User@Host: root[root] @ localhost []  Id:    123
# Query_time: 2.567890  Lock_time: 0.000123  Rows_sent: 10  Rows_examined: 1000
SET timestamp=1733816625;
SELECT * FROM large_table WHERE condition_column = 'value';

从日志中我们可以获取到以下关键信息:

  • Time:SQL语句的执行时间戳
  • User@Host:执行SQL的用户和主机信息
  • Query_time:SQL语句的执行时间,单位为秒
  • Lock_time:SQL语句获取锁的时间
  • Rows_sent:返回给客户端的行数
  • Rows_examined:查询过程中检查的行数
  • 具体SQL语句:实际执行的SQL语句

通过分析这些信息,我们可以初步判断哪些SQL语句执行效率低,以及可能存在的问题,例如扫描行数过多、锁等待时间长等。

二、使用EXPLAIN分析SQL执行计划

定位到慢SQL后,我们需要进一步分析其执行过程,找出性能瓶颈。EXPLAIN是MySQL提供的一个强大工具,它可以帮助我们查看SQL语句的执行计划,了解MySQL是如何执行查询的。

2.1 EXPLAIN的基本使用

对于任意一条SQL查询语句,我们只需要在其前面加上EXPLAIN关键字即可查看执行计划。例如,对于查询语句SELECT * FROM users WHERE age > 18 AND city = 'Beijing';,我们可以这样使用EXPLAIN:

EXPLAIN SELECT * FROM users WHERE age > 18 AND city = 'Beijing';

执行上述语句后,会得到一个包含多个字段的结果集,每个字段都有其特定的含义:

  • id:表示查询的执行顺序,id值相同则按从上到下的顺序执行,id值不同时,值越大越先执行
  • select_type:表示查询的类型,常见的类型有SIMPLE(简单查询,不包含子查询和联合查询)、PRIMARY(主查询)、SUBQUERY(子查询)等
  • table:表示当前查询涉及的表
  • type:表示表的连接类型,性能从好到差依次为system > const > eq_ref > ref > range > index > ALL。一般来说,我们希望查询的连接类型至少是range及以上
  • possible_keys:显示可能使用的索引
  • key:实际使用的索引,如果为NULL,则表示没有使用索引
  • key_len:索引字段的长度
  • ref:显示使用哪个列或常数与索引进行比较
  • rows:MySQL预估需要扫描的行数
  • Extra:包含额外的信息,例如Using where表示使用了WHERE条件过滤数据,Using index表示使用了覆盖索引等

2.2 EXPLAIN分析案例

假设我们有一个orders表,包含idorder_numbercustomer_idorder_date等字段,现在有一个查询语句SELECT * FROM orders WHERE order_date > '2024-01-01';,我们使用EXPLAIN分析其执行计划:

EXPLAIN SELECT * FROM orders WHERE order_date > '2024-01-01';

执行结果如下:

+----+-------------+--------+------------+-------+---------------+------+---------+------+--------+----------+-------------+
| id | select_type | table  | partitions | type  | possible_keys | key  | key_len | ref  | rows   | filtered | Extra       |
+----+-------------+--------+------------+-------+---------------+------+---------+------+--------+----------+-------------+
|  1 | SIMPLE      | orders | NULL       | range | idx_order_date| idx_order_date | 4 | NULL | 10000 |   100.00 | Using where |
+----+-------------+--------+------------+-------+---------------+------+---------+------+--------+----------+-------------+

从结果中可以看出,typerange,表示使用了范围查询,keyidx_order_date,说明使用了order_date字段上的索引idx_order_date,这是比较理想的情况。但如果typeALL,表示全表扫描,那么就需要考虑优化索引或查询条件了。

2.3 根据EXPLAIN结果优化SQL

如果EXPLAIN结果显示存在性能问题,我们可以根据具体情况进行优化。例如,如果发现没有使用索引(keyNULL),可以检查查询条件是否合理,是否存在函数运算、类型不匹配等导致索引失效的情况。或者考虑添加合适的索引来提高查询效率。

假设我们有一个查询语句SELECT * FROM products WHERE UPPER(product_name) = 'PRODUCT_A';,使用EXPLAIN分析后发现没有使用索引,因为对product_name字段使用了UPPER函数,导致索引失效。我们可以通过修改查询条件,将函数运算移到应用层,改为SELECT * FROM products WHERE product_name = 'product_a';,这样就有可能使用到product_name字段上的索引了。

三、使用SHOW PROFILE分析SQL执行过程

虽然EXPLAIN能够帮助我们了解SQL的执行计划,但它无法提供SQL执行过程中各个阶段的具体耗时情况。而SHOW PROFILE则可以深入分析SQL执行过程中每个阶段的时间开销,进一步定位性能瓶颈。

3.1 开启SHOW PROFILE功能

在使用SHOW PROFILE之前,我们需要先确认该功能是否已开启。可以通过以下SQL语句查看:

SHOW VARIABLES LIKE 'profiling';

如果profiling的值为OFF,则需要开启该功能。可以通过以下语句临时开启:

SET profiling = 1;

同样,这种方式开启只在当前会话有效,若要永久开启,需要修改MySQL配置文件,在[mysqld]节点下添加profiling = 1

3.2 使用SHOW PROFILE分析SQL

开启SHOW PROFILE功能后,执行需要分析的SQL语句。例如执行SELECT * FROM large_table WHERE condition_column = 'value';,然后使用以下语句查看SQL的执行概况:

SHOW PROFILE;

执行结果会列出该SQL语句在各个阶段的耗时情况,大致如下:

+----------------------+----------+
| Status               | Duration |
+----------------------+----------+
| starting             | 0.000032 |
| checking permissions | 0.000008 |
| Opening tables       | 0.000013 |
| init                 | 0.000016 |
| System lock          | 0.000006 |
| optimizing           | 0.000005 |
| statistics           | 0.000010 |
| preparing            | 0.000007 |
| executing            | 0.000005 |
| Sending data         | 2.567890 |
| end                  | 0.000004 |
| query end            | 0.000003 |
| closing tables       | 0.000006 |
| freeing items        | 0.000011 |
| cleaning up          | 0.000005 |
+----------------------+----------+

从结果中可以清晰地看到,Sending data阶段耗时最长,这可能意味着查询返回的数据量较大,或者在数据传输过程中存在性能问题。

如果我们想查看更详细的信息,可以使用以下语句:

SHOW PROFILE ALL FOR QUERY query_id;

其中query_id可以通过SHOW PROFILE语句的结果中获取。执行上述语句后,会得到更详细的各个阶段的时间开销和资源使用情况,包括CPU时间、内存使用等信息,帮助我们更精准地定位性能瓶颈。

3.3 根据SHOW PROFILE结果优化SQL

根据SHOW PROFILE的分析结果,我们可以针对耗时较长的阶段进行优化。例如,如果发现Sending data阶段耗时多,可能需要优化查询条件,减少返回的数据量;如果optimizing阶段耗时较长,可能需要调整索引或查询结构,提高查询优化效率。

四、总结

通过开启慢查询日志,我们能够快速定位到耗时较长的SQL语句;利用EXPLAIN工具,我们可以深入分析SQL的执行计划,了解索引的使用情况和表的连接类型,从而发现潜在的性能问题;借助SHOW PROFILE,我们可以进一步剖析SQL执行过程中各个阶段的时间开销,精准定位性能瓶颈。在实际的数据库优化工作中,我们需要综合运用这些方法和工具,逐步优化SQL语句,提高MySQL数据库的性能,为系统的稳定运行提供有力保障。

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

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

相关文章

数据结构第5章:树和二叉树完全指南(自整理详细图文笔记)

名人说:莫道桑榆晚,为霞尚满天。——刘禹锡(刘梦得,诗豪) 原创笔记:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 上一篇:《数据结构第4章 数组和广义表》…

Windows电脑能装鸿蒙吗_Windows电脑体验鸿蒙电脑操作系统教程

鸿蒙电脑版操作系统来了,很多小伙伴想体验鸿蒙电脑版操作系统,可惜,鸿蒙系统并不支持你正在使用的传统的电脑来安装。不过可以通过可以使用华为官方提供的虚拟机,来体验大家心心念念的鸿蒙系统啦!注意:虚拟…

基于江科大stm32屏幕驱动,实现OLED多级菜单(动画效果),结构体链表实现(独创源码)

引言 在嵌入式系统中,用户界面的设计往往直接影响到用户体验。本文将以STM32微控制器和OLED显示屏为例,介绍如何实现一个多级菜单系统。该系统支持用户通过按键导航菜单,执行相应操作,并提供平滑的滚动动画效果。 本文设计了一个…

yaml读取写入常见错误 (‘cannot represent an object‘, 117)

错误一:yaml.representer.RepresenterError: (‘cannot represent an object’, 117) 出现这个问题一直没找到原因,后面把yaml.safe_dump直接替换成yaml.dump,确实能保存,但出现乱码: 放弃yaml.dump,又切…

WebRTC调研

WebRTC是什么,为什么,如何使用 WebRTC有什么优势 WebRTC Architecture Amazon KVS WebRTC 其它厂商WebRTC 海康门禁WebRTC 海康门禁其他界面整理 威视通WebRTC 局域网 Google浏览器 Microsoft Edge 公网 RTSP RTMP NVR ONVIF SIP SRT WebRTC协…

针对药品仓库的效期管理问题,如何利用WMS系统“破局”

案例: 某医药分销企业,主要经营各类药品的批发与零售。由于药品的特殊性,效期管理至关重要,但该企业一直面临效期问题的困扰。在未使用WMS系统之前,其药品入库、存储、出库等环节的效期管理主要依赖人工记录与检查。库…

从零开始了解数据采集(二十八)——制造业数字孪生

近年来,我国的工业领域正经历一场前所未有的数字化变革,从“双碳目标”到工业互联网平台的推广,国家政策和市场需求共同推动了制造业的升级。在这场变革中,数字孪生技术成为备受关注的关键工具,它不仅让企业“看见”设…

AD学习(3)

1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…

JDK 17 序列化是怎么回事

如何序列化?其实很简单,就是根据每个类型,用工厂类调用。逐个完成。 没什么漂亮的代码,只有有效、稳定的代码。 代码中调用toJson toJson 代码 mapper.writeValueAsString ObjectMapper DefaultSerializerProvider 一堆实…

倒装芯片凸点成型工艺

UBM(Under Bump Metallization)与Bump(焊球)形成工艺流程。我们可以将整张流程图分为三大阶段来理解: 🔧 一、UBM(Under Bump Metallization)工艺流程(黄色区域&#xff…

2.3 物理层设备

在这个视频中,我们要学习工作在物理层的两种网络设备,分别是中继器和集线器。首先来看中继器。在计算机网络中两个节点之间,需要通过物理传输媒体或者说物理传输介质进行连接。像同轴电缆、双绞线就是典型的传输介质,假设A节点要给…

Qt的学习(一)

1.什么是Qt Qt特指用来进行桌面应用开发(电脑上写的程序)涉及到的一套技术Qt无法开发网页前端,也不能开发移动应用。 客户端开发的重要任务:编写和用户交互的界面。一般来说和用户交互的界面,有两种典型风格&…

Spring AOP代理对象生成原理

代理对象生成的关键类是【AnnotationAwareAspectJAutoProxyCreator】,这个类继承了【BeanPostProcessor】是一个后置处理器 在bean对象生命周期中初始化时执行【org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization】方法时…

密码学基础——SM4算法

博客主页:christine-rr-CSDN博客 ​​​​专栏主页:密码学 📌 【今日更新】📌 对称密码算法——SM4 目录 一、国密SM系列算法概述 二、SM4算法 2.1算法背景 2.2算法特点 2.3 基本部件 2.3.1 S盒 2.3.2 非线性变换 ​编辑…

aardio 自动识别验证码输入

技术尝试 上周在发学习日志时有网友提议“在网页上识别验证码”,于是尝试整合图像识别与网页自动化技术,完成了这套模拟登录流程。核心思路是:截图验证码→OCR识别→自动填充表单→提交并验证结果。 代码在这里 import soImage; import we…

车载诊断架构 --- ZEVonUDS(J1979-3)简介第一篇

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…

基于单片机的宠物屋智能系统设计与实现(论文+源码)

本设计基于单片机的宠物屋智能系统核心是实现对宠物生活环境及状态的智能管理。系统以单片机为中枢,连接红外测温传感器,可实时精准捕捉宠物体温变化,以便及时发现健康异常;水位检测传感器时刻监测饮用水余量,防止宠物…

Vue3 PC端 UI组件库我更推荐Naive UI

一、Vue3生态现状与UI库选择的重要性 随着Vue3的稳定发布和Composition API的广泛采用,前端开发者面临着UI组件库的重新选择。一个好的UI库不仅能提升开发效率,还能确保项目的长期可维护性。本文将对比三大主流Vue3 UI库(Naive UI、Element …

C# winform教程(二)----checkbox

一、作用 提供一个用户选择或者不选的状态,这是一个可以多选的控件。 二、属性 其实功能大差不差,除了特殊的几个外,与button基本相同,所有说几个独有的 checkbox属性 名称内容含义appearance控件外观可以变成按钮形状checkali…

pgsql:还原数据库后出现重复序列导致“more than one owned sequence found“报错问题的解决

问题: pgsql数据库通过备份数据库文件进行还原时,如果表中有自增序列,还原后可能会出现重复的序列,此时若向表中插入新行时会出现“more than one owned sequence found”的报错提示。 点击菜单“其它”-》“序列”,…