MySQL 查询太慢怎么优化?
SQL 查询执行很慢,页面响应时间长,需要定位和优化慢查询
解决方案
用 EXPLAIN 分析执行计划 推荐
-- 1. 在慢查询前加 EXPLAIN EXPLAIN SELECT o.order_no, u.username, o.total_amount FROM orders o JOIN users u ON o.user_id = u.id WHERE o.status = 1 AND o.created_at > '2026-05-01' ORDER BY o.created_at DESC LIMIT 20; -- 2. 关注这些指标: -- type: ALL(全表扫描,最差) → index → range → ref → const(最好) -- key: NULL 表示没用到索引 -- rows: 扫描行数,越少越好 -- Extra: Using filesort / Using temporary 需要优化 -- 3. 根据分析结果添加索引 CREATE INDEX idx_status_created ON orders(status, created_at);
EXPLAIN 是 MySQL 查询优化的第一步,能看到查询是否使用了索引、扫描了多少行、是否有排序等。根据分析结果针对性地添加索引或改写 SQL。
适用场景:任何查询变慢时的第一步诊断
优化索引设计 推荐
-- 常见索引优化策略: -- 1. 为 WHERE 条件创建复合索引(遵循最左前缀) CREATE INDEX idx_user_status_time ON orders(user_id, status, created_at); -- 2. 覆盖索引(避免回表) CREATE INDEX idx_cover ON orders(user_id, status, created_at, total_amount); -- 查询只需要索引中的列时,不需要回表查数据 -- 3. 避免索引失效的写法 -- 错误:WHERE YEAR(created_at) = 2026 (函数导致索引失效) -- 正确:WHERE created_at >= '2026-01-01' AND created_at < '2027-01-01' -- 错误:WHERE phone LIKE '%1234' (左模糊导致索引失效) -- 正确:WHERE phone LIKE '138%' (右模糊可以用索引) -- 错误:WHERE status != 1 (不等于可能不走索引) -- 正确:WHERE status IN (0, 2, 3) (用 IN 代替)
索引是查询优化最有效的手段。复合索引要把区分度高的列放前面,同时注意避免让索引失效的 SQL 写法。
适用场景:EXPLAIN 显示 type=ALL 或 key=NULL 时
优化 SQL 写法
-- 1. 避免 SELECT * -- 差:SELECT * FROM orders WHERE user_id = 1001; -- 好:SELECT order_no, total_amount, status FROM orders WHERE user_id = 1001; -- 2. 深分页优化 -- 差:SELECT * FROM orders ORDER BY id LIMIT 100000, 20; (扫描 10 万行) -- 好:SELECT * FROM orders WHERE id > 100000 ORDER BY id LIMIT 20; (游标分页) -- 3. 避免子查询,改用 JOIN -- 差:SELECT * FROM users WHERE id IN (SELECT user_id FROM orders WHERE status = 1); -- 好:SELECT DISTINCT u.* FROM users u JOIN orders o ON u.id = o.user_id WHERE o.status = 1; -- 4. 批量操作代替循环 -- 差:逐条 INSERT -- 好:INSERT INTO t VALUES (...), (...), (...); (批量插入)
SQL 写法直接影响执行效率。避免 SELECT *、优化深分页、用 JOIN 代替子查询都是常见的优化手段。
适用场景:索引已经合理但查询仍然慢时
开启慢查询日志持续监控
-- 开启慢查询日志 SET GLOBAL slow_query_log = ON; SET GLOBAL long_query_time = 1; -- 超过 1 秒记录 SET GLOBAL log_queries_not_using_indexes = ON; -- 查看慢查询日志文件位置 SHOW VARIABLES LIKE 'slow_query_log_file'; -- 用 mysqldumpslow 分析 Top 10 慢查询 -- mysqldumpslow -s t -t 10 /var/log/mysql/slow.log -- 或用 pt-query-digest 更详细的分析 -- pt-query-digest /var/log/mysql/slow.log > report.txt
慢查询日志能持续记录执行时间超过阈值的 SQL,配合分析工具找出最需要优化的查询。
适用场景:需要系统性地发现和优化慢查询
注意事项
添加索引会降低写入性能,不要盲目加索引
生产环境修改索引用 pt-online-schema-change 避免锁表
优化前先用 EXPLAIN 确认问题,不要凭感觉优化