当前位置: 首页 > news >正文

Mysql定位慢查询

        当页面加载过慢、接口压测响应时间过长(超过1s)时,很可能是因为SQL的执行时间缓慢导致。

        MySQL 提供了慢查询日志功能,可以记录执行时间超过指定阈值的 SQL 语句。

1. 开启慢查询日志

配置方法

  • 临时开启(重启后失效):

    -- 查看当前配置
    SHOW VARIABLES LIKE 'slow_query_log';
    SHOW VARIABLES LIKE 'long_query_time';-- 开启慢查询日志
    SET GLOBAL slow_query_log = ON;
    -- 设置慢查询阈值(单位:秒,这里示例为 1 秒)
    SET GLOBAL long_query_time = 1;
    -- 设置慢查询日志存储路径(可选)
    SET GLOBAL slow_query_log_file = '/var/log/mysql/mysql-slow.log';
    

  • 永久开启(修改配置文件 my.cnf 或 my.ini):

    [mysqld]
    slow_query_log = ON
    slow_query_log_file = /var/log/mysql/mysql-slow.log
    long_query_time = 1  # 超过 1 秒的查询会被记录
    log_queries_not_using_indexes = ON  # 记录未使用索引的查询(可选)
    

     

    修改后需重启 MySQL 服务生效。

2. 分析慢查询日志

慢查询日志记录了符合条件的 SQL 语句及其执行信息,可通过以下工具分析:

直接查看日志文件
日志内容包含执行时间、锁等待时间、扫描行数等关键信息,例如:

日志文件不方便我们统计查看,通常情况下我们会使用工具来辅助。

使用 mysqldumpslow 工具
MySQL 自带的日志分析工具,可统计慢查询的频率、耗时等:

# 查看最耗时的 10 条慢查询
mysqldumpslow -s t -t 10 /var/log/mysql/mysql-slow.log# 查看访问次数最多的 10 条慢查询
mysqldumpslow -s c -t 10 /var/log/mysql/mysql-slow.log

参数说明:-s 指定排序方式(t: 按时间,c: 按次数),-t 指定显示条数。

3.Docker安装Mysql并开启慢日志配置

环境:

centos7、mysql8.0.19

拉取 MySQL 镜像:

docker pull mysql:8.0.19

创建挂载文件目录:

# 创建本地目录(用于挂载配置、数据、日志)
mkdir -p /mysql8/{conf,data,logs}

创建配置文件和慢日志文件:

# 创建配置文件
vi /home/hl/mysql8/conf/my.cnf
# 创建慢日志
vi /home/hl/mysql8/logs/mysql-slow.log

将以下内容复制到my.cnf中:

[mysqld]
# 开启慢查询日志
slow_query_log = 1
# 慢查询日志路径(需对应容器内路径,已挂载到本地 /docker/mysql/logs)
slow_query_log_file = /var/log/mysql/mysql-slow.log
# 慢查询阈值(单位:秒,超过此值的 SQL 会被记录)
long_query_time = 1

完成上述操作后,我的目录文件如下:

创建容器:

docker run -d \
  --name mysql \
  -p 3306:3306 \
  -e MYSQL_ROOT_PASSWORD=1234 \
  -v /home/hl/mysql8/conf:/etc/mysql/conf.d \
  -v /home/hl/mysql8/data:/var/lib/mysql \
  -v /home/hl/mysql8/logs:/var/log/mysql \
  mysql:8.0.19

查看容器是否启动:

进入容器并查看慢日志是否启用:
输入以下命令进入容器,并登录进mysql:

# 进入容器
docker exec -it mysql8 bash# 登录 MySQL
mysql -u root -p# 查看慢查询配置
SHOW VARIABLES LIKE 'slow_query_log';  # 应显示 ON
SHOW VARIABLES LIKE 'long_query_time'; # 应显示 1.000000
SHOW VARIABLES LIKE 'slow_query_log_file'; # 应显示日志路径

slow_query_log为ON则开启成功:

有错误参考:
关于Mysql开启慢查询日志报错:13 - Permission denied的解决方案-CSDN博客

mysqldumpslow 测试:

为了方便测试,将my.cnf的long_query_time设置为0.001,差不多每支持一条sql都会被慢日志记录下来,然后随便执行几条sql,使用mysqldumpslow 查看:

可以清晰的查看到每条sql的执行时间、锁等待时间、扫描行数等关键信息

4.分析慢SQL

        通过慢查询日志我们可以定位到慢SQL,定位到SQL后,我们就可以通过EXPLAIN 或者 DESC命令获取 MySQL 如何执行 SELECT 语句的信息:

语法:

-直接在select语句之前加上关键字 explain/desc
EXPLAIN SELECT 字段列表 FROM 表名 WHERE 条件

        通过 EXPLAIN 或 EXPLAIN ANALYZE 分析 MySQL 如何执行这条 SQL,重点关注 索引使用、扫描行数、连接方式 等。

4.1 关键字段解读

执行的EXPLAIN 展示SQL信息中,我们主要关注以下这些关键字即可:

