Mysql定位慢查询

发布于:2025-07-20 ⋅ 阅读:(14) ⋅ 点赞:(0)

        当页面加载过慢、接口压测响应时间过长(超过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建议判断是否存在回表情况,若存在则可通过添加索引或者修改返回字段优化。


网站公告

今日签到

点亮在社区的每一天
去签到