什么是索引失效,如何避免它?
索引失效是指在MySQL数据库中,索引没有起到预期的作用,导致查询性能下降的情况。¹²³⁴⁵
索引失效的原因有很多,例如:
- 不符合全值匹配或最佳左前缀法则,即查询条件没有包含索引的第一列或跳过了索引中的某些列。¹²³
- 在索引列上使用了运算、函数、类型转换等操作,导致MySQL无法利用索引。¹²³
- 使用了不等于、or、like %等条件,导致MySQL无法有效地使用索引。¹²³⁴
- 查询结果集过大,导致MySQL认为全表扫描比使用索引更快。³⁴
如何避免索引失效的方法有很多,例如:
- 根据查询条件设计合理的索引,遵循全值匹配和最佳左前缀法则。¹²³
- 避免在索引列上使用运算、函数、类型转换等操作,尽量让索引列保持原始值。¹²³
- 优化查询条件,尽量使用等于、in、between等条件,避免使用不等于、or、like %等条件。¹²³⁴
- 使用覆盖索引,即只访问索引的查询,避免select *。¹²³
- 分析SQL执行计划,使用explain命令或第三方工具,查看是否有优化空间。²³
什么是覆盖索引
覆盖索引是指查询的数据列只用从索引中就能够取得,不必读取数据行,换句话说查询列要被所建的索引覆盖。²³⁴⁵⁶
覆盖索引的好处是可以避免回表操作,即不需要再根据主键去查找数据行,从而减少系统调用和数据拷贝等时间,提高查询性能。¹³⁵
覆盖索引的使用方法是根据查询需求设计合适的索引,尽量让索引包含所有需要的字段,避免select *。¹²³⁴⁵
例如,假设有一个表user,包含id、name、age、gender等字段,其中id是主键,name和age是非主键索引。如果查询语句是:
select name from user where age = 20;
那么这个语句就可以利用覆盖索引,因为name和age都在非主键索引中,不需要再回表查找数据行。⁴
MySQL全值匹配
MySQL全值匹配是指在使用复合索引时,查询条件要包含索引的所有列,才能最大程度地利用索引。¹
例如,假设有一个表emp,包含id、name、age、deptid等字段,其中id是主键,age、deptid和name是复合索引。如果查询语句是:
select * from emp where age = 20 and deptid = 10 and name = 'Tom';
那么这个语句就可以利用全值匹配,因为查询条件包含了复合索引的所有列。¹
如果查询语句是:
select * from emp where age = 20 and deptid = 10;
那么这个语句就不能利用全值匹配,因为查询条件缺少了复合索引的最后一列name。¹