8

プリペアド ステートメントをキャッシュする MySQL の機能を利用するにはどうすればよいですか? 準備済みステートメントを使用する理由の 1 つは、同じ準備済みステートメントを再度使用する場合に、準備済みステートメント自体を複数回送信する必要がないことです。

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 割り当てをループの外に移動すると、もちろん、1 つの 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で実行していました

4

5 に答える 5

3

ステートメントをループの外側で 1 回だけ準備してから、ループ内でパラメーターをバインドする必要があります。これが、プリペアド ステートメントにバインド パラメータがある理由です。つまり、プリペアド ステートメントを再利用できます。

Hibernate はまさにこれを行い、すべての SQL を舞台裏で準備済みステートメントとして扱いますが、バインド パラメータではなくリテラルを使用すると、明らかにこれを悪用できます。

于 2008-10-21T15:03:21.603 に答える
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

また、接続インスタンスでステートメントキャッシュサイズを設定する必要があります。デフォルトのキャッシュサイズは0だと思います。したがって、何もキャッシュされません。

于 2010-02-04T20:06:18.713 に答える
2

純粋な JDBC を使用してこれを模倣することは可能ですか?

これは実際には、準備されたステートメントの呼び出しをループの外に移動することによって行ったことではありませんか?

MySQL キャッシュの仕組みを誤解しているかもしれませんが、ログ ファイルはキャッシュの動作を報告する必要がありますか? Spring または Hibernate には、事前に送信されたステートメントに対して準備されたステートメントをチェックする独自の中間キャッシュがある可能性があります。Spring でプログラムを実行すると、それが表示される可能性があります。これは、システムを少しトレースして、mysqld ログが送信されたステートメントを報告しているだけであるかどうかを確認することを意味します。

于 2008-10-21T14:29:26.523 に答える
1

まず、PreparedStatement がループ内で再作成されるため、JDBC ドライバーは準備されたデータを破棄できます。だからあなたは醜い振る舞いを求めたので、あなたはそれを手に入れました。

そして、MySQL の PreparedStatement はそれ自体が 1 つの章です。実際のキャッシングを行うには、接続プロパティを介して明示的にリクエストする必要があります。

したがって、準備済みステートメントでキャッシュを取得するには、「cachePrepStmts」プロパティを「true」に設定する必要があります。デフォルトでは、そのプロパティは false に設定されています。

@詳細については、MySQL バージョンの MySQL マニュアルを参照してください

于 2008-10-22T00:30:40.897 に答える