默认情况下,SQL 语句中不会选择索引,都是由优化器自动选择。
优化器为了得到最优方案,会考虑扫描行数、是否使用临时表、是否排序等因素。
但有时候,因为种种原因,优化器选择的并不是最佳索引。
索引选择异常处理方案
analyze table
-
有时候 Mysql 不能准确判断数据的扫描行数,这时可以用 analyze table t 来重新统计索引信息
-
如果 explain 的 rows 值和实际情况相差较大,可以使用重新统计的方式解决
force index
- Mysql 会根据语法分析结果,分析出可能使用的索引作为候选项,当 force index 的索引在候选项中,则直接选择,不再评估其他候选项的代价
select * from t where a between 1 and 1000 and b between 50000 and 10000 order by b limit 1;
↓
select * from t force index(a) where a between 1 and 1000 and b between 50000 and 100000 order by b limit 1;
修改 SQL
select * from t where a between 1 and 1000 and b between 50000 and 100000 order by b limit 1;
↓
select * from t where a between 1 and 1000 and b between 50000 and 100000 order by b,a limit 1;
-
两条 SQL 语义相同,都能得到 b 最小的一条数据
-
修改前只根据 b 排序,直接用 b 索引,本身就是有序的,只要遍历,不再需要额外排序,所以即使扫描行数多,也被认为代价较小
-
修改后要根据 b,a 排序,不管选择 a b 哪个索引都需要再次排序,所以最终会选择扫描行数较小的 a 索引
修改索引
-
删掉不必要的索引,避免误用
-
新建更合适的索引
索引优化要具体问题具体分析,在实践中摸索,没有统一方案。