一、核心优化技巧1:遵循最左匹配,合理设计列顺序
1. 核心规则:等值条件列在前,范围条件列在后
联合索引的列顺序直接决定了查询能否利用索引,必须根据查询条件的类型设计:
-
✅ 正确示例:查询
where name='Lily' and age>17,建索引idx(name, age) -
name是等值条件,先锁定区间,再利用区间内age的有序性快速过滤; -
❌ 错误示例:建索引
idx(age, name) -
age是范围条件,锁定区间后name的有序性被破坏,无法利用索引。
2. 面试要点:避免"区分度优先"的误区
很多同学误以为区分度高的列要放前面,其实核心是查询条件的等值/范围类型,区分度仅在等值条件列之间作为次要参考。
二、核心优化技巧2:利用覆盖索引,彻底告别回表
1. 核心原理:查询的所有列都包含在联合索引中,无需回表
InnoDB的二级索引叶子节点存储的是(索引列值 + 主键值),如果查询的所有列都在索引中,MySQL可直接从索引返回数据,无需回表访问聚簇索引,大幅减少IO开销。
2. 实战示例
-
原SQL(需回表):
select * from t where name='Lily' and age=17,索引idx(name, age) -
select *需要查询所有列,索引中没有其他列,必须回表; -
优化后(覆盖索引):
select name, age from t where name='Lily' and age=17,索引idx(name, age) -
查询的列都在索引中,无需回表,
explain中Extra列会显示Using index。
3. 面试要点:避免使用select *,仅查询必要列
覆盖索引是优化查询性能的核心手段,面试时一定要提到"避免select *,使用覆盖索引减少回表"。
三、核心优化技巧3:利用索引有序性,干掉Using filesort
1. 核心原理:如果order by的列是联合索引的后续列,且前面的列是等值条件,可直接利用索引有序性排序,无需额外文件排序。
2. 实战示例
-
原SQL(出现
Using filesort):select * from t where name like 'L%' order by age,索引idx(name, age) -
name是范围条件,锁定区间后age的有序性被破坏,MySQL需额外排序; -
优化后(无
Using filesort):select * from t where name='Lily' order by age,索引idx(name, age) -
name是等值条件,锁定区间后age是有序的,可直接利用索引排序,无需额外操作。
四、核心优化技巧4:合并冗余索引,减少索引维护开销
1. 核心原理:联合索引的前缀列可替代单列索引,减少索引数量
联合索引idx(a, b)的前缀a是有序的,可替代单列索引idx(a),无需单独创建,减少索引数量的同时,降低写入操作的维护开销(索引越多,写入性能越差)。
2. 实战示例
-
原索引:
idx(name)和idx(name, age),两个索引都能用于查询name的场景; -
优化后:删除
idx(name),仅保留idx(name, age),后者可覆盖前者的所有查询场景,同时减少索引维护开销。
五、核心优化技巧5:配合索引下推(ICP),优化范围查询
1. 核心原理:当联合索引的前导列是范围条件,后续列无法利用索引时,开启ICP可在存储引擎层过滤后续列,减少Server层的过滤开销。
2. 实战示例
-
SQL:
select * from t where name like 'L%' and age=17,索引idx(name, age) -
name是范围条件,age无法利用索引,开启ICP后,存储引擎层可直接用索引中的age值过滤,仅将符合条件的主键传给Server层,减少数据传输开销。
六、避坑指南:这些索引失效场景别踩
❌ 误区1:在索引列上使用函数/运算,导致索引失效
- 示例:
where date_format(create_time, '%Y-%m')='2024-05',可使用虚拟列+索引优化。
❌ 误区2:前导列使用范围条件,导致后续列失效
- 示例:
where a>1 and b=2,索引idx(a,b)中a是范围条件,b无法利用索引,可调整为idx(b,a)。
❌ 误区3:联合索引总长度超过限制,导致索引创建失败
- 正解:InnoDB联合索引的总长度不能超过3072字节,过长的字符串列可使用前缀索引。
七、结尾总结
利用联合索引提升性能的核心,是最大化利用索引的有序性,避免回表和额外排序。面试时按这几个技巧回答,再结合业务场景举例,就能拿满分!