字段含义需关注的问题
type访问类型(索引使用效率)若为 ALL(全表扫描)、index(全索引扫描),说明未有效使用索引。
key实际使用的索引若为 NULL,说明未使用任何索引。
rows预估扫描行数数值越大,效率越低(尤其远大于实际返回行数 rows_sent 时)。
Extra额外信息出现 Using filesort(文件排序)、Using temporary(临时表)、Using where(全表扫描后过滤)均为性能隐患。
possible_keys可能使用的索引若 possible_keys 不为空但 key 为空,说明索引失效(需排查原因)。

type:

这条sql的连接的类型,性能由好到差为NULL、system、const、eq_ref、ref、range、 index、all

  • system:查询系统中的表
  • const:根据主键查询
  • eq_ref:主键索引查询或唯一索引查询
  • ref:索引查询
  • range:范围查询
  • index:索引树扫描
  • all:全盘扫描

Extra:

Extra 值核心含义适用场景性能影响典型示例
Using where存储引擎读取数据后,在服务器层用WHERE条件过滤数据(需访问表数据行)。无可用索引(全表扫描),或索引无法覆盖过滤条件,需回表后再过滤。效率较低(可能全表扫描或需回表)无索引时执行SELECT * FROM user WHERE name = 'xxx'
Using index仅通过索引即可获取所有所需数据,无需回表(覆盖索引)。查询的所有列都包含在索引中,且过滤条件基于索引列。效率高(避免访问表数据,仅扫描索引)索引包含nameage时,执行SELECT name, age FROM user WHERE name = 'xxx'
Using index condition存储引擎层利用索引先过滤部分条件(索引下推),减少回表数据量,剩余条件在服务器层判断。使用二级索引,过滤条件部分可通过索引字段判断(如前缀匹配),部分需回表后判断。效率中等(减少回表数据,优于Using where索引为(first_name, last_name)时,执行SELECT * FROM user WHERE first_name LIKE 'J%' AND last_name = 'Doe'

示例:

user_id是user表的主键,执行以下SQL语句:

主要信息如下:

4.2 分析慢SQL

通过explain展示的信息,我们可以分析该条SQL:

  • 通过key和key_len检查是否命中了索引(索引本身存在是否有失效的情况)
  • 通过type字段查看sql是否有进一步的优化空间,是否存在全索引扫描或全盘扫描
  • 通过extra建议判断,是否出现了回表的情况,如果出现了,可以尝试添加索引或修改返回字段来修复

5.相关面试问题

5.1 mysql中,如何定位慢查询?

        我们可以通过MySQL中提供的慢查询日志功能进行定位。

        首先,需要在cnf配置文件中自定义慢查询阈值,默认10s,我通常设置为2s。

        然后,可通过查看慢查询日志或使用mysqldumpslow工具,定位到记录的慢查询SQL。

5.2 一个SQL语句执行很慢, 如何分析?

        我们通常使用EXPLAIN或DESC命令可查看到执行SQL的具体信息:

        通过key和key_len检查是否命中了索引,若使用了索引但是没有名称,查看索引是否失效。

        通过type查看是否存在全索引扫描(index)或全盘扫描(all),若存在则可进一步优化。

        通过Extra建议判断是否存在回表情况,若存在则可通过添加索引或者修改返回字段优化。

http://www.dtcms.com/a/286427.html

相关文章:

  • 内存泄漏系列专题分析之二十九:高通相机CamX--Android通用GPU内存分配和释放原理
  • 主流编程语言全景图:从Python到Rust的深度解析
  • 优先算法——专题九:链表
  • vc配置使用预编译
  • Android性能优化
  • 搜广推校招面经九十五
  • 【PTA数据结构 | C语言版】根据后序和中序遍历输出前序遍历
  • 更适合后端宝宝的前端三件套之CSS
  • 域名备案的注册地址怎么更改
  • 基于pandas,按日期时间排序,计算每个连续段的开始时间、结束时间,以及时长
  • Selenium自动化浏览器操作指南
  • Deep Multi-scale Convolutional Neural Network for Dynamic Scene Deblurring 论文阅读
  • DTW算法解决时序问题的解析实践
  • 【C++】std::exchange 原子性 返回值优化RVO
  • js基本数据类型之字符串类型
  • Python 数据分析与可视化:从基础到进阶的技术实现与优化策略
  • svn如何设置忽略文件夹或者文件的提交
  • PyQt5信号与槽(信号与槽的高级玩法)
  • 四足机器人远程视频与互动控制的全链路方案
  • 【C++】——类和对象(中)——默认成员函数
  • 【世纪龙科技】汽车故障诊断与排除仿真教学软件让课堂更高效安全
  • 【RK3576】【Android14】开发板概述
  • iOS WebView 调试实战 全流程排查接口异常 请求丢失与跨域问题
  • github jekyll+chirpy主题搭建博客
  • 【.net core】支持通过属性名称索引的泛型包装类
  • Spring AI开发智能客服(Tool calling)
  • Linux 定时任务全解析:atd 与 crond 的区别及实战案例(含日志备份 + 时间写入)
  • SpringBoot项目创建,三层架构,分成结构,IOC,DI相关,@Resource与@Autowired的区别
  • 融合优势:SIP 广播对讲联动华为会议 全场景沟通响应提速​
  • 【PHP】Swoole:CentOS安装MySQL+Swoole