为什么mysql查询慢需要优化索引_mysql性能分析技巧

来源:这里教程网 时间:2026-02-28 20:53:04 作者:

为什么
SELECT
越查越慢,加了索引也没用?

根本原因往往不是没建索引,而是索引没被用上。MySQL 优化器会根据统计信息、条件写法、数据分布等决定是否走索引——

WHERE
中用了函数、隐式类型转换、或
LIKE
开头带通配符(如
'%abc'
),都会让索引失效。

实操建议:

EXPLAIN
type
字段:如果是
ALL
index
,基本等于全表扫描
检查
key
列是否为
NULL
,是就说明没走索引
留意
Extra
列:出现
Using filesort
Using temporary
是性能红灯
避免在索引列上做运算,比如
WHERE YEAR(create_time) = 2023
→ 改成
WHERE create_time >= '2023-01-01' AND create_time 

EXPLAIN
输出里哪些字段最关键?

EXPLAIN
不是看有没有“
key
”就完事,要盯住四个字段:
type
key
rows
Extra

常见误判点:

type
range
看似还行,但如果
rows
显示 50 万,说明这个范围太大,实际效率接近全扫
key
显示用了索引,但
Extra
写着
Using index condition
是好事(ICP 下推),而
Using where
意味着回表后还要过滤,可能意味着索引覆盖不全
rows
是估算值,不准但有参考性;如果从几千突增到几十万,大概率是统计信息过期,可运行
ANALYZE TABLE table_name
更新

联合索引怎么建才不白建?

联合索引不是字段堆砌,顺序决定生死。它本质是按最左前缀排序的 B+ 树,只支持“从左到右连续匹配”。

举个例子:索引是

(a, b, c)
,以下查询能用上:

WHERE a = 1 AND b = 2
✅(用到前两列)
WHERE a = 1 AND b > 2 AND c = 3
✅(
b
范围查询后,
c
无法再走索引,但该条件仍可用于过滤)
WHERE b = 2 AND c = 3
❌(没用
a
,跳过最左,整个索引失效)

建索引前先看慢查的

WHERE
+
ORDER BY
+
SELECT
字段组合,优先把高频过滤字段放左边,排序字段放中间,查询返回字段放右边(用于覆盖索引)。

什么时候该删索引而不是加索引?

索引不是越多越好。每个索引都增加写开销(INSERT/UPDATE/DELETE 都要维护)、占用磁盘、拖慢优化器决策速度。尤其当一个表有 10+ 索引却长期只有 1–2 个被用到,就是信号。

判断依据:

information_schema.statistics
或用
sys.schema_unused_indexes
(MySQL 8.0+)找长期未命中的索引
观察
Handler_read_*
状态变量,
Handler_read_key
很低但
Handler_read_next
很高,说明索引没起到定位作用
单表索引总数超过 5–6 个,且存在字段重复出现在多个索引中(如
(a)
(a,b)
(a,b,c)
),优先保留最长的那个

真正难的不是建索引,是识别哪些查询本就不该走索引——比如日志类大表的分页查询

LIMIT 1000000, 20
,再好的索引也救不了,得换方案(游标分页、延迟关联、或业务上限制深度)。

相关推荐