​【香菇带你学Mysql】Mysql超长执行sql定位和优化【建议收藏】

news2024/9/17 4:08:22

本文为MySQL数据库管理员和开发人员提供了一套全面的超时SQL定位和优化解决方案。通过合理运用这些方法和技巧,可以显著提升MySQL数据库的性能和稳定性,减少超时SQL语句的发生,确保数据库的高效运行。

0. 引言

最近某个Mysql数据库频繁告警,监控系统提醒有执行时间超长sql(基本上是执行时间超过1800秒)的语句。

image-20240806224456807

之前查的问题时存在某个Mysql8.0的Bug,Kill掉某个sql语句后,该sql语句实际还在运行,只能重启解决。但是由于是生产数据库。重启十分流程麻烦。进行两次维护重启后还是频繁告警,我在怀疑系统开发的sql语句到底写的是什么东西(只管查,不管耗时)。必须要和他们battle一番。要不最后还是我来背锅~

image-20240806230903579

最近一次执行时间超过30分钟的还是有70+条

image-20240806230502183

超长执行sql占用大量的数据库资源,如 CPU、内存和 I/O 带宽,导致其他并发的查询和操作响应变慢,甚至可能导致数据库死机。

今天就来和大家一起分析一下查询超长执行时间sql语句的方法和解决预防防控措施

1. 超长执行sql出现原因

数据量过大

  • 当处理大规模的数据表时,例如涉及数百万甚至数十亿条记录的查询,即使查询逻辑相对简单,也可能需要较长时间来处理和返回结果。

复杂的查询逻辑

  • 包含多层嵌套的子查询、多个表的连接操作、复杂的条件判断和聚合函数的组合使用。

    比如,一个查询同时涉及 5 个表的连接,每个表又有复杂的筛选条件,并且还包含多层子查询来获取相关的关联数据。

缺少合适的索引

  • 没有为经常用于查询、连接和排序的字段创建索引,导致数据库需要进行全表扫描来获取数据。

    例如,在一个经常根据用户 ID 进行查询的用户表中,如果没有为用户 ID 字段创建索引,每次查询都要遍历整个表。

服务器资源不足

  • 数据库服务器的硬件资源(如 CPU、内存、磁盘 I/O 性能)有限,无法快速处理复杂的查询请求。

    当服务器的内存不足时,可能会频繁进行磁盘交换,从而大大降低查询的执行速度。

网络延迟

  • 如果数据库服务器与应用程序服务器之间的网络连接不稳定或存在较高的延迟,数据传输时间会增加,导致 SQL 执行时间变长。

数据库配置不合理

  • 例如,缓存设置过小、连接池参数配置不当等。

    比如,缓冲池大小不足以容纳常用的数据,导致频繁的磁盘读取。

并发操作过多

  • 同时有大量的并发查询或更新操作,导致资源竞争和排队等待,从而延长单个 SQL 语句的执行时间。

下图为网络段子

你问我外包算什么东西?
我现在告诉你:
1:你们正编不敢连表查询,我们外包10张表都敢连

2:你们正编不敢在循环里查询数据库,我们外包敢

3:你们正编写代码考虑扩展性,我们外包直接写死

总之一句话正编做得了的,我们外包要做,正编做不了的我们外包更要做,够不够清楚

image-20240806231624529

3. sql 查询优化

正确的sql习惯可以在保证正确查询结果的前提下降低系统内存,IO的消耗,避免系统出现异常问题。

下面我将从可能导致数据库执行时间超长查询sql的情况来逐一分析并给出解决建议。

3.1 大表查询sql优化

对于数据量较大的sql语句(百万行及以上),万万不可不可直接select * ,执行时间很长不说,也很难找到我们需要的关键信息

以下是一个可能对千万级数据量的订单表进行全表扫描查询的示例 SQL 语句:

SELECT * FROM orders;

在这个示例中,* 表示选择所有列,orders 是订单表的表名。由于没有指定任何条件,这将导致对整个订单表进行全表扫描。

另一个示例是:

