MySQL执行器对存储引擎API调用改写后,为何强制索引有时会完全失效?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1333个文字,预计阅读时间需要6分钟。
MySQL 的 `FORCE INDEX` 不是强制执行,而是强制优化器考虑这个索引——它只影响优化器的索引选择阶段,并不决定存储引擎如何实际读取数据。一旦优化器决定使用某个索引,存储引擎仍可能根据实际情况选择全表扫描。当优化器确定某个索引后,如果后续执行时发现该索引无法满足查询需求(例如,需要回表查找主键、存在隐藏的类型转换等),存储引擎可能会直接退化为全表扫描。可以通过 `EXPLAIN` 查看执行计划,如果显示 `type=ALL` 或 `type=range`,说明已绕过索引。
- 常见现象:
EXPLAIN显示用了你FORCE的索引,但rows高得离谱,Extra出现Using where; Using index condition甚至Using filesort,慢查依旧 - 根本原因:优化器选了索引,但存储引擎 API(如
ha_innobase::index_read())在真正调用时发现索引记录不满足WHERE中的全部条件(尤其涉及函数、表达式、NULL 安全比较时),被迫在引擎层逐行过滤,等效于索引失效 - 典型触发场景:对
FORCE的索引字段使用UPPER()、DATE(col)、col + 1 = 100等无法下推到索引扫描的表达式
INNODB 存储引擎如何响应 FORCE INDEX 的调用
InnoDB 接收优化器传来的索引名后,并不会无条件按该索引遍历。
本文共计1333个文字,预计阅读时间需要6分钟。
MySQL 的 `FORCE INDEX` 不是强制执行,而是强制优化器考虑这个索引——它只影响优化器的索引选择阶段,并不决定存储引擎如何实际读取数据。一旦优化器决定使用某个索引,存储引擎仍可能根据实际情况选择全表扫描。当优化器确定某个索引后,如果后续执行时发现该索引无法满足查询需求(例如,需要回表查找主键、存在隐藏的类型转换等),存储引擎可能会直接退化为全表扫描。可以通过 `EXPLAIN` 查看执行计划,如果显示 `type=ALL` 或 `type=range`,说明已绕过索引。
- 常见现象:
EXPLAIN显示用了你FORCE的索引,但rows高得离谱,Extra出现Using where; Using index condition甚至Using filesort,慢查依旧 - 根本原因:优化器选了索引,但存储引擎 API(如
ha_innobase::index_read())在真正调用时发现索引记录不满足WHERE中的全部条件(尤其涉及函数、表达式、NULL 安全比较时),被迫在引擎层逐行过滤,等效于索引失效 - 典型触发场景:对
FORCE的索引字段使用UPPER()、DATE(col)、col + 1 = 100等无法下推到索引扫描的表达式
INNODB 存储引擎如何响应 FORCE INDEX 的调用
InnoDB 接收优化器传来的索引名后,并不会无条件按该索引遍历。

