要让 MySQL 服务端真正缓存预编译语句,必须同时启用 useServerPrepStmts=true、cachePrepStmts=true 和 prepStmtCacheSize=250(推荐值),并配合固定 SQL 模板复用 PreparedStatement 对象。

要让 MySQL 在服务端真正缓存预编译语句(即 PreparedStatement),不能只靠 Java 侧调用 prepareStatement(),关键得在 JDBC 连接层通过驱动参数协同控制。MySQL Connector/J 驱动本身不缓存语句,它依赖服务端预编译 + 客户端缓存机制配合生效。
必须同时启用三个核心参数
useServerPrepStmts=true
启用后,驱动会把PreparedStatement请求发给 MySQL 服务端做真实预编译(生成执行计划并缓存),而不是在客户端模拟(默认行为)。这是服务端缓存的前提。cachePrepStmts=true
开启客户端对PreparedStatement对象的复用缓存——避免反复创建、销毁 Statement 实例,减少开销;它和useServerPrepStmts是配套关系,单独开启无效。prepStmtCacheSize=250(推荐值)
显式指定缓存多少个预编译语句对象,默认是 25。如果应用中高频使用几十种不同 SQL 模板(如带不同 where 条件的查询),建议设为 100–500。prepStmtCacheSqlLimit=2048(可选)
控制缓存的 SQL 长度上限(单位:字符),避免长 SQL 占满缓存。默认 256,复杂语句建议调大。
连接 URL 示例(完整写法)
jdbc:mysql://localhost:3306/mydb? useServerPrepStmts=true& cachePrepStmts=true& prepStmtCacheSize=250& prepStmtCacheSqlLimit=2048& useSSL=false& serverTimezone=UTC
代码侧配合要点
立即学习“Java免费学习笔记(深入)”;
- 使用
Connection.prepareStatement(sql)创建语句,且 SQL 模板固定(占位符?位置/数量不变) - 同一连接内重复使用相同模板的
PreparedStatement,驱动才会命中缓存 - 不要每次执行都
close()再prepareStatement(),应复用对象(尤其在循环或连接池场景) - 若用 HikariCP 等连接池,确保池配置允许语句复用(默认支持)
验证是否生效的小技巧
在 MySQL 服务端执行:
SHOW STATUS LIKE 'Com_stmt_prepare'; SHOW STATUS LIKE 'Com_stmt_execute';
批量操作前后对比,若 Com_stmt_prepare 增长缓慢而 Com_stmt_execute 大幅上升,说明预编译已缓存并复用。
不复杂但容易忽略



