SELECT order_id, customer_name, total_amount FROM orders;

这个语句选择了 order_idcustomer_nametotal_amount 这几列,但同样没有添加任何筛选条件,仍然会进行全表扫描。

需要注意的是,在实际应用中,对如此大规模的数据量进行全表扫描通常是不推荐的,因为这可能会导致性能严重下降。应该尽量根据具体的业务需求添加合适的条件来缩小查询范围,例如:

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

这个语句只会查询订单日期在 2024 年 8 月 1 日之后的订单,从而减少需要扫描的数据量,提高查询性能。

同样也可以限制查询结果数量

下面sql语句是从 orders 表中选取前 10 行的数据

SELECT * FROM orders BY order_id LIMIT limit 10

3.2 复杂查询逻辑sql优化

对于复杂查询逻辑sql,我们尽量分开查询,避免一次执行,这样虽然可能看似方便,实际执行时间太长,导致查询效率很低

部分优化方法如下

使用合适的索引

  • 分析查询中经常用于条件判断、连接和排序的字段,为这些字段创建合适的索引。

    例如,如果经常根据 order_date 字段进行查询,可以创建索引:CREATE INDEX idx_order_date ON orders (order_date);

分解复杂查询

  • 将一个复杂的大查询分解为多个较小的、更简单的查询,然后在应用程序层进行组合和处理。

    比如,原本一个包含多个子查询和连接的复杂查询,可以拆分为先获取一部分数据,然后基于这部分数据再进行后续的查询。

避免不必要的计算和函数

WHERE子句中尽量避免使用复杂的计算和函数,这可能会导致索引无法使用。

例如,不要写成 WHERE YEAR(order_date) = 2024 ,而是直接写成 WHERE order_date >= '2024-01-01' AND order_date < '2025-01-01'

优化连接操作

  • 确保连接条件准确且高效,尽量使用主键或有索引的字段进行连接。

    比如,在连接两个表时,使用具有索引的 id 字段进行关联。

减少数据量

  • 在查询的早期阶段通过条件过滤掉尽可能多的数据,减少后续操作的数据量。

    先使用 WHERE 子句筛选出符合条件的记录,再进行其他操作。

使用临时表

  • 对于一些中间结果集,可以将其存储在临时表中,以提高查询的可读性和性能。

调整数据库配置参数

  • 根据服务器的硬件资源和业务需求,调整一些数据库的配置参数,如缓冲池大小、并发连接数等。

例如,有一个复杂的查询语句:

SELECT o.order_id, c.customer_name, SUM(o.order_amount) AS total_amount
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id
WHERE o.order_date BETWEEN '2024-01-01' AND '2024-08-06'
GROUP BY o.order_id, c.customer_name;

优化后的可能如下:

-- 先创建一个临时表存储筛选后的订单数据
CREATE TEMPORARY TABLE temp_orders AS
SELECT * FROM orders WHERE order_date BETWEEN '2024-01-01' AND '2024-08-06';

-- 基于临时表进行连接和聚合操作
SELECT o.order_id, c.customer_name, SUM(o.order_amount) AS total_amount
FROM temp_orders o
JOIN customers c ON o.customer_id = c.customer_id
GROUP BY o.order_id, c.customer_name;

通过这样的优化,可以提高查询的性能和效率。

3.3 数据库配置优化

Mysql数据库常见配置文件名称如下

  1. /etc/mysql/my.cnf
  2. /etc/my.cnf
  3. /etc/mysql/mysqld.cnf
  4. /etc/mysql/conf.d/ (这里可能包含多个配置文件)
  5. /usr/local/mysql/etc/my.cnf(如果 MySQL 是通过源码编译安装的话)

在配置文件中修改下面的信息,附内核配置文件优化修改脚本

调整缓冲池大小(InnoDB Buffer Pool)

innodb_buffer_pool_size = 总内存的 50% - 80%

较大的缓冲池可以减少磁盘 I/O,加快数据访问速度。

增加并发线程数(Thread Concurrency)

