MySQL 索引原理与最佳实践
B+Tree 结构、回表与覆盖索引、最左前缀原则、索引选择性,以及避免索引失效的常见写法。
索引是 MySQL 查询性能的决定性因素。理解 InnoDB 的 B+Tree 索引结构,才能写出真正命中索引的 SQL。
B+Tree 与聚簇索引
InnoDB 使用 B+Tree 组织索引,其特点是非叶子节点只存索引键用于导航,所有数据都落在叶子节点,且叶子节点通过双向链表串联,非常适合范围扫描。
InnoDB 的主键索引是聚簇索引,叶子节点直接存放整行数据;二级索引的叶子节点存放「索引键 + 主键值」。因此通过二级索引查询非索引列时,需要再用主键回表查聚簇索引。
回表与覆盖索引
当查询的列都在二级索引中时,无需回表,称为覆盖索引,性能更好:
若 SELECT * 还需要 phone 等额外列,则会触发回表。高频查询应优先设计为覆盖索引。
最左前缀原则
联合索引 (a, b, c) 能生效的条件是查询从最左列开始连续匹配:
WHERE a = ?可用WHERE a = ? AND b = ?可用WHERE b = ?无法使用该联合索引(断开了最左前缀)
避免索引失效
常见导致索引失效的写法:
- 对索引列做函数运算或隐式类型转换:
WHERE DATE(create_time) = ... - 使用前导模糊匹配:
LIKE '%abc' - 使用
OR连接非索引列 - 优化器判断全表扫描更快时主动放弃索引
索引并非越多越好:每个索引都会拖慢写入与占用空间。应结合选择性(区分度)高的列建索引,并用 EXPLAIN 验证执行计划。