SQL优化的20条军规

SQL 优化的 20 条军规(MySQL 为主,生产环境实战版)

以下 20 条规则是大量互联网公司(尤其是中大厂)在 MySQL 环境下总结出的高频、致命、必须遵守的优化军规。很多慢查询、线上事故都和违反其中几条直接相关。

优先级排序(从最致命到相对次要):

  1. **禁止 SELECT ***
    只查询真正需要的字段。
    反例:SELECT * FROM user WHERE id = 1
    正例:SELECT id, name, phone FROM user WHERE id = 1
    理由:减少 IO、降低网络传输、防止表结构变更影响。
  2. WHERE 条件字段必须走索引
    所有过滤、排序、连接字段尽量建索引。
    没有索引 = 全表扫描(大表秒变 OOM)。
  3. 上线前必用 EXPLAIN / EXPLAIN ANALYZE 分析
    关注 type、key、rows、Extra(Using filesort / Using temporary 最危险)。
    目标:type ≥ ref / range,Extra 不出现 filesort / temporary。
  4. 禁止在 WHERE 条件列上使用函数
    反例:WHERE DATE(create_time) = '2025-01-01'
    正例:WHERE create_time >= '2025-01-01' AND create_time < '2025-01-02'
    函数导致索引失效。
  5. 避免 OR 条件
    OR 很容易导致全表扫描。
    改写为 UNION ALL 或拆成多条 SQL + 代码合并。
    极少数情况下可用 IN 替代(但 IN 元素过多也危险)。
  6. LIKE 左边不要加 %
    反例:WHERE name LIKE '%张三%' → 索引失效
    正例:WHERE name LIKE '张三%' → 可走前缀索引
  7. JOIN 表数量控制在 3 张以内
    多表 join 容易产生笛卡尔积爆炸。
    超过 3 张表建议拆 SQL 或引入中间表。
  8. JOIN 时字段类型、字符集、排序规则必须完全一致
    否则隐式转换导致索引失效(最常见 varchar 与 char、utf8 与 utf8mb4)。
  9. 小表驱动大表
    永远让小表(行数少)放在左边(驱动表)。
    MySQL 执行计划会尽量把小表放在前面,但不要依赖它。
  10. 禁止在索引列上做计算
    反例:WHERE age + 1 > 18
    正例:WHERE age > 17
  11. 分页大偏移优化(千万级表致命)
    反例:LIMIT 1000000,10(扫描 1000010 行)
    正例: SELECT id FROM t ORDER BY id LIMIT 1000000,10; -- 然后用 id 回表 SELECT * FROM t WHERE id IN (……) ORDER BY id; 或用延迟关联 / 覆盖索引。
  12. 优先使用覆盖索引
    把查询字段全部放到索引中(索引覆盖所有 select + where + order by + group by),Extra = Using index。
  13. 拒绝在 WHERE 中使用 !=、<>、NOT IN、NOT EXISTS
    这些条件很难利用索引,优先改成正向条件。
  14. ORDER BY / GROUP BY 字段要走索引
    否则 Using filesort(内存/磁盘排序)非常耗资源。
  15. 控制 IN 列表长度
    IN 超过 1000 条左右性能急剧下降,建议分批或用临时表。
  16. 避免隐式类型转换
    反例:WHERE phone = 13812345678(phone 是 varchar)
    正例:WHERE phone = '13812345678'
  17. COUNT(*) vs COUNT(1) vs COUNT(主键)
    MySQL 5.7.18+ 后三者性能几乎无差别,但建议用 COUNT(*)(最清晰)。
  18. 批量操作优于循环单条
    INSERT/UPDATE/DELETE 优先批量(VALUES 多行或 JOIN + UPDATE)。
  19. 禁止在事务中做大批量更新
    大事务持锁时间长,容易死锁 / 阻塞。拆小批次 + 合理 sleep。
  20. 合理使用索引下推(Index Condition Pushdown)
    MySQL 5.6+ 支持,把 where 条件推到存储引擎层减少回表。
    尤其对复合索引 + 范围 + 其他过滤条件非常有效。

快速记忆口诀版(浓缩 10 条最狠的)

  • 别 *,要字段
  • 索必须有,where 必中
  • Explain 先行,type ref range
  • 函数、计算、OR 尽量别上
  • Like 右模糊,左模糊别用
  • Join 三张内,小表驱动大
  • 类型一致,字符集一致
  • 大偏移分页要用 id 优化
  • 覆盖索引最香
  • 批量 > 循环,事务别太大

最后提醒
SQL 优化不是“一招鲜”,先用 EXPLAIN 定位问题,再针对性优化。
线上慢查询日志 + 定期 review 是长治久安的根本。

你最近在优化哪类 SQL?是分页、JOIN 还是聚合?可以贴出来具体语句,我帮你一起分析。

文章已创建 4516

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部