MySQL升级后索引失效主因是执行计划变更,需用EXPLAIN确认key是否为NULL;更新统计信息(ANALYZE TABLE)、检查字符集/排序规则兼容性、创建函数索引可解决。

MySQL升级后索引失效,通常不是索引“真的没了”,而是查询执行计划发生了变化,导致优化器不再选择原有索引。这背后多与统计信息过期、隐式类型转换、字符集/排序规则变更、索引列函数化或新版本优化器行为调整有关。
检查执行计划是否真没走索引
先用 EXPLAIN 确认当前查询是否真的跳过了索引:
- 运行
EXPLAIN SELECT ...,重点看 key 列是否为NULL,type 是否退化为ALL或index - 对比升级前的执行计划(如有慢日志或历史监控),确认是同一查询、相同数据量下行为突变
- 注意 Extra 列:出现
Using filesort或Using temporary不代表索引失效,但可能说明索引覆盖不全
更新统计信息和重建索引
MySQL 8.0+ 默认启用 innodb_stats_auto_recalc,但升级后旧表统计信息可能未及时刷新,导致优化器误判成本:
- 手动更新:对问题表执行
ANALYZE TABLE table_name; - 强制重建索引(尤其当表有大量增删改):
ALTER TABLE table_name ENGINE=InnoDB;(会重建聚簇索引和二级索引) - 若使用直方图,检查是否需重采样:
ANALYZE TABLE table_name UPDATE HISTOGRAM ON col1, col2;
排查字符集与排序规则兼容性
MySQL 5.7 升级到 8.0 时,默认字符集从 latin1 变为 utf8mb4,且默认排序规则变为 utf8mb4_0900_ai_ci。若字段定义未同步更新,易引发隐式转换:
- 检查索引列的
COLLATION:SHOW FULL COLUMNS FROM table_name LIKE 'col_name'; - 确认 WHERE 条件中传入的字符串字面量或参数是否匹配列的排序规则(如用
utf8mb4_general_ci的值去查utf8mb4_0900_ai_ci字段,可能触发转换,使索引失效) - 必要时显式指定排序规则:
WHERE col_name = 'xxx' COLLATE utf8mb4_0900_ai_ci,或统一修改列定义:ALTER TABLE t MODIFY col VARCHAR(100) COLLATE utf8mb4_0900_ai_ci;
验证函数索引与生成列兼容性
MySQL 5.7 不支持函数索引,8.0+ 支持。若升级后在 WHERE 中用了表达式(如 WHERE UPPER(name) = 'ABC'),而未创建对应函数索引,则无法走索引:
- 检查是否有常用表达式场景,例如大小写、日期截取、JSON 提取等
- 为高频表达式创建函数索引:
CREATE INDEX idx_upper_name ON t ((UPPER(name))); - 注意:函数索引列必须用双括号包裹,且仅支持确定性函数
- 若原逻辑依赖虚拟列+索引,确认虚拟列定义是否仍有效(如 JSON 函数返回类型变化)










