2008-10-21 32 views
8

如何利用MySQL緩存預準備語句的能力? 使用預處理語句的一個原因是,如果再次使用相同的預處理語句,則不需要多次發送預處理語句本身。如何使用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服務器4.1.22和MySQL連接器的Java-5.0.4.jar

回答

2

上運行這是否有可能模仿這種用純 JDBC?

這實際上不是你通過將準備好的語句調用移出循環而完成的嗎?

我可能會誤解MySQL緩存的工作方式,但日誌文件是否必須報告緩存的工作? Spring或Hibernate可能有自己的中間緩存,用於檢查預先準備好的語句與之前發送的語句。這可能是你在用Spring運行程序時看到的。這意味着要對系統進行一些跟蹤,以查看mysqld日誌是否只是報告已發送的語句,而不管它如何處理它們。

2

您應該只在循環之外準備好語句一次,然後在循環中綁定參數。這就是準備好的語句綁定參數的原因 - 因此您可以重新使用準備好的語句。

Hibernate確實做到了這一點,將所有SQL視爲幕後準備好的語句,儘管如果使用文本而不是綁定參數,顯然可能會濫用這一點。

1

首先,您的PreparedStatement是在循環中重新創建的,因此允許JDBC驅動程序放棄準備好的數據。所以你要求醜陋的行爲,所以你明白了。

然後,MySQL中的PreparedStatement是它自己的一章。要有真正的緩存,你必須通過連接屬性明確地請求它。

因此,您必須將「cachePrepStmts」屬性設置爲「true」才能在預準備語句中獲得緩存。默認情況下,該屬性設置爲false。

@請參閱MySQL版本的MySQL手冊瞭解詳細信息

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.因此沒有任何內容會被緩存。