Twoje pytanie w końcu sprowadza się do „jak java.sql.PreparedStatement
gra z PostgreSQL". Zobacz odpowiedź na końcu "jak to działa z planami przygotowanymi przez serwer".
Oto odpowiedź:to zależy od używanego sterownika JDBC.
TL;DR :w nowoczesnych kierowcach oświadczenie przygotowane przez serwer żyje do momentu zerwania połączenia lub do momentu, gdy oświadczenie zostanie eksmitowane przez inne (zwykła eksmisja LRU).
Uwaga:serwer PostgreSQL nie może udostępniać przygotowanych instrukcji między połączeniami z bazą danych, dlatego najlepszym sterownikiem JDBC jest zachowanie pamięci podręcznej planu w każdym połączeniu.
Uwaga:specyfikacja JDBC nakazuje użycie ?, ?
dla symboli zastępczych powiązań, podczas gdy serwer chce $1, $2
dlatego sterowniki JDBC buforują również tak zwane przeanalizowane teksty SQL.
Istnieją dwa dobrze znane sterowniki JDBC:pgjdbc i pgjdbc-ng
pgjdbc
https://github.com/pgjdbc/pgjdbc
Od pgjdbc 9.4-1202
automatycznie buforuje plany po stronie serwera podczas korzystania z PreparedStatement
.Uwaga:instrukcje są buforowane, nawet jeśli close()
PreparedStatement
.Aby dostać się do przygotowania po stronie serwera, musisz wykonać zapytanie 5 razy (można to skonfigurować za pomocą prepareThreshold
).
Obecnie pamięć podręczna jest zaimplementowana na połączenie. Domyślnie pgjdbc buforuje 256 (preparedStatementCacheQueries
) zapytania i maksymalnie preparedStatementCacheSizeMiB
zapytań. Jest to konserwatywne ustawienie, więc możesz je dostosować. Zobacz dokumentację
dla opisu właściwości. Pamięć podręczna zawiera zarówno przeanalizowane, jak i przygotowane przez serwer instrukcje.
Problem z githubem:https://github.com/pgjdbc/pgjdbc/pull/319
pgjdbc-ng
https://github.com/impossibl/pgjdbc-ng
Nie interesuje mnie pgjdbc-ng, ale wygląda na to, że wykonuje oba parsowanie (domyślny rozmiar pamięci podręcznej to 250 zapytania) i przygotowanie serwera (domyślny rozmiar pamięci podręcznej to 50 zapytania). Obsługa wyciągów przygotowanych po stronie serwera pojawiła się 24 lutego 2014 r., więc jeśli używasz nieco najnowszej wersji, możesz uzyskać buforowanie wyciągów.
Uwaga:jeśli przypadkowo użyjesz bardzo długich zapytań, możesz nacisnąć OutOfMemory
ponieważ pgjdbc-ng nie może eksmitować wpisów na podstawie liczby zachowanych bajtów.
Pamięć podręczna jest na połączenie, dlatego jest używana w sposób przejrzysty, nawet jeśli zamkniesz instrukcje.
Nie mogę wiele powiedzieć o wydajności pgjdbc-ng, chociaż odkąd ostatnio próbowałem rzucić na niego jmh, nie udało się to z przypadkowymi wyjątkami.
Problem z githubem:https://github.com/impossibl/pgjdbc-ng/pull/ 69
Plany przygotowane przez serwer
PostgreSQL ma PREPARE
i DEALLOCATE
komendy odwołujące się do instrukcji podczas wysyłania EXEC
przez drut. Optymalizuje dwie rzeczy:
- Gdy używasz
PREPARE
Instrukcja d (innymi słowy przygotowana przez serwer), klient nie musi ciągle wysyłać tekstu zapytania. Po prostu wysyła krótką nazwę zapytania i wartości zmiennych wiązania. - Od wersji 9.2 baza danych wciąż próbuje ponownie zaplanować kilka pierwszych wykonań zapytania. Robi to, aby sprawdzić, czy zapytanie wymaga wielu planów lub czy plan ogólny jest wystarczająco dobry. Ostatecznie (natychmiast, jeśli zapytanie nie ma parametrów), baza danych może przejść na plan ogólny .
- Od 12 roku istnieje ustawienie wymuszające wykonanie WSZYSTKICH instrukcji przygotowanych przez serwer z planami ogólnymi lub niestandardowymi:plan_cache_mode
=
auto | force_custom_plan | force_generic_plan
Innymi słowy, PreparedStatement
optymalizuje zarówno analizowanie zapytań po stronie JDBC, jak i planowanie zapytań po stronie bazy danych.
Więcej informacji tutaj:http://blog.endpoint .com/2014/04/custom-plans-prepared-statements-in.html
Przygotowane instrukcje w PL/pgSQL
Zgodnie z dokumentacją PostgreSQL bufory plany zapytań używanych w PL/pgSQL. Dzieje się tak po kilku wykonaniach (3 lub 5, nie pamiętam dokładnego progu), więc po utworzeniu procedury składowanej może być nieco powolna, ale wtedy przełączy się na plany buforowane (pod warunkiem, że baza danych zgodzi się na użycie planu generycznego dla konkretnego zapytania).
Innymi słowy, aby osiągnąć „plany wykonania w pamięci podręcznej”, musisz albo użyć aktualnego sterownika JDBC, albo możesz opakować wszystkie swoje zapytania w procedury składowane. zazwyczaj znacznie krótsze niż zapytania składające się na procedurę.