查看: 33|回复: 0

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

[复制链接]

2

主题

0

回帖

0

积分

积极分子

金币
0
阅读权限
220
精华
0
威望
0
贡献
0
在线时间
0 小时
注册时间
2011-10-5
发表于 2026-4-26 15:11:00 | 显示全部楼层 |阅读模式

一、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
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

相关侵权、举报、投诉及建议等,请发 E-mail:qiongdian@foxmail.com

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部