Entonces, su pregunta finalmente se reduce a "cómo java.sql.PreparedStatement
juega con PostgreSQL". Vea la respuesta sobre "cómo funciona esto con planes preparados por el servidor" al final.
Aquí está la respuesta:eso depende del controlador JDBC que use.
TL;RD :en los controladores modernos, la declaración preparada por el servidor vive hasta que la conexión muere o hasta que la declaración es desalojada por otra (desalojo LRU normal).
Nota:el servidor PostgreSQL no puede compartir declaraciones preparadas entre conexiones de bases de datos, por lo tanto, lo mejor que puede hacer el controlador JDBC es mantener el plan en caché en cada conexión.
Nota:la especificación JDBC exige el uso de ?, ?
para marcadores de posición de enlace, mientras que el servidor quiere $1, $2
por lo tanto, los controladores JDBC también almacenan en caché los llamados textos SQL analizados.
Hay dos controladores JDBC conocidos:pgjdbc y pgjdbc-ng
pgjdbc
https://github.com/pgjdbc/pgjdbc
Desde pgjdbc 9.4-1202
automáticamente almacena en caché los planes del lado del servidor cuando se usa PreparedStatement
.Nota:las declaraciones se almacenan en caché incluso si close()
la PreparedStatement
.Para llegar a la preparación del lado del servidor, debe ejecutar la consulta 5 veces (que se puede configurar a través de prepareThreshold
).
Actualmente, el caché se implementa por conexión. Por defecto pgjdbc cachea 256 (preparedStatementCacheQueries
) consultas y hasta preparedStatementCacheSizeMiB
de consultas Esta es una configuración conservadora, por lo que es posible que desee ajustarla. Ver documentación
para la descripción de las propiedades. La memoria caché incluye sentencias analizadas y preparadas por el servidor.
problema de github:https://github.com/pgjdbc/pgjdbc/pull/319
pgjdbc-ng
https://github.com/impossibl/pgjdbc-ng
No me gusta pgjdbc-ng, sin embargo, parece que analiza ambos (el tamaño de caché predeterminado es 250 consultas) y preparación del servidor (el tamaño de caché predeterminado es 50 consultas). El soporte de declaraciones preparadas del lado del servidor llegó el 24 de febrero de 2014, por lo que si usa una versión algo reciente, puede obtener el almacenamiento en caché de declaraciones.
Nota:si accidentalmente usa consultas muy largas, puede presionar OutOfMemory
ya que pgjdbc-ng no puede desalojar entradas en función de la cantidad de bytes retenidos.
El caché es por conexión, por lo que se usa de forma transparente incluso si cierra declaraciones.
No puedo decir mucho sobre el rendimiento de pgjdbc-ng, aunque desde la última vez que intenté lanzarle jmh falló con excepciones aleatorias.
problema de github:https://github.com/impossibl/pgjdbc-ng/pull/ 69
Planes preparados por el servidor
PostgreSQL tiene PREPARE
y DEALLOCATE
comandos para hacer referencia a la declaración al enviar EXEC
sobre el alambre. Optimiza dos cosas:
- Al usar
PREPARE
d (en otras palabras, uno preparado por el servidor), el cliente no tiene que enviar el texto de consulta una y otra vez. Simplemente envía un nombre de consulta corto y los valores para las variables de vinculación. - Desde 9.2, la base de datos aún intenta replanificar las primeras ejecuciones de una consulta. Lo hace para probar si la consulta necesita varios planes o si el plan genérico es lo suficientemente bueno. Eventualmente (inmediatamente si la consulta no tiene parámetros), la base de datos podría cambiar a un plan genérico .
- Desde 12, hay una configuración para forzar que TODAS las declaraciones preparadas por el servidor se ejecuten con planes genéricos o personalizados:plan_cache_mode
=
auto | force_custom_plan | force_generic_plan
En otras palabras, PreparedStatement
optimiza tanto el análisis de consultas en el lado de JDBC como la planificación de consultas en el lado de la base de datos.
Más información aquí:http://blog.endpoint .com/2014/04/custom-plans-prepared-statements-in.html
Declaraciones preparadas en PL/pgSQL
Según la documentación, PostgreSQL cachés planes para consultas utilizadas en PL/pgSQL. Esto sucede después de algunas ejecuciones (3 o 5, no recuerdo el umbral exacto), por lo que después de crear el procedimiento almacenado puede ser un poco lento, sin embargo, luego cambiará a planes almacenados en caché (siempre que la base de datos acepte usar un plan genérico para una consulta en particular).
En otras palabras, para lograr "planes de ejecución en caché", debe usar un controlador JDBC actualizado o puede envolver todas sus consultas en procedimientos almacenados. La llamada al procedimiento se volverá a planificar en cada ejecución, sin embargo, la llamada en sí es normalmente mucho más cortos que las consultas que componen el procedimiento.