为什么 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,再好的索引也救不了,得换方案(游标分页、延迟关联、或业务上限制深度)。
