MySQL重启后首次查询变慢是因为InnoDB缓冲池清空需从磁盘加载数据页,统计信息过期导致优化器选错索引,且关键配置未固化;解决需调大innodb_buffer_pool_size、执行ANALYZE TABLE并固化optimizer_switch。

MySQL重启后性能抖动,不是执行计划“丢了”,而是缓冲池清空、统计信息过期、或关键配置没固化——直接调大innodb_buffer_pool_size、跑一次ANALYZE TABLE、确认optimizer_switch已写入配置文件,就能压住首轮查询延迟。
为什么重启后首查特别慢?
这不是Bug,是InnoDB的正常行为:重启后innodb_buffer_pool_size内存全空,第一次查询必须从磁盘加载数据页;同时表的统计信息(cardinality)可能陈旧,优化器误判索引效率,选错执行路径。
-
Innodb_buffer_pool_pages_free在刚启动时接近总页数,说明缓存完全未预热 -
SHOW INDEX FROM t1里Cardinality列数值远低于实际行数,说明统计信息失效 - 慢查询日志中同一SQL的
Rows_examined比重启前高数倍,大概率是索引未被选中
怎么让重启后性能立刻稳住?
重点不是“记下上次的执行计划”,而是让优化器每次都有足够信息和资源做正确决策:
- 把
innodb_buffer_pool_size设为物理内存的60%~70%,并写死在my.cnf的[mysqld]段——别依赖动态SET,重启就丢 - 重启后立即执行
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插件:非官方支持,升级时极易崩溃,线上环境风险极高
- 手动保存
EXPLAIN输出再硬编码进应用:数据分布一变,静态绑定的计划反而更慢 - 指望
optimizer_use_condition_selectivity这类变量“记住上次选择”:它控制的是条件估算方式,不是计划缓存机制
真正影响重启后首查体验的,只有三件事:缓冲池大小是否够、统计信息是否新、优化器开关是否稳。执行计划本身不该、也不能被“持久化”——它本就该是实时生成的,否则数据一变,性能就崩。



















