MySQL8慢查询

本文详细介绍了如何在MySQL中开启慢查询日志,设置慢查询超时时间,并通过示例展示了如何触发慢查询。此外,还提到了使用mysqldumpslow工具进行慢查询日志分析,并解释了其常用参数。最后,讨论了MySQL重启后配置失效的问题及解决办法,即通过修改my.cnf配置文件实现慢查询日志的永久开启。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

开启慢查询日志

默认情况,MySQL的慢查询日志是关闭的

mysql> show variables like 'slow_query%';
+---------------------+-----------------------------------------+
| Variable_name       | Value                                   |
+---------------------+-----------------------------------------+
| slow_query_log      | OFF                                     |
| slow_query_log_file | /var/lib/mysql/VM-20-11-centos-slow.log |
+---------------------+-----------------------------------------+
2 rows in set (0.00 sec)

开启MySQL的慢查询日志功能

mysql> set global slow_query_log='ON';
Query OK, 0 rows affected (0.09 sec)

mysql> show variables like 'slow_query%';
+---------------------+-----------------------------------------+
| Variable_name       | Value                                   |
+---------------------+-----------------------------------------+
| slow_query_log      | ON                                      |
| slow_query_log_file | /var/lib/mysql/VM-20-11-centos-slow.log |
+---------------------+-----------------------------------------+
2 rows in set (0.01 sec)

设置慢查询超时时间

mysql> show variables like 'long_query_time%';
+-----------------+-----------+
| Variable_name   | Value     |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.00 sec)

long_query_time 默认时间为 10s。修改慢查询超时时间

# 执行完后需要将当前窗口关闭重新连接才会生效 如果只想让本窗口有效果的话,不用加global关键字
set global long_query_time=2;
delimiter ;;
create procedure idata2()
begin
  declare i int;
  set i=1;
  while(i<=100000)do
    insert into t values(i, i, i,i);
    set i=i+1;
  end while;
end;;
delimiter ;
call idata2();

测试慢查询

mysql> select sleep(3);
+----------+
| sleep(3) |
+----------+
|        0 |
+----------+
1 row in set (3.00 sec)

查看慢查询

cat /var/lib/mysql/VM-20-11-centos-slow.log
# Time: 2022-04-23T04:32:54.796190Z
# User@Host: root[root] @ localhost []  Id: 10864
# Query_time: 3.000236  Lock_time: 0.000000 Rows_sent: 1  Rows_examined: 1
SET timestamp=1650688371;
select sleep(3);

慢日志分析工具

mysqldumpslow

mysqldumpslow经常使用的参数:

-s 按照那种方式排序
    c:访问计数
    l:锁定时间
    r:返回记录
    a:查询时间
    al:平均锁定时间
    ar:平均访问记录数
    at:平均查询时间
-t 是top n的意思,返回多少条数据。
-g 可以跟上正则匹配模式,大小写不敏感。

例如:

mysqldumpslow -t 3 -s t -g 'left join' /var/lib/mysql/VM-20-11-centos-slow.log

mysqldumpslow -t 3 -s t  /var/lib/mysql/VM-20-11-centos-slow.log

执行结果分析,例如

Count: 4  Time=3.75s (15s)  Lock=0.00s (0s)  Rows=1.0 (4), root[root]@localhost
  select sleep(N)

Count 表示该类型的语句执行次数

**Time ** 表示该类型的语句执行的平均时间(总计时间)

Lock 锁时间0s

Rows 单次返回的结果数是1条记录,4次总共返回4条记录

MySQL重启失效

[root@VM-20-11-centos ~]# systemctl restart mysqld
[root@VM-20-11-centos ~]# mysql -uroot -proot123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.28 MySQL Community Server - GPL

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show variables like 'slow_query%';
+---------------------+-----------------------------------------+
| Variable_name       | Value                                   |
+---------------------+-----------------------------------------+
| slow_query_log      | OFF                                     |
| slow_query_log_file | /var/lib/mysql/VM-20-11-centos-slow.log |
+---------------------+-----------------------------------------+
2 rows in set (0.01 sec)

通过变量方式启动MySQL相关功能,重启后恢复到默认配置。如果需要永久有效,则通过修改 MySQL 的配置文件 my.cnf。

# 打开配置文件
vim /etc/my.cnf

在[mysqld]后添加

slow-query-log = on
long_query_time = 2

然后重启服务

