不是。MySQL存储过程无编译缓存,ALTER PROCEDURE仅更新元数据,不重建执行计划;变慢主因是优化器行为变化、统计信息陈旧或变量传参导致计划复用失效,须用EXPLAIN分析关键语句、ANALYZE TABLE更新统计、必要时用RECOMPILE提示或PREPARE动态执行。

存储过程没有“编译缓存”,别白费劲 ALTER PROCEDURE
MySQL 存储过程不生成可执行二进制码,ALTER PROCEDURE 只更新元数据(比如注释、参数名),完全不会触发执行计划重建或优化器重评估。升级后变慢,不是因为“没重编译”,而是优化器行为变了、统计信息旧了、或者默认配置调整了。
常见错误现象:看到慢了就下意识 ALTER PROCEDURE xxx ...,再反复 CALL 测试,结果毫无改善;甚至误以为是“过程被缓存了旧计划”,试图杀连接清缓存——MySQL 没有存储过程级的计划缓存。
- 真正影响首次调用性能的是语句解析 + 优化器决策,这部分开销在第一次执行时发生,之后复用的是单条 SQL 的查询计划(不是整个过程)
- 若过程内含动态拼接(
PREPARE/EXECUTE),每次都会重新解析,这才是真正的“重复编译”点 - 检查是否真有编译类开销,可对比
SHOW PROFILE FOR QUERY N中的Creating sort index、executing和end阶段耗时,而非盯着“parse”阶段
先看执行计划,再动参数:EXPLAIN 是唯一可信依据
存储过程里每条 SELECT、UPDATE、DELETE 都独立走优化器,执行计划可能因传入变量值不同而彻底改变。必须对过程内关键语句单独 EXPLAIN,不能只看 CALL 整体耗时。
使用场景:升级 MySQL 5.7 → 8.0 后,同一存储过程变慢,但 EXPLAIN 显示走了 HASH JOIN 或用了直方图估算,和之前 NESTED LOOP 完全不同。
- 用
EXPLAIN FORMAT=TREE(8.0)或EXPLAIN FORMAT=JSON(5.7+)看真实执行路径,重点关注join_execution和used_columns - 在过程内模拟参数值:比如
SET @p_status = 'done'; SELECT ... WHERE status = @p_status;,再EXPLAIN,避免被变量掩盖选择率 - 临时关闭可疑特性验证影响:
SET SESSION optimizer_switch='hash_join=off';,再CALL测试,确认是否是某开关导致计划劣化
统计信息陈旧是头号杀手,ANALYZE TABLE 必须手动跑
升级后最常被忽略的动作:没手动执行 ANALYZE TABLE。InnoDB 的统计信息不会自动刷新到足够精度,尤其当表数据量大、分布倾斜时,优化器会严重误判行数,导致选错索引、用错 JOIN 顺序——这对含多表关联的存储过程几乎是致命的。
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
容易踩的坑:用 OPTIMIZE TABLE 代替 ANALYZE TABLE;或全库扫表执行 mysqlcheck --analyze,引发长锁阻塞业务。
- 对存储过程中高频访问的表逐个执行:
ANALYZE TABLE orders, customers, order_items; - 确认
innodb_stats_auto_recalc=ON(5.6.6+ 默认开启),但升级后首次仍需手动触发,否则优化器基于旧采样做决策 - 低峰执行:5.7 中
ANALYZE TABLE是阻塞操作;8.0+ 支持并发采样,但仍建议避开流量高峰
变量传参导致计划复用失效,小心“伪缓存”陷阱
MySQL 没有参数化嗅探(parameter sniffing),存储过程中用变量(如 WHERE status = p_status)时,优化器在**首次调用时基于该变量具体值**生成并缓存计划。后续即使传入高基数、低选择率的值,也继续复用那个“过时”的计划——看起来像缓存,实则是隐患。
典型表现:第一次传 p_status = 'pending'(10% 行),走了索引;第二次传 p_status = 'done'(95% 行),还硬走索引,全表扫描都比它快。
- 强制重生成计划:在关键查询前加
SELECT /*+ RECOMPILE */ ...(8.0.22+);或改用PREPARE/EXECUTE动态构造语句(注意注入风险) - 更稳妥做法:把高频变化的条件拆成多个专用过程,或用
CASE WHEN在 SQL 内部分支,让优化器能为各分支生成不同计划 - 监控是否中招:查
performance_schema.events_statements_summary_by_digest,看同一 digest 的avg_timer_wait是否波动极大
真正卡住性能的,往往不是语法写得有多错,而是统计信息滞后、执行计划固化、变量值误导这三者叠加。动手前先 EXPLAIN 关键语句,再 ANALYZE TABLE,最后看变量怎么传——顺序错了,调一天也白搭。


















