Så dit spørgsmål koger endelig ned til "hvordan java.sql.PreparedStatement
spiller med PostgreSQL". Se svar på "hvordan det spiller med serverforberedte planer" til sidst.
Her er svaret:det afhænger af den JDBC-driver du bruger.
TL;DR :i moderne drivere lever server-forberedt erklæring, indtil forbindelsen dør, eller indtil erklæringen er smidt ud af en anden (almindelig LRU-udsættelse).
Bemærk:PostgreSQL-serveren kan ikke dele forberedt sætning på tværs af databaseforbindelser, så den bedste JDBC-driver kan gøre er at holde planen cachelagret i hver forbindelse.
Bemærk:JDBC-specifikationen kræver brug af ?, ?
for bind-pladsholdere, mens serveren vil have $1, $2
således cacher JDBC-drivere også såkaldte parsede SQL-tekster.
Der er to velkendte JDBC-drivere:pgjdbc og pgjdbc-ng
pgjdbc
https://github.com/pgjdbc/pgjdbc
Siden pgjdbc 9.4-1202
den cacher automatisk planer på serversiden, når du bruger PreparedStatement
.Bemærk:sætningerne cachelagres, selvom du close()
PreparedStatement
.For at komme til forberedelse på serversiden skal du udføre forespørgslen 5 gange (der kan konfigureres via prepareThreshold
).
I øjeblikket implementeres cachen pr. forbindelse. Som standard pgjdbc caches 256 (preparedStatementCacheQueries
) forespørgsler og op til preparedStatementCacheSizeMiB
af forespørgsler. Dette er en konservativ indstilling, så du vil måske justere den. Se dokumentation
for beskrivelse af egenskaber. Cachen omfatter både parsede og server-forberedte sætninger.
github problem:https://github.com/pgjdbc/pgjdbc/pull/319
pgjdbc-ng
https://github.com/impossibl/pgjdbc-ng
Jeg er ikke til pgjdbc-ng, men det ser ud til, at det både parser (standard cachestørrelse er 250 forespørgsler) og server-forberedelse (standard cache-størrelse er /a> forespørgsler). Understøttelsen af forberedte erklæringer på serversiden landede den 24. februar 2014, så hvis du bruger en lidt nyere version, kan du få sætningscache.
Bemærk:Hvis du ved et uheld bruger meget lange forespørgsler, kan du trykke OutOfMemory
da pgjdbc-ng ikke kan fjerne poster baseret på antallet af bevarede bytes.
Cachen er per-forbindelse, så den bruges transparent, selvom du lukker sætninger.
Jeg kan ikke sige meget om pgjdbc-ng ydeevne, men siden sidste gang jeg prøvede at kaste jmh på det, mislykkedes det med tilfældige undtagelser.
github problem:https://github.com/impossibl/pgjdbc-ng/pull/ 69
Serverforberedte planer
PostgreSQL har PREPARE
og DEALLOCATE
kommandoer til at referere til sætningen, når du sender EXEC
over ledningen. Det optimerer to ting:
- Når du bruger
PREPARE
d-sætning (med andre ord server-forberedt), behøver klienten ikke at sende forespørgselstekst igen og igen. Den sender bare et kort forespørgselsnavn og værdierne for bindevariabler. - Siden 9.2 forsøger databasen stadig at omplanlægge de første par udførelser af en forespørgsel. Det gør det for at prøve, om forespørgslen har brug for flere planer, eller om den generiske plan er god nok. Til sidst (umiddelbart hvis forespørgslen ikke har nogen parametre), databasen kan skifte til en generisk plan .
- Siden 12 har der været en indstilling til at tvinge ALLE serverforberedte sætninger til at blive udført med generiske eller tilpassede planer:plan_cache_mode
=
auto | force_custom_plan | force_generic_plan
Med andre ord, PreparedStatement
optimerer både forespørgselsparsing på JDBC-siden og forespørgselsplanlægning på databasesiden.
Mere info her:http://blog.endpoint .com/2014/04/custom-plans-prepared-statements-in.html
Forberedte udsagn i PL/pgSQL
I henhold til dokumentationen cacher PostgreSQL planer for forespørgsler brugt i PL/pgSQL. Dette sker efter et par henrettelser (3 eller 5, jeg kan ikke huske den nøjagtige tærskel), så efter at du har oprettet en lagret procedure, kan den være lidt langsom, men så vil den skifte til cachelagrede planer (forudsat at databasen accepterer at bruge generisk plan for en bestemt forespørgsel).
Med andre ord for at opnå "cachede eksekveringsplaner", skal du enten bruge en opdateret JDBC-driver, eller du kan pakke alle dine forespørgsler ind i lagrede procedurer. Call to-proceduren planlægges igen ved hver eksekvering, men selve opkaldet er typisk meget kortere end forespørgsler, der udgør proceduren.