如何使用 MySQL 准备好的语句缓存?
Posted
技术标签:
【中文标题】如何使用 MySQL 准备好的语句缓存?【英文标题】:How to use MySQL prepared statement caching? 【发布时间】:2010-09-18 07:58:25 【问题描述】:如何利用 mysql 缓存准备好的语句的能力? 使用预准备语句的一个原因是,如果要再次使用同一个预准备语句,则无需多次发送预准备语句本身。
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb" +
"?cachePrepStmts=true", "user", "pass");
for (int i = 0; i < 5; i++)
PreparedStatement ps = conn.prepareStatement("select * from MYTABLE where id=?");
ps.setInt(1, 1);
ps.execute();
conn.close()
在运行上述 Java 示例时,我在 mysqld 日志文件中看到了 5 对 Prepare 和 Execute 命令。当然,将 ps 分配移到循环之外会导致单个 Prepare 和 5 Execute 命令。连接参数“cachePrepStmts=true”在这里似乎没有任何区别。 当使用 Spring 和 Hibernate 运行类似的程序时,发送的 Prepare 命令的数量(1 或 5)取决于是否启用了 cachePrepStmts 连接参数。 Hibernate 如何执行准备好的语句以利用 cachePrepStmts 设置?是否可以使用纯 JDBC 来模拟这一点? 我在 MySQL Server 4.1.22 和 mysql-connector-java-5.0.4.jar 上运行它
【问题讨论】:
【参考方案1】:你应该在循环外准备语句。
Connection conn = DatabaseUtil.getConnection();
PreparedStatement stmtUpdate = conn.prepareStatement("UPDATE foo SET bar=? WHERE id = ?");
for(int id=0; id<10; id++)
stmtUpdate.setString(1, "baz");
stmtUpdate.setInt(2, id);
int rows = stmtUpdate.executeUpdate();
// Clear parameters for reusing the preparedStatement
stmtUpdate.clearParameters();
conn.close();
我不知道 mysql 缓存准备好的语句,但这是 JDBC 准备好的语句应该被重用的方式。
【讨论】:
【参考方案2】:您还需要在连接实例上设置语句缓存大小。我假设默认缓存大小为 0。因此不会缓存任何内容。
【讨论】:
【参考方案3】:首先,您的 PreparedStatement 在循环中重新创建,因此允许 JDBC 驱动程序丢弃准备好的数据。所以你要求丑陋的行为,所以你得到了它。
然后,MySQL 中的 PreparedStatement 是独立的一章。要获得真正的缓存,您必须通过连接属性显式请求它。
因此,您必须将“cachePrepStmts”属性设置为“true”才能缓存准备好的语句。默认情况下,该属性设置为 false。
@有关详细信息,请参阅您的 MySQL 版本的 MySQL 手册
【讨论】:
【参考方案4】:您应该只在循环之外准备一次语句,然后在循环中绑定参数。这就是准备好的语句具有绑定参数的原因——因此您可以重复使用准备好的语句。
Hibernate 正是这样做的,将所有 SQL 视为幕后准备好的语句,但如果您使用文字而不是绑定参数,您显然会滥用这一点。
【讨论】:
【参考方案5】:是否可以使用 纯 JDBC?
这实际上不是您通过将准备好的语句调用移出循环所做的吗?
我可能误解了 MySQL 缓存的工作方式,但是日志文件是否一定会报告缓存的工作?可能是 Spring 或 Hibernate 有自己的中间缓存,用于检查准备好的语句与之前发送的语句。这可能是您在使用 Spring 运行程序时所看到的。这意味着对您的系统进行一些跟踪,以查看 mysqld 日志是否只是报告它已发送的语句,而不管它如何处理它们。
【讨论】:
以上是关于如何使用 MySQL 准备好的语句缓存?的主要内容,如果未能解决你的问题,请参考以下文章