sql >> Database teknologi >  >> RDS >> PostgreSQL

Hvad er levetiden for en PostgreSQL server-side forberedt erklæring

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:

  1. 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.
  2. 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 .
  3. 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.



  1. Sådan arbejder du med datofunktioner i Oracle sql

  2. MySQL:grupper efter dato RANGE?

  3. Enhver, der bruger SQL-kildekontrol fra Red Gate

  4. pandaer - Sammenfletning på strengkolonner virker ikke (fejl?)