sql >> Databasteknik >  >> RDS >> PostgreSQL

Vad är livslängden för en PostgreSQL-server-side-förberedd uttalande

Så din fråga kokar äntligen ner till "hur java.sql.PreparedStatement spelar med PostgreSQL". Se svaret på "hur det här spelar med serverförberedda planer" i slutet.

Här är svaret:det beror på vilken JDBC-drivrutin du använder.

TL;DR :i moderna drivrutiner lever serverförberedda uttalanden tills anslutningen dör eller tills uttalandet vräkts av en annan (vanlig LRU-vräkning).

Obs:PostgreSQL-servern kan inte dela förberedda uttalanden över databasanslutningar, så den bästa JDBC-drivrutinen kan göra är att hålla planen cachad i varje anslutning.

Obs:JDBC-specifikationen kräver användning av ?, ? för binda platshållare, medan servern vill ha $1, $2 sålunda cachelagrar JDBC-drivrutiner också så kallade parsade SQL-texter.

Det finns två välkända JDBC-drivrutiner:pgjdbc och pgjdbc-ng

pgjdbc

https://github.com/pgjdbc/pgjdbc

Sedan pgjdbc 9.4-1202 den cachar automatiskt planerna på serversidan när du använder PreparedStatement .Obs:satserna cachelagras även om du close() PreparedStatement .För att komma till förberedelse på serversidan måste du köra frågan 5 gånger (som kan konfigureras via prepareThreshold ).

För närvarande implementeras cachen per anslutning. Som standard pgjdbc cachar 256 (preparedStatementCacheQueries ) frågor och upp till preparedStatementCacheSizeMiB av frågor. Detta är en konservativ inställning, så du kanske vill justera den. Se dokumentation för beskrivning av egenskaper. Cachen innehåller både analyserade och serverförberedda satser.

github-problem:https://github.com/pgjdbc/pgjdbc/pull/319

pgjdbc-ng

https://github.com/impossibl/pgjdbc-ng

Jag är inte intresserad av pgjdbc-ng, men det ser ut som att det gör både parsning (standard cachestorlek är 250 frågor) och serverförberedande (standard cachestorlek är frågor). Stödet för förberedda uttalanden på serversidan landade den 24 februari 2014, så om du använder en lite ny version kan du få satscache.

Obs:om du av misstag använder mycket långa frågor kan du trycka på OutOfMemory eftersom pgjdbc-ng inte kan avhysa poster baserat på antalet bibehållna byte.

Cachen är per anslutning, så den används transparent även om du stänger uttalanden.

Jag kan inte säga så mycket om pgjdbc-ng prestanda, men sedan sist jag försökte kasta jmh på det misslyckades det med slumpmässiga undantag.

github-problem:https://github.com/impossibl/pgjdbc-ng/pull/ 69

Serverförberedda planer

PostgreSQL har PREPARE och DEALLOCATE kommandon för att referera till satsen när du skickar EXEC över tråden. Det optimerar två saker:

  1. När du använder PREPARE d-satsen (med andra ord serverförberedd) behöver klienten inte skicka frågetext om och om igen. Den skickar bara ett kort frågenamn och värdena för bindningsvariabler.
  2. Sedan 9.2 försöker databasen fortfarande planera om de första körningarna av en fråga. Det gör det för att försöka om frågan behöver flera planer eller om den generiska planen är tillräckligt bra. Så småningom (omedelbart om frågan inte har några parametrar), databasen kan byta till en generisk plan .
  3. Sedan 12 finns det en inställning för att tvinga ALLA serverförberedda uttalanden att köras med generiska eller anpassade planer:plan_cache_mode =auto | force_custom_plan | force_generic_plan

Med andra ord, PreparedStatement optimerar både frågeanalys på JDBC-sidan och frågeplanering på databassidan.

Mer info här:http://blog.endpoint .com/2014/04/custom-plans-prepared-statements-in.html

Förberedda uttalanden i PL/pgSQL

Enligt dokumentation, PostgreSQL cachar planer för frågor som används i PL/pgSQL. Detta händer efter några körningar (3 eller 5, jag kommer inte ihåg den exakta tröskeln), så efter att du har skapat en lagrad procedur kan det vara lite långsamt, men då kommer det att byta till cachade planer (förutsatt att databasen går med på att använda generisk plan för en viss fråga).

Med andra ord för att uppnå "cachade körningsplaner", måste du antingen använda uppdaterad JDBC-drivrutin, eller så kan du lägga in alla dina frågor i lagrade procedurer. Anropet till proceduren kommer att planeras om vid varje körning, men själva anropet är vanligtvis mycket kortare än frågor som utgör proceduren.



  1. SQL-fråga med två datum

  2. LIBSODIUM dekryptera data inuti mysql-frågan som gjorde med AES_DECRYPT

  3. Hur får man första och sista posten från en sql-fråga?

  4. Hur ser man index för en databas eller tabell i MySQL?