thread_concurrency = CPU 核心数 * 2

这有助于提高并发处理能力。

优化查询缓存(Query Cache)

query_cache_type = 0  # 除非您的应用有大量相同的查询,否则建议关闭

调整连接参数

max_connections = 根据预期的并发连接数设置

优化 InnoDB 日志文件

innodb_log_file_size = 256M  # 根据写入量适当调整
innodb_log_buffer_size = 16M  # 缓冲日志数据

调整排序缓冲区大小(Sort Buffer Size)

sort_buffer_size = 2M  # 根据需要适当增大

调整读缓冲区大小(Read Buffer Size)

read_buffer_size = 2M  # 适当调整

启用并行查询(Parallel Query)

innodb_parallel_read_threads = 4  # 根据硬件配置调整

Mysql配置参数优化脚本

下面脚本可以保存后执行,但是请确认你的配置文件路径,仅供参考

#!/bin/bash

# 备份原配置文件
# 这一步很重要,万一修改配置文件后出现问题,可以回滚到原始状态
cp /etc/my.cnf /etc/my.cnf.bak

# 打开配置文件进行编辑
vi /etc/my.cnf

# 添加或修改以下参数

# [mysqld] 部分表示以下的参数是针对 mysqld 服务的
echo "[mysqld]" >> /etc/my.cnf

# innodb_buffer_pool_size:InnoDB 缓冲池的大小,用于缓存表和索引数据。较大的值可以减少磁盘 I/O,提高性能。
# 这里设置为 512M,您可以根据服务器内存大小进行调整。
echo "innodb_buffer_pool_size = 512M" >> /etc/my.cnf

# thread_concurrency:设置并发线程数,根据服务器的 CPU 核心数进行适当调整,以提高并发处理能力。
echo "thread_concurrency = 8" >> /etc/my.cnf

# query_cache_type:查询缓存类型,设置为 0 表示关闭查询缓存。除非您的应用有大量重复的查询,否则关闭可能更好。
echo "query_cache_type = 0" >> /etc/my.cnf

# max_connections:设置最大并发连接数,根据预期的并发连接需求进行设置。
echo "max_connections = 200" >> /etc/my.cnf

# innodb_log_file_size:InnoDB 日志文件的大小,适当调整可以优化性能和恢复时间。
echo "innodb_log_file_size = 256M" >> /etc/my.cnf

# innodb_log_buffer_size:InnoDB 日志缓冲区的大小,缓冲日志数据以减少磁盘写入次数。
echo "innodb_log_buffer_size = 16M" >> /etc/my.cnf

# sort_buffer_size:排序缓冲区大小,用于排序操作,根据需要适当调整。
echo "sort_buffer_size = 2M" >> /etc/my.cnf

# read_buffer_size:读缓冲区大小,用于顺序读取数据,适当调整。
echo "read_buffer_size = 2M" >> /etc/my.cnf

# innodb_parallel_read_threads:InnoDB 并行读线程数,根据硬件配置调整,提高读取性能。
echo "innodb_parallel_read_threads = 4" >> /etc/my.cnf

4. 超长执行sql语句定位

下面我将介绍集中查询到底哪些sql语句在超时执行的语句,记录下来做针对性优化。

4.1 使用 SHOW PROCESSLIST 命令

SHOW PROCESSLIST;

这个命令会显示当前正在执行的所有连接和它们正在执行的 SQL 语句,以及执行的状态、时间等信息。您可以通过观察 Time 列来判断哪些语句执行时间较长。

image-20240807000702067

4.2.开启慢查询日志

首先,需要在 MySQL 的配置文件(通常是 my.cnfmy.ini)中进行相关设置:

slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 2  # 单位为秒,设置超过多长时间的查询被认为是慢查询

然后,重启 MySQL 服务使配置生效。之后,执行时间超过设定阈值的 SQL 语句会被记录到指定的慢查询日志文件中。

4.3.利用性能分析工具

