mchange example combopooleddatasource postgresql c3p0

postgresql - example - java c3p0 timeout



¿Debo activar la agrupación de sentencias c3p0? (2)

estamos ejecutando java6 / hibernate / c3p0 / postgresql stack. Nuestro controlador JDBC es 8.4-701.jdbc3

Tengo algunas preguntas sobre declaraciones preparadas. He leído excelente documento sobre declaraciones preparadas

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

Por el momento tenemos

c3p0.maxStatements = 0 c3p0.maxStatementsPerConnection = 0

En mi entendimiento, las declaraciones preparadas y la combinación de declaraciones son dos cosas diferentes:

Nuestra pila de hibernación utiliza declaraciones preparadas. Postgresql está almacenando en caché el plan de ejecución. La próxima vez que se use la misma instrucción, postgresql reutiliza el plan de ejecución. Esto ahorra tiempo en las declaraciones de planificación dentro de DB.

Además, c3p0 puede almacenar en caché las instancias java de "java.sql.PreparedStatement", lo que significa que está almacenando en caché el objeto java. Así que cuando se usa
c3p0.maxStatementsPerConnection = 100 almacena en caché a lo sumo 100 diferentes
objetos. 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.

¿Derecha?

Como usamos alrededor de 100 declaraciones diferentes, establecería c3p0.maxStatementsPerConnection = 100

Pero los documentos c3p0 dicen en c3p0 fallas conocidas

La sobrecarga de la agrupación de instrucciones es demasiado alta. Para los controladores que no realizan un procesamiento previo significativo de PreparedStatements, la sobrecarga de la agrupación supera cualquier ahorro. Por lo tanto, la agrupación de instrucciones está desactivada de forma predeterminada. Si su controlador realiza un preprocesamiento de las declaraciones preparadas, especialmente si lo hace a través de IPC con el RDBMS, es probable que vea un aumento significativo en el rendimiento al activar la agrupación de instrucciones. (Haga esto configurando la propiedad de configuración maxStatements o maxStatementsPerConnection en un valor mayor que cero).

Entonces: ¿Es razonable activar maxStatementsPerConnection con c3p0 y Postgresql? ¿Hay un beneficio real activándolo?

Saludos cordiales Janning


No recuerdo de antemano si Hibernate realmente almacena instancias de PreparedStatement o si confía en el proveedor de la conexión para que las reutilice. (Un análisis rápido de BatcherImpl sugiere que reutiliza la última declaración preparada 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 no es útil: algunos controladores terminarán simplemente empalmando los parámetros en el lado del cliente y luego pasarán la declaración SQL construida a la base de datos de todos modos. . Para estos controladores, PreparedStatements no es una ventaja en absoluto, y se desperdicia cualquier esfuerzo para reutilizarlos. (Las preguntas frecuentes de Postgresql JDBC dicen que este fue el caso de Postgresql antes del protocolo sever versión 3 y hay información más detallada en la documentation ).

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

  • Connection.prepareStatement (sql): crea una declaración del lado del servidor
  • PreparedStatement.execute (..) etc. - ejecuta esa declaración del lado del servidor
  • PreparedStatement.close () - desasignar la declaración del lado del servidor

Dado esto, si la aplicación siempre abre una declaración preparada, la ejecuta una vez y luego la vuelve a cerrar, todavía no hay beneficio; de hecho, podría ser peor, ya que ahora hay potencialmente más viajes de ida y vuelta. Así que la aplicación necesita aferrarse a instancias de PreparedStatement. Por supuesto, esto conduce a otro problema: si la aplicación se cuelga de demasiados, y cada declaración del lado del servidor consume algunos recursos, entonces esto puede llevar a problemas del lado del servidor. En el caso de que alguien esté usando JDBC directamente, esto podría manejarse de forma manual; 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 es omitir el otro beneficio de las declaraciones preparadas: manejar el escape de argumentos)

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

Las piezas finales del rompecabezas son que los conductores de JDBC pueden decidir ser inteligentes y hacer esto; y los servidores también pueden decidir ser inteligentes y detectar a un cliente que envía una declaración que es 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 que debería reducirse la sobrecarga de las declaraciones comunes debido a la reutilización de los planes almacenados en caché). Si c3p0 no almacena en caché las declaraciones preparadas, entonces el controlador verá que la aplicación prepara una declaración, la ejecuta y luego la vuelve a cerrar. Parece que el controlador JDBC tiene una documentation para evitar la sobrecarga del servidor de preparación / ejecución en el caso donde la aplicación siempre hace esto. Entonces, sí, necesitas tener c3p0 hacer el almacenamiento en caché de la declaración.

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


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