8

How do i take advantage of MySQL's ability to cache prepared statements? One reason to use prepared statements is that there is no need to send the prepared statement itself multiple times if the same prepared statement is to be used again.

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()

When running the above Java example I see 5 pairs of Prepare and Execute commands in the mysqld log file. Moving the ps assignment outside of the loop results in a single Prepare and 5 Execute commands of course. The connection parameter "cachePrepStmts=true" doesn't seem to make any difference here.
When running a similar program using Spring and Hibernate the number of Prepare commands sent (1 or 5) depends on whether the cachePrepStmts connection parameter is enabled. How does Hibernate execute prepared statements to take advantage of the cachePrepStmts setting? Is it possible to mimic this using pure JDBC?
I was running this on MySQL Server 4.1.22 and mysql-connector-java-5.0.4.jar

4

5 回答 5

3

您应该只在循环之外准备一次语句,然后在循环中绑定参数。这就是准备好的语句具有绑定参数的原因——因此您可以重用准备好的语句。

Hibernate 正是这样做的,将所有 SQL 视为幕后准备好的语句,尽管如果您使用文字而不是绑定参数,您显然会滥用这一点。

于 2008-10-21T15:03:21.603 回答
2

您还需要在连接实例上设置语句缓存大小。我假设默认缓存大小为 0。因此不会缓存任何内容。

于 2010-02-04T20:06:18.713 回答
2

您应该在循环外准备语句。

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 准备好的语句应该被重用的方式。

于 2008-12-17T12:17:16.517 回答
2

Is it possible to mimic this using pure JDBC?

Is this not in fact what you've done by moving your prepared statement call out of the loop?

I may be misunderstanding the way the MySQL cache works, but does the log file necessarily report the cache's work? It may be that Spring or Hibernate has its own intermediate cache that checks the prepared statements against those sent earlier. It might be that that you're seeing when you run the program with Spring. That would mean doing a bit of tracing with your system to see if the mysqld log is just reporting the statements it's been sent, regardless of how it deals with them.

于 2008-10-21T14:29:26.523 回答
1

首先,您的 PreparedStatement 在循环中重新创建,因此允许 JDBC 驱动程序丢弃准备好的数据。所以你要求丑陋的行为,所以你得到了它。

然后,MySQL 中的 PreparedStatement 是独立的一章。要获得真正的缓存,您必须通过连接属性显式请求它。

因此,您必须将“cachePrepStmts”属性设置为“true”才能缓存准备好的语句。默认情况下,该属性设置为 false。

@查看你的 MySQL 版本的 MySQL 手册以获取详细信息

于 2008-10-22T00:30:40.897 回答