例如 pt-query-digest 工具,它可以对 MySQL 的查询日志(包括慢查询日志)进行分析,帮助您找出执行效率低下的 SQL 语句。

例如,如果您的慢查询日志文件名为 mysql-slow.log,可以使用以下命令进行分析:

pt-query-digest mysql-slow.log

4.4 查询近期长时间执行sql

下图可以查询24h内执行时间超过AVG_TIMER_WAIT的语句和相关执行用户

-- 从 performance_schema.events_statements_summary_by_digest 表中选择数据
SELECT * 
FROM performance_schema.events_statements_summary_by_digest 
-- 筛选条件:摘要文本不包含'performance_schema'
WHERE DIGEST_TEXT NOT LIKE '%performance_schema%' 
  -- 平均等待时间大于1小时
  AND AVG_TIMER_WAIT > 3600000000000 
  -- 最后出现时间在过去 24 小时内
  AND LAST_SEEN >= DATE_SUB(NOW(), INTERVAL 24 HOUR) 
-- 按照平均等待时间降序排序
ORDER BY AVG_TIMER_WAIT DESC\G

5. 超长sql监控脚本

作为DBA,善于利用shell脚本和定时任务可以极大的减轻工作量,提高工作效率。

我们可以通过编写定时任务的方法每天执行时间较长的sql查询语句,获取其相关信息到txt文本中。

  1. 首先,创建一个包含上述查询语句的 SQL 脚本文件,例如 slow_query_check.sql ,内容如下:
SELECT * 
FROM performance_schema.events_statements_summary_by_digest 
WHERE DIGEST_TEXT NOT LIKE '%performance_schema%' 
  AND AVG_TIMER_WAIT >3600000000000 
  AND LAST_SEEN >= DATE_SUB(NOW(), INTERVAL 24 HOUR) 
ORDER BY AVG_TIMER_WAIT DESC\G

image-20240807002258469

然后,使用 crontab -e 命令编辑定时任务。

在打开的文件中添加以下内容:

0 8 * * * 登录数据的命令,需要包含密码 < /home/mysql/zhangfakai/slow_query_check.sql > /home/mysql/zhangfakai/$(date +\%Y\%m\%d_slow_query_result.txt)

每天早上 8 点就会自动执行查询,并将结果输出到指定的 txt 文本中。

我们每天上班后可以先查询txt查看有无异常。

6. 总结

本文详细探讨了MySQL数据库中出现超时SQL语句的原因、定位方法、以及相应的优化和预防措施。通过深入分析,我们了解到MySQL数据库超时执行SQL的问题主要源于数据量过大、复杂的查询逻辑、缺少合适的索引、服务器资源不足、网络延迟、数据库配置不合理以及并发操作过多等多方面因素。

针对这些问题,本文提出了多项优化策略。在SQL查询优化方面,强调了避免大表全表扫描、优化复杂查询逻辑、使用合适的索引、分解复杂查询、避免不必要的计算和函数、优化连接操作、减少数据量以及使用临时表等技巧。同时,也介绍了如何通过调整数据库配置参数(如缓冲池大小、并发线程数、查询缓存、连接参数等)来优化数据库性能。

在超时SQL语句的定位方面,本文介绍了使用SHOW PROCESSLIST命令、开启慢查询日志、利用性能分析工具(如pt-query-digest)以及查询近期长时间执行的SQL语句等多种方法。这些方法有助于快速定位问题SQL语句,从而进行针对性的优化。

最后,本文还提出了编写超长SQL监控脚本的建议,通过定时任务自动检测长时间执行的SQL语句,并生成报告,帮助DBA及时发现问题并进行处理。

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

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

相关文章

统信UOS激活系统故障

统信UOS激活系统故障 1. 离线环境下如何激活系统 ①点击右下角的授权管理 ②点击“激活” ③输入激活码,并点击确定 ④离线环境下此时会弹出二维码,使用微信去扫码,按照提示确定激活 ⑤微信确定以后,激活端会显示成功 2. 激活过程中提示服务器连接失败 激活时如果提示服…

