SQL 优化、索引、执行计划、慢查询

一、SQL 为什么会慢?

  根本原因 3 个:  

  1. 没走索引 / 索引失效(全表扫描)
  2. 数据量太大(没分页、没过滤)
  3. 写法复杂(子查询嵌套、join 太多、排序分组无索引)

 


 

二、索引(SQL 优化的核心)

 

1. 什么是索引?

  可以理解为书的目录:  

  • 没有索引 = 一页一页翻(全表扫描)
  • 有索引 = 直接查目录定位(快速查找)

 

2. 最常用索引类型

 

  1. 主键索引(PRIMARY KEY)   唯一、非空、最快
  2. 唯一索引(UNIQUE)   列值不能重复
  3. 普通索引(INDEX)   最常用,加速查询
  4. 联合索引(复合索引)   最关键! 多列一起建索引

 

3. 联合索引最左前缀原则

  索引
(a, b, c)  

  • 能命中:where a=?where a=? and b=?where a=? and b=? and c=?
  • 不能命中:where b=?where c=?where b=? and c=?

  一句话:必须从左到右连续使用,不能跳过前面的列。  

4. 哪些情况索引会失效?(高频)

 

  1. 索引列上运算 / 函数:where age+1=10where substr(name,1,2)='ab'
  2. 隐式类型转换:where phone=13800138000(phone 是字符串)
  3. like 以 % 开头:where name like '%张三'
  4. 使用!= /not in /is not null(会导致索引失效)
  5. or 连接非索引列
  6. 联合索引不满足最左前缀

 

5. 建索引的最佳实践

 

  • where 经常查询的列建索引
  • group by / order by 字段建索引
  • join 关联字段建索引
  • 不要滥用索引(写入会变慢)
  • 区分度低的列不要建索引(如性别、状态)
  • 优先用联合索引,少用多个单值索引

 


 

三、执行计划(看懂 SQL 到底怎么跑)

  使用命令(MySQL):  

EXPLAIN SELECT * FROM user WHERE name = '张三';

   

重点看 3 个字段

 

  1. type(最重要)   性能从好到坏:   system > const > eq_ref > ref > range > index > ALL  
    • ALL = 全表扫描(必须优化)
    • ref = 走了索引(良好)
    • range = 范围索引(良好)

     

  2. key   实际使用了哪个索引,为 NULL 表示没走索引。  
  3. Extra  
    • Using filesort:文件排序(必须优化)
    • Using temporary:用到临时表(必须优化)
    • Using index:覆盖索引(最优)

     

 


 

四、常见慢查询 + 优化方案

 

1. 慢查询 1:全表扫描

 

SELECT * FROM user WHERE name = '张三';

    优化:给 name 建索引  

CREATE INDEX idx_name ON user(name);

   


 

2. 慢查询 2:like % xxx(索引失效)

 

SELECT * FROM user WHERE name LIKE '%张三';

    优化:  

  • 业务允许:改成 LIKE '张三%'
  • 必须模糊:用 ES 或 MySQL 全文索引

 


 

3. 慢查询 3:索引列上用函数

 

SELECT * FROM user WHERE YEAR(create_time) = 2025;

    优化:  

SELECT * FROM user 
WHERE create_time >= '2025-01-01' 
AND create_time < '2026-01-01';

 


 

4. 慢查询 4:order by 无索引

 

SELECT * FROM user ORDER BY create_time DESC;

    优化:给排序字段建索引  


 

5. 慢查询 5:join 无索引

 

SELECT * FROM order o
JOIN user u ON o.user_id = u.id
WHERE u.name = '张三';

    优化:  

  • order.user_id 建索引
  • user.name 建索引

 


 

6. 慢查询 6:not in / != 导致索引失效

 

SELECT * FROM user WHERE status != 1;

    优化:  

  • 改用范围
  • 或业务上调整为正向查询

 


 

7. 慢查询 7:分页太深

 

SELECT * FROM user LIMIT 1000000,10;

  优化:  

SELECT * FROM user 
WHERE id > 1000000 
LIMIT 10;

 


 

五、SQL 优化便签

 

  1. 先看是否走索引
  2. 避免全表扫描(type=ALL)
  3. 索引列不运算、不函数
  4. 联合索引遵守最左前缀
  5. 少用 select *,只查需要的列
  6. join 必须加索引
  7. 深度分页用主键过滤
  8. 避免 Using filesort 和 Using temporary

 


 

六、快速排查慢查询步骤

 

  1. 开启慢查询日志
  2. EXPLAIN 看执行计划
  3. type 是否 ALL(全表扫描)
  4. key 是否为 NULL(没走索引)
  5. Extra 是否有文件排序 / 临时表
  6. 建索引 / 改 SQL 重新验证

 


 

总结

 

  • 索引是 SQL 优化的核心,联合索引最常用
  • 执行计划判断 SQL 好坏
  • 慢查询 90% 是索引问题
  • 索引列不运算、不函数、不隐式转换

文章摘自:https://www.cnblogs.com/chuansheng/p/19914144