2010-05-27 13 views
17

estamos ejecutando la pila java6/hibernate/c3p0/postgresql. Nuestro controlador JDBC es 8.4-701.jdbc3¿debo activar la agrupación de declaraciones c3p0?

Tengo algunas preguntas sobre Declaraciones preparadas. He leído documento excelente sobre Prepared Statements

Pero todavía tengo una pregunta sobre cómo configurar c3p0 con postgresql.

En el momento en que tienen

c3p0.maxStatements = 0 
c3p0.maxStatementsPerConnection = 0 

A mi entender las declaraciones preparadas y puesta en común afirmación son dos cosas diferentes:

Nuestra pila Hibernate usa comandos preparados. Postgresql está almacenando en caché el plan de ejecución . La próxima vez que se use la misma declaración, postgresql reutilizará el plan de ejecución . Esto ahorra tiempo en las declaraciones de planificación dentro de DB.

Además, c3p0 puede almacenar en caché instancias Java de "java.sql.PreparedStatement" , lo que significa que está almacenando en caché el objeto java. Por lo tanto, cuando se usa
c3p0.maxStatementsPerConnection = 100 almacena en caché como máximo 100 objetos diferentes
. Ahorra tiempo en la creación de objetos, pero esto no tiene nada que ver con la base de datos postgresql y sus declaraciones preparadas.

Derecho?

Como usamos unos 100 estados diferentes Fijaría c3p0.maxStatementsPerConnection = 100

Pero los documentos c3p0 decir en c3p0 known shortcomings

La sobrecarga de la Declaración de la agrupación es demasiado alto. Para los controladores que no realizan preprocesamiento significativo de PreparedStatements, la agrupación compensa cualquier ahorro. La agrupación de instrucciones se desactiva por lo tanto de forma predeterminada. Si su controlador hace preprocess PreparedStatements, especialmente si lo hace a través de IPC con el RDBMS, probablemente verá una ganancia de rendimiento significativa de en activando la agrupación de sentencias. (Haga esto estableciendo la propiedad de configuración maxStatements o maxStatementsPerConnection en un valor mayor que cero).

Entonces: ¿Es razonable activar maxStatementsPerConnection con c3p0 y Postgresql? ¿Existe un beneficio real al activarlo?

Saludos cordiales Janning

Respuesta

23

No recuerdo si la ligera Hibernate realmente almacena casos PreparedStatement mismo, o se basa en el proveedor de la conexión a volver a utilizarlos.(Un análisis rápido de BatcherImpl sugiere que reutiliza el último PreparedStatement si se ejecuta el mismo SQL varias veces seguidas)

Creo que el punto que la documentación de c3p0 está tratando de hacer es que para muchos controladores JDBC, un PreparedStatement isn ' t útil: algunos controladores terminarán simplemente empalmando los parámetros en el lado del cliente y pasando la declaración SQL incorporada a la base de datos de todos modos. Para estos controladores, los estados preparados no son una ventaja en absoluto, y se desperdicia cualquier esfuerzo por reutilizarlos. (El Postgresql JDBC FAQ dice que este fue el caso de Postgresql antes del protocolo de corte versión 3 y que hay información más detallada en el documentation).

Para los controladores que manejan de manera útil los estados preparados, es probable que sea necesario reutilizar las instancias de PreparedStatement para obtener algún beneficio. Por ejemplo, si el controlador implementa:

  • Connection.prepareStatement (SQL) - crear una declaración del lado del servidor
  • PreparedStatement.execute (..), etc - ejecutar esa declaración del lado del servidor
  • PreparedStatement.close() - desasignar la declaración del lado del servidor

Teniendo en cuenta esto, si la aplicación se abre siempre una declaración preparada, ejecuta una vez y luego se cierra de nuevo, hay todavía ningún beneficio; de hecho, podría ser peor ya que ahora hay potencialmente más viajes de ida y vuelta. Entonces, la aplicación necesita atenerse a las instancias de PreparedStatement. Por supuesto, esto lleva a otro problema: si la aplicación se atasca en demasiadas, y cada sentencia del lado del servidor consume algunos recursos, esto puede generar problemas en el servidor. En el caso de que alguien esté usando JDBC directamente, esto podría ser manejado a mano: se sabe que algunas declaraciones son reutilizables y, por lo tanto, están preparadas; algunos no lo son y solo usan instancias transitorias de Statement. (Esto se saltea el otro beneficio de las declaraciones preparadas: manejo del argumento de escape)

Por eso, c3p0 y otras agrupaciones de conexiones también tienen cachés de declaraciones preparados, lo que permite que el código de la aplicación evite todo esto. Las declaraciones generalmente se guardan en un grupo de LRU limitado, por lo que las declaraciones comunes reutilizan una instancia de PreparedStatement.

Las piezas finales del rompecabezas son que los controladores JDBC pueden decidir ser inteligentes y hacer esto; y los servidores también pueden decidir ser inteligentes y detectar a un cliente que presente una declaración estructuralmente similar a la anterior.

Dado que Hibernate no mantiene un caché de instancias de PreparedStatement, debe hacer que c3p0 haga eso para obtener el beneficio de ellas. (Lo cual debería reducirse en gastos generales para declaraciones comunes debido a la reutilización de planes en caché). Si c3p0 no almacena en caché las declaraciones preparadas, entonces el controlador solo verá la aplicación preparando una declaración, ejecutándola y luego cerrándola de nuevo. Parece que el controlador JDBC tiene un "threshold" setting para evitar la sobrecarga del servidor de preparación/ejecución en el caso en que la aplicación siempre hace esto. Entonces, sí, necesitas tener c3p0 do caching de declaración.

Espero que ayude, lo siento, es un poco largo aliento. La respuesta es .

+1

¡¡Gran respuesta !! Con su explicación detallada, pude realizar algunas pruebas. De hecho: es razonable activar el agrupamiento de declaraciones c3p0. antes de que mis declaraciones fueran analizadas y planificadas cada vez, ahora solo se enlazan y se ejecutan. , pero tenga en cuenta si su cambio de datos y los planes antiguos no funcionan óptimamente. Todavía no sé si postgresql replans preparedtestements de vez en cuando. ¡Muchas gracias por su ayuda! – Janning

+0

¡Excelente respuesta! En realidad, siempre estoy confundido acerca de la implementación de PreparedStatement y sus beneficios son sospechosos como todos me dijeron. – Chao

2

Recuerde que las declaraciones deben almacenarse en caché por conexión lo que significa que tendrá que consumir una gran cantidad de memoria y pasará mucho tiempo antes de que vea algún beneficio. Entonces, si lo configura para usar 100 declaraciones para almacenar en caché, en realidad son 100 * número de conexiones o 100/no de conexiones, pero aún necesitará tomar bastante tiempo hasta que su caché tenga un efecto significativo.

Cuestiones relacionadas