首先,开启慢查询日志,设置slow_query_log=1和long_query_time=1(单位秒),然后通过show processlist查看当前慢查询;使用EXPLAIN分析查询计划,关注type、key、rows字段;优化索引,建立合适的复合索引,避免全表扫描;更新统计信息用ANALYZE TABLE;合理设计表结构,避免大字段和过多JOIN。
排查步骤
1. 检查慢查询日志:查看mysql.slow_log表或日志文件,找出执行时间长的SQL。
2. 用EXPLAIN SELECT ... 查看执行计划,type=ALL表示全表扫描,需要加索引。
3. 检查锁等待:show engine innodb status,看是否有死锁或长事务。
4. 监控CPU、内存、IO:用top、iotop、free命令观察资源瓶颈。
5. 参数调优:增大innodb_buffer_pool_size到内存的70%。
优化方法
索引优化是关键,对于频繁WHERE、JOIN、ORDER BY的字段建索引;用覆盖索引减少回表;避免SELECT *,只选需要的列;分页优化用id>last_id LIMIT 10代替OFFSET;子查询改关联查询;批量操作代替循环插入。
实际案例
一个订单表查询慢,EXPLAIN显示type=index,rows=100万,加了复合索引(user_id,create_time)后,rows降到10,时间从5s到0.01s。另一个是UPDATE锁表,改用WHERE id IN (select...)分批更新。
服务器层面
升级SSD硬盘,增加内存;MySQL配置max_connections=1000,innodb_flush_log_at_trx_commit=2;读写分离,主库写从库读;用Redis缓存热点数据,减少数据库压力。
代码示例
-- 慢查询示例
SELECT * FROM orders WHERE status=1 ORDER BY create_time DESC LIMIT 10000; -- 全表排序
-- 优化后
SELECT id,user_id,amount FROM orders WHERE status=1 ORDER BY create_time DESC LIMIT 10000;
-- 加索引:ALTER TABLE orders ADD INDEX idx_status_time(status,create_time);
监控工具
用Percona Toolkit的pt-query-digest分析慢日志;Prometheus+Grafana监控QPS、慢查询率;阿里云RDS的SQL洞察功能自动推荐索引。
FAQ
Q: 怎么快速找到最慢的SQL?
A: 开启慢查询日志,执行pt-query-digest slow.log | head -20。
Q: 加索引后还是慢怎么办?
A: 检查是否覆盖索引,统计信息是否更新,用ANALYZE TABLE刷新。
Q: 大表分页慢怎么优化?
A: 用基于自增ID的深分页:SELECT ... FROM table WHERE id > 最后ID LIMIT 20。
Q: InnoDB缓冲池设置多少合适?
A: 服务器内存的60-80%,留给OS用。