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

MySQL慢SQL优化全攻略:从诊断到调优

目录

慢SQL日志分析与诊断

开启慢查询日志

慢查询日志分析工具

慢SQL优化策略

1. 避免SELECT * 查询

2. 创建高效索引

索引选择原则

索引使用注意事项

3. 使用EXPLAIN分析执行计划

4. 优化排序操作

5. 解决深分页问题

6. 避免全表扫描

7. 优化JOIN操作

8. 合理使用子查询

高级优化技巧

1. 使用覆盖索引

2. 索引条件下推(ICP)

3. 使用批处理减少交互

4. 合理使用临时表

名词解释

总结


慢SQL日志分析与诊断

开启慢查询日志

-- 开启慢查询日志功能
SET GLOBAL slow_query_log = 'ON';-- 设置慢SQL时间阈值(单位:秒),超过此时间的查询会被记录
SET GLOBAL long_query_time = 5;-- 查看慢查询日志文件位置
SHOW GLOBAL VARIABLES LIKE 'slow_query_log_file';-- 使用mysqldumpslow工具分析慢查询日志
-- 常用参数:-s排序方式(t按时间,c按次数),-t显示前N条
-- 示例:mysqldumpslow -s t -t 10 /var/logs/mysql/slow.log

慢查询日志分析工具

除了mysqldumpslow,还可以使用:

  1. ​pt-query-digest​​(Percona Toolkit的一部分):更强大的日志分析工具

    pt-query-digest /var/logs/mysql/slow.log
  2. ​MySQL Workbench​​:图形化界面分析工具

慢SQL优化策略

1. 避免SELECT * 查询

-- 不推荐
SELECT * FROM users WHERE id = 1;-- 推荐:只查询需要的列
SELECT id, username, email FROM users WHERE id = 1;

​原因​​:

  • 增加网络I/O负担
  • 当表中有大字段(如TEXT/BLOB)时性能影响显著
  • 可能使覆盖索引失效(后面会解释)

2. 创建高效索引

索引选择原则
  • ​高区分度​​:选择区分度高的列建索引(如用户ID比性别更适合)
  • ​常用查询条件​​:为WHERE、JOIN、ORDER BY、GROUP BY中的列建索引
  • ​短字段优先​​:整型字段比字符串字段更适合做索引
-- 创建单列索引
CREATE INDEX idx_username ON users(username);-- 创建复合索引
CREATE INDEX idx_status_created ON orders(status, created_at);
索引使用注意事项
  • ​最左匹配原则​​:复合索引必须从左到右使用

    -- 对于INDEX(a, b, c)
    WHERE a = 1 AND b = 2 -- 使用索引
    WHERE b = 2 AND c = 3 -- 不使用索引(缺少a)
    WHERE a = 1 AND c = 3 -- 部分使用索引(只用a)
  • ​避免索引失效​​:

    • 不要在索引列上使用函数:WHERE YEAR(create_time) = 2023
    • 避免隐式类型转换:WHERE user_id = '123'(user_id是整型)
    • 避免使用!=NOT INIS NULL等操作符

3. 使用EXPLAIN分析执行计划

EXPLAIN SELECT * FROM users WHERE username = 'john';

​关键指标解读​​:

  • ​type​​:访问类型(从好到差:system > const > eq_ref > ref > range > index > ALL)
  • ​possible_keys​​:可能使用的索引
  • ​key​​:实际使用的索引
  • ​rows​​:预估需要检查的行数
  • ​Extra​​:额外信息(如Using filesort、Using temporary表示性能问题)

4. 优化排序操作

-- 不推荐:大数据集文件排序
SELECT * FROM products ORDER BY price DESC LIMIT 100;-- 推荐:为排序字段添加索引
ALTER TABLE products ADD INDEX idx_price (price);
SELECT * FROM products ORDER BY price DESC LIMIT 100;

​原理​​:B+树索引本身是有序的,利用索引可以避免内存排序(Using filesort)

5. 解决深分页问题

​问题​​:LIMIT 10000, 20会先读取10020条记录,然后丢弃前10000条

​优化方案​​:

  1. ​使用覆盖索引+延迟关联​

    SELECT * FROM products JOIN (SELECT id FROM products WHERE category_id = 5 ORDER BY created_at DESC LIMIT 10000, 20
    ) AS tmp USING(id);
  2. ​记录上次查询位置​​(适用于有序数据)

    -- 第一页
    SELECT * FROM products ORDER BY id DESC LIMIT 20;-- 后续页(假设上一页最后一条记录的id是12345)
    SELECT * FROM products WHERE id < 12345 ORDER BY id DESC LIMIT 20;