Java多商户新零售超市外卖商品系统

解锁新零售奥秘&#xff0c;多商户外卖超市商品系统大揭秘&#xff01; &#x1f31f; 开篇&#xff1a;新零售时代的浪潮 在这个日新月异的数字化时代&#xff0c;新零售已悄然成为商业变革的新风口。想象一下&#xff0c;足不出户就能逛遍全城商家&#xff0c;心仪商品一键…

智算与大模型人才白皮书学习

目录 智算定义 智算的相关政策 公司的智算战略 服务提供者的定义及服务内容 智算人才需求 典型智算参与者的角色要求 业务流程全过程的分解 自己的定位 智算定义 智算通过智能化技术手段优化和提升技术系统的功能和性能&#xff0c;是为满足未来人工智能发展 和相关应用…

如何快速发现SIM卡托潜在问题?

手机SIM卡托通常是指放置SIM卡的卡槽或卡托。SIM卡托位于手机的侧面或顶部&#xff0c;用于插入SIM卡以连接到移动网络。通常&#xff0c;用户可以通过将SIM卡插入手机SIM卡托来激活手机服务、接收通话、发送短信和使用移动数据。SIM卡托一般设计成易于插拔&#xff0c;使用户能…

DataWhale AI夏令营-英特尔-阿里天池LLM Hackathon

英特尔-阿里天池LLM Hackathon 项目思路项目背景项目思路 Lora微调Qwen模型使用ipex_llm推理加速Gradio交互 项目名称&#xff1a;医疗问答助手 项目思路 项目背景 在当今医疗领域&#xff0c;智能问答系统正在逐步成为辅助医疗诊断的重要工具。随着自然语言处理技术的发展&…

基于STM32的智能家居灯光控制系统

目录 引言环境准备工作 硬件准备软件安装与配置系统设计 系统架构硬件连接代码实现 初始化代码灯光控制代码应用场景 智能家居灯光控制办公环境智能照明常见问题及解决方案 常见问题解决方案结论 1. 引言 随着智能家居技术的发展&#xff0c;灯光控制系统在提升家居生活品质…

尝鲜 HarmonyOS NEXT 开发环境搭建

申请好 HarmonyOS NEXT的开发套件白名单后&#xff0c;就可以下载最的开发套件了&#xff0c;最新的开发工具更新时间是2024-06-17&#xff0c;DevEcoStudio5.0-API12-x86-402。下载后是这样的&#xff1a; 我用的是 MAC PRO&#xff0c;所以下载的是 MAC 版&#xff0c;这里有…

VMware Linux 虚拟机设置了共享文件夹找不到如何解决?

如果在‌虚拟机中设置了‌共享文件夹但找不到&#xff0c;可能是因为没有正确执行挂载操作。挂载操作是将主机上的共享文件夹与虚拟机中的某个目录关联起来的步骤。 目前已经设置了共享文件夹&#xff0c;但是在Linux 上并没有找到 执行以下操作&#xff1a; mkdir /mnt/hgf…

云原生第一次作业

一、实验准备 1、准备一台rhel7的主机,并开启主机的图形 2、配置好可用IP 3、做kickstart自动安装脚本后面需要用到DHCP&#xff0c;关闭VMware DHCP功能 一、kickstart的安装和配置 安装 yum install system-config-kickstart 配置 安装httpd yum install httpd -y\n\n…

投资充电桩源码 共享充电桩投资理财源码 金融理财源码 最新理财投资源码php 投资理财网站源码

海外共享项目投资源码&#xff0c;投资充电桩源码 共享充电桩投资理财源码 金融理财源码 最新理财投资源码php 投资理财网站源码 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/89612921 更多资源下载&#xff1a;关注我。

软件测试学习笔记

测试学习 1. 测试流程2. Bug的提出什么是bugbug 的描述bug 级别 3. 测试用例的设计什么是测试用例测试用例应如何设计基于需求的设计方法等价类边界值场景法正交表法判定表法错误猜测法 4. 自动化测试回归测试自动化分类 5. 安装 webdriver-manager 和 selenium第一个web自动化…