[root@VM-20-11-centos ~]# systemctl restart mysqld
[root@VM-20-11-centos ~]# mysql -uroot -proot123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.28 MySQL Community Server - GPL

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show variables like 'slow_query%';
+---------------------+-----------------------------------------+
| Variable_name       | Value                                   |
+---------------------+-----------------------------------------+
| slow_query_log      | ON                                      |
| slow_query_log_file | /var/lib/mysql/VM-20-11-centos-slow.log |
+---------------------+-----------------------------------------+
2 rows in set (0.00 sec)
<think>我们被要求回答关于MySQL慢查询优化的问题。根据提供的引用内容,我们可以总结出以下优化方法: 1. 定位慢查询:通过慢查询日志找出执行缓慢的SQL语句。 2. 分析查询:使用EXPLAIN分析SQL语句的执行计划。 3. 优化索引:添加合适的索引,避免全表扫描。 4. 优化查询语句:避免使用SELECT *,只选择需要的列;优化JOIN操作;避免使用子查询,改用JOIN;避免在WHERE子句中对字段进行函数操作等。 5. 分页优化:对于大偏移量的分页查询,使用更高效的方法(如记录上次查询的最大ID)。 6. 数据类型优化:使用更小的数据类型,如用TIMESTAMP代替DATETIME,用整数类型代替字符串类型存储IP等。 7. 避免慢查询:定期分析慢查询日志,及时优化。 我们将按照这些方面来组织回答,并参考引用内容进行详细说明。</think>### MySQL慢查询优化方法详解 MySQL慢查询优化需结合**索引设计**、**SQL改写**、**配置调整**等多维度进行。以下是系统化的解决方案: --- ### **一、定位慢查询根源** 1. **启用慢查询日志** - 修改配置文件 `my.cnf`: ```ini slow_query_log = 1 slow_query_log_file = /var/log/mysql/slow.log long_query_time = 2 # 定义慢查询阈值(秒) log_queries_not_using_indexes = 1 # 记录未使用索引的查询 ``` - 重启MySQL生效,通过日志分析高频慢SQL[^1][^4]。 --- ### **二、索引优化(核心手段)** 1. **添加缺失索引** - 对 `WHERE`、`JOIN`、`ORDER BY` 字段创建索引: ```sql ALTER TABLE orders ADD INDEX idx_user_id (user_id); -- 为user_id添加索引[^2][^3] ``` - 联合索引需遵循**最左前缀原则**: ```sql ALTER TABLE users ADD INDEX idx_name_age (name, age); -- 索引顺序需匹配查询条件 ``` 2. **避免索引失效场景** - 禁止对索引列进行函数操作: ```sql -- ❌ 错误示例(索引失效) SELECT * FROM users WHERE YEAR(create_time) = 2023; -- ✅ 优化为范围查询 SELECT * FROM users WHERE create_time BETWEEN '2023-01-01' AND '2023-12-31'; ``` - 避免 `LIKE` 以通配符开头: ```sql -- ❌ 索引失效 SELECT * FROM products WHERE name LIKE '%apple%'; -- ✅ 使用全文索引或倒排索引替代 ``` --- ### **三、SQL语句优化** 1. **改写低效语法** - **用 `JOIN` 替代子查询**: ```sql -- ❌ 低效子查询 SELECT * FROM users WHERE id IN (SELECT user_id FROM orders WHERE amount > 100); -- ✅ JOIN优化 SELECT u.* FROM users u JOIN orders o ON u.id = o.user_id WHERE o.amount > 100;[^3] ``` - **避免 `SELECT *`**: ```sql SELECT id, name FROM users; -- 仅查询必要字段[^2] ``` 2. **分页优化** - 大偏移量分页改用 **游标或延迟关联**: ```sql -- ❌ 低效分页(扫描前10000行) SELECT * FROM orders LIMIT 10000, 20; -- ✅ 优化(通过ID定位) SELECT * FROM orders WHERE id > 10000 LIMIT 20; ``` --- ### **四、表结构与数据类型优化** 1. **选择高效数据类型** - 用 `TIMESTAMP`(4字节)替代 `DATETIME`(8字节)[^2] - 金额字段转换为整数存储: ```sql DECIMAL(10,2) → BIGINT -- 存储时乘以100(如1.23元存为123)[^2] ``` 2. **规范表设计** - 避免大字段(如 `TEXT`)影响行存储密度 - 拆分高频更新与低频查询字段到不同表 --- ### **五、配置与系统级优化** 1. **调整关键参数** - 增加 `innodb_buffer_pool_size`(通常设为物理内存70%~80%) - 控制未使用索引的日志量: ```ini log_throttle_queries_not_using_indexes = 100 -- 每分钟最多记录100条[^4] ``` 2. **监控锁竞争** - 通过 `SHOW ENGINE INNODB STATUS` 检查锁等待 - 优化事务隔离级别(如 `READ COMMITTED`)[^4] --- ### **六、持续监控机制** 1. 定期分析慢日志工具(如 `pt-query-digest`) 2. 使用性能诊断工具: - `EXPLAIN` 分析执行计划 - `SHOW PROFILE` 查看资源消耗 > **优化本质**:通过减少磁盘I/O、降低CPU计算量、最小化网络传输提升效率[^1][^5]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值