CREATE PROCEDURE本身不自动提升性能,仅在满足静态SQL、高频调用、网络延迟高、多语句事务等全部条件时才可能提速;其“预编译”实为首次解析与执行计划缓存,非永久字节码,且MySQL 8.0已移除查询缓存,仅缓存执行计划。
CREATE PROCEDURE 本身不带来自动性能提升,所谓“预编译提速”只在特定条件下成立——它省掉的是首次调用时的语法解析和语义检查开销,后续调用复用的是执行计划缓存(plan cache),而非“编译结果”。MySQL 8.0 的执行计划缓存是语句级的,不是过程级的。
很多人误以为存储过程像 C 函数一样“编译一次、永久运行”。实际上:
PROCEDURE 生成机器码或中间字节码;所谓“预编译”仅指首次 CALL 时完成 SQL 解析、权限校验、对象存在性检查,并为其中每条语句生成执行计划(plan)WHERE id = @v),优化器无法准确估算选择性,常弃用索引——此时“预编译”毫无意义,每次执行都可能走全表扫描只有满足以下全部条件时,你才可能观察到明显提速:
SELECT * FROM users WHERE status = 'active'
BEGIN; INSERT; UPDATE; COMMIT;),避免客户端多次 round-tripPDO::prepare() + 绑定参数执行相同逻辑”现代应用层普遍使用连接池和预编译接口,已吸收大部分“解析/传输”开销。此时存储过程反而引入新瓶颈:
EXPLAIN 无法直接分析 CALL proc_name(),必须拆出内部语句单独测试——而多数人跳过这步,误把慢 SQL 归咎于“存储过程太重”DECLARE CURSOR 或 WHILE 循环处理数据,实际是单行迭代,比客户端批量拉取再处理更慢真正影响快慢的从来不是“有没有预编译”,而是那条最慢的 SELECT 是否命中索引、是否触发磁盘排序、是否被锁住——这些细节藏在过程内部,不挖出来看 EXPLAIN FORMAT=TREE 就永远找不到根因。