SAP MM学习笔记 - 豆知识05 - Customer Exit 实例,MM01上定义Customer Exit 来Check评估Class

上一章讲了一些MM模块的豆知识。 - MM01中设定的安全在库和最小安全在库 - MM01/MMSC/Customize自动 扩张物料的保管场所 - MM01中定义生产订单的默认入库保管场所 - VA01受注票中设定禁止贩卖某个物料 SAP MM学习笔记 - 豆知识03 - 安全在库和最小安全在库&#xff0c;扩…

java使用opencv

一、windows安装opencv 下载地址&#xff1a;https://opencv.org/releases/ 下载后安装 本人安装目录 目录说明&#xff1a; build&#xff1a;基于windows构建 java&#xff1a;开发关注 x64、x86对应windows操作系统位数 sources&#xff1a;开源源码 二、java使用ope…

java之多线程篇

一、基本概念 1.什么是线程&#xff1f; 线程就是&#xff0c;操作系统能够进行运算调度的最小单位。它被包含在进程之中&#xff0c;是进程中的实际运作单位。简单理解就是&#xff1a;应用软件中互相独立&#xff0c;可以同时运行的功能 2.什么是多线程&#xff1f; 有了多线…

高清无水印视频素材哪里找?分享几个热门的高清无水印素材网站

一个好的短视频离不开精彩的素材&#xff0c;但高清视频素材哪里找&#xff1f;今天小编就跟大家分享五个可以下载高清无水印短视频素材的网站&#xff0c;如果你还不知道从哪里可以下载高清视频素材&#xff0c;赶紧进来看看吧&#xff01;&#xff5e; 1、稻虎网 首推的是稻…

leetcode数论(​3044. 出现频率最高的质数)-质数判断

前言 经过前期的基础训练以及部分实战练习&#xff0c;粗略掌握了各种题型的解题思路。现阶段开始专项练习。 描述 给你一个大小为 m x n 、下标从 0 开始的二维矩阵 mat 。在每个单元格&#xff0c;你可以按以下方式生成数字&#xff1a; 最多有 8 条路径可以选择&#xff1…

宝兰德JVM参数查看及优化

最近生产环境宝兰德服务总是莫名奇妙的宕掉&#xff0c;很是搞人心态&#xff08;幸好是集群服务器多&#xff0c;总有一台提供服务&#xff09;&#xff0c;初步排查是内存溢出导致&#xff0c;需要进行宝兰德JVM进行调整 调整宝兰德&#xff08;BES&#xff09;JVM参数通常涉…

Spring源码解析(29)之AOP动态代理对象创建过程分析

一、前言 在上一节中我们已经介绍了在createBean过程中去执行AspectJAutoProxyCreator的after方法&#xff0c;然后去获取当前bean适配的advisor&#xff0c;如果还不熟悉的可以去看下之前的博客&#xff0c;接下来我们分析Spring AOP是如何创建代理对象的&#xff0c;在此之前…

38. 115.不同的子序列,583. 两个字符串的删除操作,72. 编辑距离,编辑距离总结篇

确定dp数组以及下标的含义。dp[i][j]&#xff1a;以i-1为结尾的s子序列中出现以j-1为结尾的t的个数为dp[i][j]。确定递推公式。这一类问题&#xff0c;基本是要分析两种情况&#xff1a;s[i - 1] 与 t[j - 1]相等&#xff1b;s[i - 1] 与 t[j - 1] 不相等。当s[i - 1] 与 t[j -…

【屏驱MCU】RT-Thread 文件系统接口解析

本文主要介绍【屏驱MCU】基于RT-Thread 系统的文件系统原理介绍与代码接口梳理 目录 0. 个人简介 && 授权须知1. 文件系统架构1.1 虚拟文件系统目录架构 2. menuconfig 分析3. 代码接口分析3.1 DFS框架挂载目录3.2 【FAL抽象层】分区表和设备表3.3 如何将【文件路径】挂…