6. 避免全表扫描

  • 为查询条件添加适当的索引
  • 避免在WHERE子句中对字段进行运算或使用函数
  • 使用合适的查询条件,避免过于宽泛的条件

7. 优化JOIN操作

  • 确保JOIN字段有索引
  • 小表驱动大表(MySQL优化器通常会自动处理)
  • 避免多表JOIN(超过3个表考虑反范式化设计)

8. 合理使用子查询

-- 不推荐:相关子查询
SELECT * FROM users WHERE id IN (SELECT user_id FROM orders WHERE amount > 1000
);-- 推荐:改用JOIN
SELECT DISTINCT u.* FROM users u
JOIN orders o ON u.id = o.user_id
WHERE o.amount > 1000;

高级优化技巧

1. 使用覆盖索引

​覆盖索引​​:查询的所有字段都包含在索引中,无需回表

-- 假设有INDEX(username, email)
SELECT username, email FROM users WHERE username = 'john';

​优势​​:减少I/O操作,提高查询速度

2. 索引条件下推(ICP)

MySQL 5.6+特性,将WHERE条件推到存储引擎层过滤

-- 假设有INDEX(a, b)
SELECT * FROM table WHERE a = 1 AND b LIKE '%test%';

3. 使用批处理减少交互

-- 不推荐
INSERT INTO users(name) VALUES ('a');
INSERT INTO users(name) VALUES ('b');-- 推荐
INSERT INTO users(name) VALUES ('a'), ('b');

4. 合理使用临时表

对于复杂查询,可以考虑使用临时表分步处理

CREATE TEMPORARY TABLE temp_orders
SELECT user_id, SUM(amount) AS total 
FROM orders 
GROUP BY user_id
HAVING total > 1000;SELECT u.* FROM users u
JOIN temp_orders t ON u.id = t.user_id;

名词解释

  1. ​B+树​​:MySQL索引的数据结构,特点是:

    • 所有数据都存储在叶子节点
    • 叶子节点通过指针连接,适合范围查询
    • 树的高度低,查询效率稳定
  2. ​回表​​:当使用非主键索引查询时,先通过索引找到主键,再通过主键索引查找完整数据的过程

  3. ​覆盖索引​​:查询的列都包含在索引中,无需回表

  4. ​最左匹配原则​​:复合索引必须从左到右使用,不能跳过前面的列

  5. ​深分页​​:当LIMIT offset很大时(如LIMIT 100000, 10),MySQL需要先读取offset+limit条记录,性能差

  6. ​Using filesort​​:表示MySQL需要进行额外的排序操作,通常是因为没有使用索引排序

  7. ​Using temporary​​:表示MySQL需要创建临时表来处理查询,常见于GROUP BY、ORDER BY等操作

总结

慢SQL优化是一个系统工程,需要:

  1. 通过慢查询日志定位问题SQL
  2. 使用EXPLAIN分析执行计划
  3. 针对性应用优化策略
  4. 持续监控优化效果

记住:索引不是越多越好,每个索引都会增加写操作的成本。好的数据库设计加上合理的索引策略,才能获得最佳性能。

相关文章:

  • C++ 学习笔记精要(二)
  • Android Kotlin 用法对比Java使用小结
  • Dilworth 定理 学习笔记
  • 智能危险品搬运机器人市场报告:行业趋势与未来展望
  • qt常用控件--01
  • 对于网站业务安全SCDN都能够从哪些方面进行保护?
  • Kafka协议开发总踩坑?3步拆解二进制协议核心
  • IP 风险画像网络违规行为识别
  • 语音相关-浏览器的自动播放策略研究和websocket研究
  • Kafka线上集群部署方案:从环境选型到资源规划思考
  • C#学习日记
  • 基于存储过程的MySQL自动化DDL同步系统设计
  • GNU Octave 基础教程(2):第一个 Octave 程序
  • 作为运营,需要在账号中给用户提供什么?
  • 文件管理总结
  • HCIP-数据通信基础
  • python高校运动会数据分析管理系统
  • LINUX620 NFS
  • 空壳V3.0,免费10开!
  • PAI推理重磅发布模型权重服务,大幅降低冷启动与扩容时长
  • 学网站开发的能找什么工作/搜狗推广登录平台官网
  • 做网站首页有什么/外贸seo推广招聘
  • 济宁网站建设多少钱/如何写市场调研报告
  • 网站建设服务合同书标准版/网络服务商怎么咨询
  • 灰色网站欣赏/360优化大师历史版本
  • 小程序源码网站论坛/网络软文推广案例