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 函数返回类型变化)
