如何利用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
答案 0 :(得分:2)
是否可以模仿这个使用 纯JDBC?
这实际上不是通过将准备好的语句调用移出循环来完成的吗?
我可能误解了MySQL缓存的工作方式,但日志文件是否必须报告缓存的工作?可能是Spring或Hibernate有自己的中间缓存,它会根据之前发送的语句检查预准备语句。可能是您在使用Spring运行程序时看到的。这意味着要对你的系统进行一些跟踪,看看mysqld日志是否只是报告它发送的语句,而不管它是如何处理它们的。
答案 1 :(得分:2)
您应该只在循环之外准备一次语句,然后在循环中绑定参数。这就是预准备语句具有绑定参数的原因 - 因此您可以重用已准备好的语句。
Hibernate就是这样做的,将所有SQL视为幕后准备好的语句,但如果你使用文字而不是绑定参数,你很明显会滥用它。
答案 2 :(得分:2)
您还需要在连接实例上设置语句缓存大小。我假设默认缓存大小为0.因此不会缓存任何内容。
答案 3 :(得分:1)
首先,在循环中重新创建PreparedStatement,因此允许JDBC驱动程序丢弃准备好的数据。所以你问了丑陋的行为,所以你得到了它。
然后,MySQL中的PreparedStatement就是一个章节。要进行真正的缓存,您必须通过连接属性显式请求它。
因此,您必须将“cachePrepStmts”属性设置为“true”才能在预准备语句上进行缓存。默认情况下,该属性设置为false。
@查看MySQL版本的MySQL手册了解详情
答案 4 :(得分: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预处理语句应该被重用的方式。