mysql不提供执行计划持久化功能,重启后查询变慢的主因是缓冲池清空、统计信息过期或配置未固化;解决关键在于合理设置innodb_buffer_pool_size、定期analyze table、固化优化器参数并用force index等提示稳定执行路径。

MySQL 本身**不提供“执行计划持久化”功能**——执行计划是每次查询时由优化器动态生成的,重启后不会、也不能被固化保存。所谓“重启后查询变慢”,根本原因几乎从来不是“执行计划丢了”,而是**缓存清空、统计信息过期、或配置未持久化**导致优化器做出了次优选择。
下面直说怎么解决真问题:
为什么重启后查询突然变慢?
常见真实原因有三个:
• innodb_buffer_pool_size 太小,重启后缓存全空,首次查询要大量磁盘 IO
• 表的统计信息(cardinality)没更新,优化器误判索引区分度,选错执行路径
• query_cache 在 8.0 已移除,但旧应用若依赖它,重启后“感觉变慢”其实是缓存失效的错觉
• 会话级设置(如 optimizer_switch)没写进配置文件,重启后恢复默认值
如何让重启后查询性能稳定?
重点不是“保存执行计划”,而是让优化器每次都能做出合理决策:
- 确保
innodb_buffer_pool_size设置合理(建议设为物理内存的 50%–70%),并在my.cnf的[mysqld]段中固化,避免重启丢失 - 定期更新统计信息:
ANALYZE TABLE t1, t2;;生产环境可配合定时任务每天凌晨跑一次,或开启innodb_stats_auto_recalc=ON(默认开启,但仅在 10% 数据变更后触发) - 禁用可能导致计划波动的开关:比如
SET GLOBAL optimizer_switch='index_merge=off,index_merge_union=off';,并写入配置文件防止重启还原 - 对关键慢查询,用
FORCE INDEX或优化器提示(如/*+ USE_INDEX(t1,idx_name) */)显式约束,这类提示随 SQL 一起提交,不依赖服务端状态
哪些“计划固化”方案实际不可靠?
别踩这些坑:
-
query cache:MySQL 8.0 已彻底删除,5.7 中也默认关闭;即使开启,它缓的是结果集,不是执行计划,且极易因表变更失效 - 第三方 plan cache 插件(如某些商业版或 fork 分支):非官方支持,升级风险高,兼容性差,线上慎用
- 手动保存
EXPLAIN输出再硬编码到应用里:执行计划依赖数据分布,静态绑定反而容易在数据增长后劣化 - 指望
optimizer_use_condition_selectivity等隐藏变量“记住上次选择”:该变量控制的是条件选择率估算方式,不是计划缓存机制











