mysql索引优化在面试中常考哪些点_mysql高频考点总结

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

为什么
WHERE
条件里用了函数索引就失效了

MySQL 无法对表达式结果做索引匹配,比如

WHERE YEAR(create_time) = 2023
,即使
create_time
有索引,优化器也无法下推使用。本质是索引 B+ 树里存的是原始值,不是计算后的结果。

实操建议:

改写为范围查询:
WHERE create_time >= '2023-01-01' AND create_time 
如果必须按年查,可额外建生成列索引(MySQL 5.7+):
ALTER TABLE t ADD COLUMN y INT AS (YEAR(create_time)) STORED, ADD INDEX idx_y(y)
避免在索引字段上用
UPPER()
TRIM()
CONCAT()
等函数

ORDER BY
LIMIT
组合为啥有时走不了索引

ORDER BY
字段不在索引最左前缀,或排序方向不一致(如联合索引
(a,b)
,却写
ORDER BY a ASC, b DESC
),MySQL 可能放弃索引排序,改用文件排序(
Using filesort
)。

实操建议:

联合索引顺序要匹配查询顺序,
ORDER BY a,b
对应索引
(a,b)
,而非
(b,a)
LIMIT
本身不决定是否走索引,但
ORDER BY + LIMIT
是典型“分页陷阱”,
OFFSET
很大时即使走了索引,也要跳过大量行
深分页优化优先考虑游标法(用上一页最后一条的
id
作为下一页条件),而不是依赖
OFFSET

什么情况下
SELECT *
会导致索引失效或回表加重

覆盖索引(Covering Index)要求查询字段全部被索引包含。一旦写

SELECT *
,而索引只是二级索引(非聚簇索引),就必须回表查主键对应行的完整数据,IO 成倍增加。

实操建议:

只查需要的字段,尤其避免在高频查询中
SELECT *
把常用查询字段加入联合索引末尾,构成覆盖索引,例如查询常要
user_id, status, created_at
,可建索引
(status, user_id, created_at)
注意
TEXT
/
BLOB
类型字段不能建索引,且会阻止覆盖索引生效(因为它们不存于索引页)

EXPLAIN
type=ALL
Extra=Using temporary
分别意味着什么

type=ALL
表示全表扫描,没走任何索引;
Extra=Using temporary
表示 MySQL 内部创建了临时表(常见于 GROUP BY、DISTINCT 或某些 JOIN 场景),往往伴随性能陡降。

实操建议:

type
值从好到差:
const
eq_ref
>
ref
>
range
>
index
>
ALL
;只要看到
ALL
,就要立刻检查 WHERE 条件是否有可用索引
Using temporary
出现在 GROUP BY 时,确认分组字段是否已建索引;若用了函数(如
GROUP BY DATE(created_at)
),同样会触发临时表
key_len
值比预期小,说明只用了联合索引前缀,后面字段没生效——这时要检查 WHERE 条件是否满足最左前缀原则
索引优化真正难的不是记规则,而是看懂
EXPLAIN
输出和实际执行路径之间的落差。很多面试题故意在隐式类型转换、字符集不一致、统计信息过期这些地方设坑,光背结论没用。

相关推荐