索引与查询优化

索引用空间换取查询速度:按高频查询的过滤与排序顺序建立联合索引,遵循最左前缀;写放大与选择性之间需要权衡,冗余索引要定期清理。

索引与查询优化是什么

索引用额外的存储空间与写入开销换取查询速度。设计要点是让高频查询的过滤条件与排序顺序尽量命中同一个索引,并遵循最左前缀规则;索引并非越多越好,写多的表上每个额外索引都会放大写入与维护成本。

列序怎么定

一般顺序是等值条件列在前,范围条件列与排序列在后,因为范围条件之后的列通常无法继续用于精确定位。如果查询涉及的列全部包含在索引里,就可以避免回表,这在宽表上的高频查询中收益明显。动手加索引前先看执行计划,确认扫描行数与回表次数,再决定加什么、怎么排序。

基本信息

联合索引按等值、范围、排序的顺序设计列序,注意最左前缀
覆盖索引查询列全部命中索引即可避免回表
维护成本写多的表控制索引数量,定期检查未使用的索引
失效场景列被函数包裹、隐式类型转换都会导致索引无法使用

联合索引示例

联合索引示例
CREATE INDEX idx_order_user_status_time
  ON orders (user_id, status, created_at);
-- 支持:WHERE user_id=? AND status=? ORDER BY created_at
-- 范围条件之后的列,通常无法继续用于等值定位
-- 加索引前先用执行计划确认扫描行数与回表次数

优化步骤

  • 抓慢查询:按总耗时与出现频率排序,圈定优化对象
  • 看执行计划:确认扫描行数、命中索引与回表次数
  • 定列序:等值条件列在前,范围与排序列在后
  • 验证收益:对比优化前后的执行计划与延迟数据
  • 控制成本:合并冗余索引,跟踪写延迟与空间占用

什么时候不该加索引

写入密集的表要慎加索引:每次插入与更新都要维护全部索引,写放大会直接体现在写入延迟上。选择性极低的列单独建索引收益很小,查询优化器很可能直接放弃使用。还有一种情况是查询本身可以改写:把范围查询拆成更窄的条件、减少返回列、避免在条件里做函数计算,往往比新增索引更有效。

索引是否生效必须用执行计划验证:函数包裹列、隐式类型转换、字符集不一致都会让索引失效,代码评审时看不出来,只有执行计划能暴露。

易错点

  • 对低选择性列单独建索引,写入变慢而查询收益极其有限
  • 查询条件里的列被函数包裹,索引用不上,全表扫描照旧
  • 联合索引列序与查询条件顺序不匹配,实际只能命中前缀
  • 索引只加不删,写放大与存储成本长期累积却无人清理

数据来源与参考

  • 《高性能 MySQL(第 4 版)》
  • MySQL 8.0 Reference Manual:Optimization and Indexes
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