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

2次阅读

mysql函数索引失效因b+树存原始值而非计算结果,如year(create_time)=2023无法走索引;应改写为范围查询,并依explain中type、key_len、using temporary等指标诊断优化。

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

为什么 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 BYLIMIT 组合为啥有时走不了索引

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 类型字段不能建索引,且会阻止覆盖索引生效(因为它们不存于索引页)

EXPLAINtype=ALLExtra=Using temporary 分别意味着什么

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

实操建议:

  • type 值从好到差: consteq_ref > ref > range > index > ALL;只要看到 ALL,就要立刻检查 WHERE 条件是否有可用索引
  • Using temporary 出现在 GROUP BY 时,确认分组字段是否已建索引;若用了函数(如 GROUP BY date(created_at)),同样会触发临时表
  • key_len 值比预期小,说明只用了联合索引前缀,后面字段没生效——这时要检查 WHERE 条件是否满足最左前缀原则

索引优化真正难的不是记规则,而是看懂 EXPLAIN 输出和实际执行路径之间的落差。很多面试题故意在隐式类型转换、字符集不一致、统计信息过期这些地方设坑,光背结论没用。

text=ZqhQzanResources