2008-10-21 11 views
8

¿Cómo aprovecho la capacidad de MySQL para almacenar en caché las declaraciones preparadas? Una razón para usar declaraciones preparadas es que no es necesario enviar la declaración preparada muchas veces si la misma declaración preparada se va a usar nuevamente.¿Cómo usar el almacenamiento en caché de sentencias preparadas de 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() 

Al ejecutar el ejemplo anterior de Java veo 5 pares de preparar y ejecutar comandos en el archivo de registro mysqld. Al mover la asignación ps fuera del bucle, se obtienen, por supuesto, los comandos Preparar y 5 Ejecutar. El parámetro de conexión "cachePrepStmts = true" no parece hacer ninguna diferencia aquí.
Al ejecutar un programa similar utilizando Spring e Hibernate, el número de comandos de preparación enviados (1 o 5) depende de si el parámetro de conexión cachePrepStmts está habilitado. ¿Cómo ejecuta Hibernate las declaraciones preparadas para aprovechar la configuración de cachePrepStmts? ¿Es posible imitar esto usando JDBC puro?
yo estaba corriendo en este servidor MySQL 4.1.22 y MySQL-conector-java-5.0.4.jar

Respuesta

2

¿Es posible imitar este usando JDBC puro?

¿No es esto, de hecho, lo que ha hecho al mover su llamada de declaración preparada fuera del ciclo?

Es posible que esté malinterpretando la forma en que funciona la memoria caché de MySQL, pero ¿el archivo de registro necesariamente informa el trabajo de la caché? Puede ser que Spring o Hibernate tengan su propio caché intermedio que verifique las declaraciones preparadas contra las enviadas anteriormente. Puede ser que estés viendo cuando ejecutas el programa con Spring. Eso significaría rastrear un poco con su sistema para ver si el registro de mysqld solo está informando sobre las declaraciones que se han enviado, independientemente de cómo se maneje.

2

Debe preparar su resumen solo una vez, fuera del ciclo, y luego vincular los parámetros en el ciclo. Esta es la razón por la cual las declaraciones preparadas tienen parámetros de enlace, por lo que puede reutilizar la declaración preparada.

Hibernate hace exactamente esto, tratando todo SQL como una declaración preparada detrás de escena, aunque obviamente puede abusar de esto si usa parámetros literales en lugar de obligar.

1

En primer lugar, su PreparedStatement se vuelve a crear en el ciclo, por lo que el controlador JDBC puede descartar los datos preparados. Entonces preguntaste por el comportamiento feo, y entonces lo obtuviste.

Y luego, PreparedStatement en MySQL es un capítulo en sí mismo. Para tener un almacenamiento en caché real, debe solicitarlo explícitamente a través de una propiedad de conexión.

Por lo tanto, debe establecer la propiedad "cachePrepStmts" en "true" para obtener el almacenamiento en caché de las declaraciones preparadas. Por defecto, esa propiedad se establece en falso.

@see el manual de MySQL para su versión de MySQL para obtener detalles

1

Debe preparar la declaración fuera del bucle.

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

no sé acerca de las declaraciones preparadas de MySQL de almacenamiento en caché, pero esta es la forma de JDBC preparado se supone declaraciones para ser reutilizado.

2

También necesita establecer el tamaño de caché de sentencia en la instancia de conexión. Supongo que el tamaño de caché predeterminado es 0. Por lo tanto, nada se almacenará en caché.

Cuestiones relacionadas