sql性能优化需系统性排查:先通过慢查询日志和explain定位瓶颈,再针对性优化索引(遵守最左匹配、避免函数/隐式转换)、sql写法(禁用select *、改深分页为游标、控制join数量)及表结构(分区、拆大字段、统一字符集)。

SQL性能优化不是靠背口诀,而是看懂数据库怎么想、怎么干。面试中问“怎么优化慢SQL”,考的从来不是标准答案,而是你有没有系统性排查的习惯、能不能抓住关键瓶颈、会不会权衡代价。
先定位,别猜——从慢查询日志和EXPLAIN入手
没证据的优化都是拍脑袋。第一步永远是拿到真实执行信息:
- 打开慢查询日志(slow_query_log = ON),设好阈值(long_query_time = 1秒较合理);
- 用
EXPLAIN看执行计划,重点关注type(是否用到索引)、rows(预估扫描行数)、key(实际命中哪个索引)、Extra(有没有Using filesort或Using temporary); - 如果发现
rows远大于返回结果数,说明过滤条件没走索引,得查WHERE字段有没有隐式转换、函数包裹或OR连写。
索引不是越多越好,而是要“刚好够用”
索引本质是空间换时间,但写入代价、维护成本、内存占用都真实存在:
- 联合索引必须遵守最左匹配:比如建了
(user_id, status, create_time),那WHERE user_id = ? AND status = ?能用,但WHERE status = ?就失效; - 避免在索引列上做运算:
WHERE DATE(create_time) = '2025-01-01'会让索引失效,改成WHERE create_time >= '2025-01-01' AND create_time ; - LIKE只在前缀匹配时有效:
username LIKE '张%'走索引,username LIKE '%张%'基本等于全表扫; - 删除长期未被
information_schema.STATISTICS记录使用的索引,减少写放大。
写法决定效率,少做无谓动作
很多慢SQL问题出在语句结构本身,和索引无关:
- 别用
SELECT *,只查真正需要的字段,尤其避开BLOB/TEXT; - 深分页不用
LIMIT 10000, 20,改用游标式查询:WHERE id > 10000 ORDER BY id LIMIT 20; - 多表JOIN控制在3张以内,大表务必放在驱动表位置(MySQL中,小结果集驱动大表更优);
- 用
UNION ALL代替UNION,除非真需要去重; - 子查询优先考虑改写为JOIN或CTE,避免重复执行和无法下推条件。
结构和场景也要适配,不能只盯SQL本身
有些瓶颈不在语句,而在设计或环境:
- 单表超千万行,考虑按时间分区(RANGE分区)或分库分表;
- 高频统计类查询,提前物化聚合结果(如按天汇总订单金额),别每次实时算;
- 大字段(如商品描述、用户头像路径)拆到附表,主表保持轻量;
- 确认字符集和排序规则一致,尤其JOIN字段两边都是
utf8mb4_unicode_ci,否则索引可能失效; - 检查是否因并发高、内存不足或磁盘I/O打满,导致本该快的SQL变慢。











