MySQL 慢查询日志及优化

一、简介

MySQL 慢查询日志是定位数据库性能瓶颈的核心工具,主要用于追踪执行效率低下的 SQL 语句。通过慢查询日志,可以查找出哪些查询语句的执行效率低,以便进行优化。慢查询日志默认不开启。

二、作用

慢查询日志用于记录执行时间超过设定阈值的 SQL 语句,帮助开发者或 DBA 发现 "拖慢" 数据库的低效查询。其核心价值在于:

  • 精准定位耗时较长的 SQL(如全表扫描、复杂关联查询等);

  • 分析查询的执行频率、锁等待时间、扫描行数等关键指标;

  • 为 SQL 优化、索引调整、表结构设计提供数据依据。

三、关键配置参数及开启方式

1、关键配置参数

参数名 含义 默认值
slow_query_log 是否开启慢查询日志(1开启,0关闭) 0
slow_query_log_file 慢查询日志文件路径 取决于系统,如 /var/log/mysql/slow.log
long_query_time 慢查询阈值(单位:秒),执行时间 ≥ 该值 的 SQL 会被记录 10
log_queries_not_using_indexes 是否记录未使用索引或是全表扫描的查询(即使执行时间未超过 long_query_time) 0
log_slow_rate_limit 查询多少次才记录,MariaDB 特有配置项 1

2、临时开启

通过 SET GLOBAL 命令修改参数,当前会话生效,重启失效

sql 复制代码
-- 开启慢查询日志
SET GLOBAL slow_query_log = 1;

-- 设置日志文件路径(需提前创建目录并授权)
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';

-- 设置慢查询阈值(如 10 秒,支持小数,如 0.5 表示 500 毫秒)
SET GLOBAL long_query_time = 10;

-- 记录未使用索引的查询(可选,用于发现索引缺失问题)
SET GLOBAL log_queries_not_using_indexes = 1;

3、永久开启

修改 MySQL 配置文件(通常为 /etc/my.cnf 或 /etc/mysql/my.cnf),在 mysqld 段添加相关配置参数

bash 复制代码
[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 10  # 阈值 10 秒
log_queries_not_using_indexes = 1  # 记录未用索引的查询

修改后重启 MySQL 服务生效

四、慢查询日志分析

1、模拟慢查询

临时开启慢查询日志,设置阈值为1秒,设置日志输出为 /var/log/mysql/slow.log

执行慢查询动作,生成日志

查看日志

2、日志关键字段解析

  • Query_time:SQL 执行时间(秒),此处为 3 秒,超过阈值 1 秒;

  • Lock_time:锁等待时间(秒),此处 0 秒,若过大可能存在锁竞争;

  • Rows_sent:返回给客户端的行数(1行);

  • Rows_examined:扫描的行数(1 行)

3、定位问题的步骤

筛选关键慢查询:优先关注 Query_time 大、执行频率高的 SQL(可通过 mysqldumpslow 工具统计,如 mysqldumpslow -s t -t 10 /var/log/mysql/slow.log 按时间取前 10 条)。

分析执行计划:对慢查询使用 EXPLAIN 工具查看执行计划,重点关注:

  • type:访问类型(ALL 表示全表扫描,性能最差;ref/range 表示使用索引,较优);

  • key:实际使用的索引(NULL 表示未使用索引);

  • rows:预估扫描行数(值越大,效率越低);

  • Extra:额外信息(如 Using filesort 表示需要排序,Using temporary 表示使用临时表,均需优化)。

定位根因:结合执行计划判断问题类型,例如:

  • 若 type=ALL 且 key=NULL:未创建合适的索引;

  • 若 rows 远大于 Rows_sent:索引过滤性差(如区分度低的字段);

  • 若 Lock_time 大:存在行锁 / 表锁竞争(如高并发更新同一行)。

五、常见的慢查询优化

针对慢查询日志定位的问题,常见优化手段可分为索引优化、SQL 语句优化、表结构优化和配置优化四类:

1、索引优化

  • 添加合适的索引:为查询条件(WHERE)、关联字段(JOIN ON)、排序字段(ORDER BY)创建索引;

  • 避免索引失效:不使用函数或表达式处理索引字段(如 WHERE SUBSTR(phone,1,3)='138' 会导致 phone 索引失效);避免 !=、NOT IN、IS NOT NULL 等操作(索引难以高效过滤);

  • 避免隐式类型转换:字符串查询加引号(如 WHERE name='123' 而非 WHERE name=123);

  • 删除冗余索引:同一字段的重复索引会增加写入开销。

2、SQL 语句优化

  • 避免 SELECT *:只查询需要的字段,减少 IO 开销;

  • 拆分复杂查询:将一次性执行的大查询拆分为多个小查询(如分页查询用 LIMIT 限制行数,避免全表扫描后过滤);

  • 优化关联查询:JOIN 表数量控制在 3 张以内,关联字段必须建索引,避免 LEFT JOIN 时右表条件导致全表扫描;避免笛卡尔积;

  • 替换子查询:子查询可能产生临时表,改用 JOIN 优化(如 SELECT * FROM t1 WHERE id IN (SELECT id FROM t2) 改为 SELECT t1.* FROM t1 JOIN t2 ON t1.id = t2.id)。

3、表结构优化

  • 分表分库:大表(千万级以上)按时间(如订单表按月份分表)或哈希(如用户表按 user_id 分表)拆分,减少单表数据量。

  • 选择合适的数据类型:如用 INT 代替 VARCHAR 存储数字,DATE/DATETIME 代替字符串存储日期,减少存储空间和比较开销。

  • 避免大字段:TEXT/BLOB 等大字段单独存表,避免查询时不必要的 IO 消耗。

4、配置优化

  • 调整缓存:增大 innodb_buffer_pool_size(InnoDB 缓存池,建议占物理内存的 50%-70%),减少磁盘 IO;

  • 优化连接:调整 max_connections 避免连接数不足,wait_timeout 释放闲置连接;

  • 日志优化:非必要时关闭 log_queries_not_using_indexes(避免日志过大),定期轮转慢查询日志。

相关推荐
筵陌3 小时前
MYSQL表的操作
数据库·mysql·1024程序员节
hazy1k3 小时前
51单片机基础-红外遥控(NEC协议)
stm32·单片机·嵌入式硬件·51单片机·1024程序员节
不见长安在4 小时前
Jvm资料整理
jvm·1024程序员节
如果丶可以坑4 小时前
maven无法获取依赖问题
java·maven·1024程序员节
羊村里的大灰狼4 小时前
Windows下载安装配置rabbitmq
1024程序员节
B站计算机毕业设计之家4 小时前
Python手势识别检测系统 基于MediaPipe的改进SSD算法 opencv+mediapipe 深度学习 大数据 (建议收藏)✅
python·深度学习·opencv·计算机视觉·1024程序员节
兜兜风d'4 小时前
RabbitMQ 持久性详解
spring boot·分布式·rabbitmq·1024程序员节
MeowKnight9585 小时前
【Linux】常见的系统调用 函数和功能简单总结
linux·1024程序员节
华仔啊5 小时前
这20条SQL优化方案,让你的数据库查询速度提升10倍
数据库·后端·mysql