MySQL优化查询速度,explain分析执行计划

前言

SQL查得慢,不知道为什么慢。用EXPLAIN看MySQL怎么执行这条SQL,就能找到问题在哪。

一、EXPLAIN怎么用

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

输出很多列,重点看这几个:id、select_type、table、type、key、rows、Extra。

二、重点列详解

1. type(访问类型)

最重要的一列,看SQL查得快不快。

从好到差:

type 说明 速度
system 表只有一行 最快
const 主键或唯一索引查一次 很快
eq_ref 联表时主键关联 很快
ref 非唯一索引查 快
range 索引范围扫描 中
index 扫整个索引树 慢
ALL 全表扫描 最慢

目标: 至少达到range,最好是ref以上。

如果type是ALL,就是全表扫描,必须优化。

2. key(实际用到的索引)

key: NULL

说明没用索引。

key: idx_name

说明用到了idx_name索引。

3. rows(扫描行数)

MySQL预估要扫描多少行。

rows越大,越慢。

4. Extra(额外信息)

常见的:

  • Using where:WHERE过滤
  • Using index:覆盖索引,不用回表,好
  • Using filesort:需要额外排序,不好
  • Using temporary:用了临时表,不好

三、常见问题

问题1:type=ALL,全表扫描

原因: 没加索引,或者索引失效。

解决: 给WHERE条件的字段加索引。

问题2:key=NULL,没用索引

原因:

  1. 没建索引
  2. 索引失效了(函数、类型转换、前导模糊查询等)

解决: 建正确的索引,避免索引失效写法。

问题3:Using filesort

原因: ORDER BY的字段没走索引。

解决: 给ORDER BY的字段加索引。

问题4:Using temporary

原因: GROUP BY或DISTINCT用了临时表。

解决: 给GROUP BY的字段加索引。

四、实战案例

慢SQL

SELECT * FROM orders WHERE user_id = 100 ORDER BY create_time DESC LIMIT 10;

EXPLAIN结果:

id select_type table type key rows Extra
1 SIMPLE orders ALL NULL 100000 Using where; Using filesort

问题:

  1. type=ALL,全表扫描
  2. key=NULL,没用索引
  3. rows=100000,扫了10万行
  4. Using filesort,还要额外排序

优化

加联合索引:

ALTER TABLE orders ADD INDEX idx_userid_createtime (user_id, create_time);

再EXPLAIN:

id select_type table type key rows Extra
1 SIMPLE orders ref idx_userid_createtime 10 Using where

优化效果:

  1. type变成ref
  2. 用到了索引
  3. rows从10万变成10
  4. 没有filesort了

五、常用优化技巧

1. 避免SELECT *

只查需要的列,能用上覆盖索引。

2. WHERE条件加索引

经常查询的字段加索引。

3. 联合索引最左前缀

联合索引 (a,b,c),查询条件要从最左列开始。

4. 避免索引失效

  • 不要对索引字段用函数
  • 不要隐式类型转换
  • 不要前导模糊查询 like '%xxx'

总结

EXPLAIN看这三点:

  1. type:是不是全表扫描
  2. key:有没有用到索引
  3. rows:扫描了多少行

记住: 慢SQL先EXPLAIN,找到问题再优化。

遇到问题加QQ23979811 协助处理


emer 发布于  2026-10-8 07:47 

MySQL 索引优化实战:从 Explain 分析到查询性能翻倍

前言

数据库查询慢是 Web 开发中最常见的性能问题之一。而绝大多数慢查询都可以通过合理使用索引来解决。本文将从 Explain 执行计划入手,带你一步步掌握 MySQL 索引优化的实战技巧。

一、认识 Explain 执行计划

要优化查询,首先得知道 MySQL 是怎么执行你的 SQL 的。EXPLAIN 命令可以展示 MySQL 执行查询的详细步骤:

EXPLAIN SELECT * FROM orders WHERE user_id = 10086 AND status = 'paid';

重点关注以下几个字段:

  • type:访问类型,从好到差依次为 const > eq_ref > ref > range > index > ALL。出现 ALL 就是全表扫描,必须优化。
  • key:实际使用的索引。如果为 NULL,说明没有用到索引。
  • rows:预估需要扫描的行数。这个值越大越慢。
  • Extra:额外信息。Using filesort 和 Using temporary 都是危险信号。

二、最左前缀原则

联合索引 (a, b, c) 的匹配规则:

-- 用到索引 a,b,c
SELECT * FROM t WHERE a = 1 AND b = 2 AND c = 3;

-- 用到索引 a,b
SELECT * FROM t WHERE a = 1 AND b = 2;

-- 只用到索引 a(中间断了)
SELECT * FROM t WHERE a = 1 AND c = 3;

-- 完全用不到索引
SELECT * FROM t WHERE b = 2 AND c = 3;

实战要点:把等值查询的列放在前面,范围查询的列放在后面。

三、常见索引失效场景

1. 对索引列使用函数或运算

-- 失效:对索引列用了函数
SELECT * FROM users WHERE DATE(created_at) = '2026-01-01';

-- 有效:改成范围查询
SELECT * FROM users WHERE created_at >= '2026-01-01' AND created_at < '2026-01-02';

2. 隐式类型转换

-- 失效:phone 是 varchar,用数字查
SELECT * FROM users WHERE phone = 13800138000;

-- 有效:加引号
SELECT * FROM users WHERE phone = '13800138000';

3. LIKE 以通配符开头

-- 失效
SELECT * FROM users WHERE name LIKE '%张%';

-- 有效
SELECT * FROM users WHERE name LIKE '张%';

四、实战优化案例

问题 SQL(扫描 10 万行,耗时 1.2 秒):

SELECT id, title, created_at FROM articles
WHERE category_id = 5 AND status = 'published'
ORDER BY created_at DESC LIMIT 20;

Explain 结果:type=index,rows=120000,Using filesort。

优化方案:创建联合索引

ALTER TABLE articles ADD INDEX idx_cat_status_time (category_id, status, created_at DESC);

优化后:type=ref,rows=20,Extra 无 filesort。查询时间从 1.2 秒降到 0.005 秒。

五、索引不是越多越好

索引虽然能加速查询,但也有代价:

  1. 写入变慢:每次 INSERT/UPDATE 都要维护索引
  2. 占用空间:索引也是要存磁盘的
  3. 优化器选错:索引太多可能让优化器犯迷糊

建议:单表索引数量控制在 5 个以内,避免重复索引和冗余索引。

总结

MySQL 索引优化的核心思路:

  1. 用 EXPLAIN 看执行计划,找到慢的原因
  2. 遵循最左前缀原则设计联合索引
  3. 避免常见的索引失效写法
  4. 定期清理无用索引

掌握这些技巧,你就能解决 80% 以上的慢查询问题。


emer 发布于  2026-10-4 09:52 
'); })();