Quindi, la tua domanda si riduce finalmente a "come java.sql.PreparedStatement
gioca con PostgreSQL". Vedi alla fine la risposta su "come funziona con i piani preparati dal server".
Ecco la risposta:dipende dal driver JDBC che usi.
TL;DR :nei driver moderni l'istruzione preparata dal server dura fino a quando la connessione si interrompe o fino a quando l'istruzione non viene eliminata da un'altra (eliminazione regolare di LRU).
Nota:il server PostgreSQL non può condividere l'istruzione preparata tra le connessioni al database, quindi il miglior driver JDBC che può fare è mantenere il piano memorizzato nella cache in ogni connessione.
Nota:le specifiche JDBC impongono l'utilizzo di ?, ?
per i segnaposto bind, mentre il server vuole $1, $2
quindi i driver JDBC memorizzano nella cache anche i cosiddetti testi SQL analizzati.
Esistono due noti driver JDBC:pgjdbc e pgjdbc-ng
pgjdbc
https://github.com/pgjdbc/pgjdbc
Poiché pgjdbc 9.4-1202
memorizza automaticamente nella cache i piani lato server quando si utilizza PreparedStatement
.Nota:le istruzioni vengono memorizzate nella cache anche se close()
il PreparedStatement
.Per accedere alla preparazione lato server, è necessario eseguire la query 5 volte (che può essere configurata tramite prepareThreshold
).
Attualmente, la cache è implementata per connessione. Per impostazione predefinita pgjdbc memorizza nella cache 256 (preparedStatementCacheQueries
) e fino a preparedStatementCacheSizeMiB
di interrogazioni. Questa è un'impostazione conservativa, quindi potresti volerla regolare. Consulta la documentazione
per la descrizione delle proprietà. La cache include istruzioni analizzate e preparate dal server.
problema github:https://github.com/pgjdbc/pgjdbc/pull/319
pgjdbc-ng
https://github.com/imossibl/pgjdbc-ng
Non mi piace pgjdbc-ng, tuttavia sembra che esegua entrambe le analisi (la dimensione predefinita della cache è 250 query) e la preparazione del server (la dimensione predefinita della cache è 50 interrogazioni). Il supporto delle istruzioni preparate lato server è arrivato il 24 febbraio 2014, quindi se utilizzi una versione piuttosto recente, puoi ottenere la memorizzazione nella cache delle istruzioni.
Nota:se utilizzi accidentalmente query molto lunghe, puoi premere OutOfMemory
poiché pgjdbc-ng non può eliminare le voci in base al numero di byte conservati.
La cache è per connessione, quindi viene utilizzata in modo trasparente anche se chiudi le istruzioni.
Non posso dire molto sulle prestazioni di pgjdbc-ng anche se dall'ultima volta che ho provato a lanciare jmh non è riuscito con eccezioni casuali.
problema github:https://github.com/imossibl/pgjdbc-ng/pull/ 69
Piani preparati per il server
PostgreSQL ha PREPARE
e DEALLOCATE
comandi per fare riferimento all'istruzione durante l'invio di EXEC
sopra il filo. Ottimizza due cose:
- Quando si utilizza
PREPARE
d (in altre parole, preparata dal server), il client non deve inviare ripetutamente il testo della query. Invia solo un breve nome di query e i valori per le variabili di collegamento. - Dalla versione 9.2, il database tenta ancora di riprogrammare le prime esecuzioni di una query. Lo fa per provare se la query necessita di più piani o se il piano generico è abbastanza buono. Eventualmente (immediatamente se la query non ha parametri), il database potrebbe passare a un piano generico .
- Dal 12, esiste un'impostazione per forzare l'esecuzione di TUTTE le istruzioni preparate dal server con piani generici o personalizzati:plan_cache_mode
=
auto | force_custom_plan | force_generic_plan
In altre parole, PreparedStatement
ottimizza sia l'analisi delle query sul lato JDBC che la pianificazione delle query sul lato database.
Maggiori informazioni qui:http://blog.endpoint .com/2014/04/custom-plans-prepared-statements-in.html
Dichiarazioni preparate in PL/pgSQL
Come da documentazione, PostgreSQL cache piani per le query utilizzate in PL/pgSQL. Questo accade dopo alcune esecuzioni (3 o 5, non ricordo la soglia esatta), quindi dopo aver creato la stored procedure potrebbe essere un po' lenta, tuttavia passerà ai piani memorizzati nella cache (a condizione che il database accetti di utilizzare un piano generico per una domanda particolare).
In altre parole, per ottenere "piani di esecuzione memorizzati nella cache", è necessario utilizzare un driver JDBC aggiornato oppure è possibile eseguire il wrapping di tutte le query in procedure memorizzate. La chiamata alla procedura verrà ripianificata ad ogni esecuzione, tuttavia la chiamata stessa è in genere molto più brevi delle query che compongono la procedura.