MySQL 5.7升8.0后性能下降主因是旧配置失效、新默认值不匹配及优化器因统计信息过期误判,需优先检查persisted_variables覆盖情况、optimizer_switch变更、ANALYZE TABLE刷新统计信息,并调优sort_buffer_size与innodb_buffer_pool_size。

MySQL 5.7 升级到 8.0 后 SQL 性能下降,大概率不是“变慢了”,而是旧配置失效 + 新默认值不匹配 + 优化器重新评估数据时踩了坑——直接调参数不如先查清楚谁在生效。
检查 persisted_variables 是否覆盖了你的 my.cnf
MySQL 8.0 的 PERSIST 机制会把 SET PERSIST sort_buffer_size = 64K 这类命令写入 mysqld-auto.cnf,且该文件优先级高于 my.cnf。你改了配置文件却没生效,十有八九是它在捣鬼。
- 查当前实际生效的持久化变量:
SELECT * FROM performance_schema.persisted_variables; - 看加载顺序和来源:
SELECT VARIABLE_NAME, VARIABLE_SOURCE, VARIABLE_PATH FROM performance_schema.variables_info WHERE VARIABLE_SOURCE IN ('PERSISTED', 'CONFIG'); - 临时清空(仅测试环境):
RESET PERSIST;,再重启验证是否恢复预期配置 - 别漏掉
innodb_buffer_pool_size、sort_buffer_size、optimizer_switch这几个最常被PERSIST锁死的关键项
验证 optimizer_switch 默认值是否导致执行计划跳变
MySQL 8.0 至少有 12 项 optimizer_switch 子开关默认值变了,比如 mrr=off(5.7 是 on)、index_merge=on(开启后可能拼凑单列索引,反而绕过你建好的复合索引)。
- 升级前务必存档 baseline:
SELECT @@optimizer_switch; - 升级后比对差异,重点关注带
=off的项:mrr、use_index_extensions、derived_merge - 临时验证执行路径:
SET SESSION optimizer_switch='mrr=on,use_index_extensions=on';,再跑EXPLAIN - 如果
Extra出现Using intersect()或Using union(),说明index_merge在干扰,可先关掉:SET SESSION optimizer_switch='index_merge=off';
确认统计信息是否过期导致优化器“瞎猜”
5.7 升 8.0 后,INNODB_TABLESTATS 表里的 last_update 时间仍停留在升级前,优化器就以为某张表有 10 万行,实际才 100 行——于是放弃索引,走 type: ALL。
- 查失真程度:
SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLESTATS WHERE TABLE_NAME = 'your_table';,对比SHOW INDEX FROM your_table中的Cardinality和SELECT COUNT(DISTINCT your_col) FROM your_table - 立刻修复:
ANALYZE TABLE your_table;(对所有慢查询涉及的表都执行) - 长期建议设
innodb_stats_persistent = ON,避免后续频繁失效 - 注意:若启用了
information_schema_stats_expiry(8.0 默认 3600 秒),缓存统计信息可能延迟刷新,ANALYZE TABLE是唯一强同步手段
排查 sort_buffer_size 是否触发磁盘 filesort
MySQL 8.0.20+ 彻底废弃 max_length_for_sort_data,排序策略改为全字段内存排序。只要 sort_buffer_size 不够装下“排序字段总长度 × 行数”,就必然触发磁盘 filesort——而 8.0 默认仍是 256K,但排序开销模型变了,同样值更容易溢出。
- 别盲目调大:
sort_buffer_size是 per-connection 分配的,设成 8M 并发 200 连接,光排序缓冲就吃掉 1.6GB 内存 - 更稳妥做法:先建复合索引覆盖
ORDER BY字段,再把sort_buffer_size设为 2M~4M 区间观察 - 查是否已触发磁盘排序:慢日志里看是否有
Sort_merge_passes激增,或SHOW STATUS LIKE 'Sort%';中Sort_merge_passes值持续上升 - 注意:8.0 的
read_rnd_buffer_size也影响回表性能,若EXPLAIN显示rows很小但执行慢,也要一起检查
真正卡住升级后性能的,往往不是某个参数值本身,而是多个机制叠加后的隐式行为变化:PERSIST 覆盖配置、optimizer_switch 关闭关键优化、统计信息陈旧、排序缓冲不足——这些点单独看都不致命,但一起出现时,优化器就彻底“迷路”了。



















