Ihre Frage läuft also darauf hinaus, "wie java.sql.PreparedStatement
spielt mit PostgreSQL". Siehe Antwort auf "wie dies mit vom Server vorbereiteten Plänen spielt" am Ende.
Hier ist die Antwort:Das hängt vom verwendeten JDBC-Treiber ab.
TL;DR :In modernen Treibern lebt die vom Server vorbereitete Anweisung, bis die Verbindung unterbrochen wird oder bis die Anweisung von einer anderen entfernt wird (normale LRU-Beseitigung).
Hinweis:Der PostgreSQL-Server kann vorbereitete Anweisungen nicht über Datenbankverbindungen hinweg freigeben, daher ist der beste JDBC-Treiber, den Plan in jeder Verbindung zwischenzuspeichern.
Hinweis:Die JDBC-Spezifikation schreibt die Verwendung von ?, ?
vor für Bindungsplatzhalter, während der Server $1, $2
will daher cachen JDBC-Treiber auch sogenannte geparste SQL-Texte.
Es gibt zwei bekannte JDBC-Treiber:pgjdbc und pgjdbc-ng
pgjdbc
https://github.com/pgjdbc/pgjdbc
Seit pgjdbc 9.4-1202
es speichert automatisch serverseitige Pläne, wenn PreparedStatement
verwendet wird .Hinweis:Die Anweisungen werden zwischengespeichert, auch wenn Sie close()
ausführen das PreparedStatement
.Um zur serverseitigen Vorbereitung zu gelangen, müssen Sie die Abfrage 5 Mal ausführen (das kann über prepareThreshold
konfiguriert werden ).
Derzeit wird der Cache pro Verbindung implementiert. Standardmäßig speichert pgjdbc 256 (preparedStatementCacheQueries
) Abfragen und bis zu preparedStatementCacheSizeMiB
von Anfragen. Dies ist eine konservative Einstellung, daher sollten Sie sie möglicherweise anpassen. Siehe Dokumentation
für die Beschreibung von Eigenschaften. Der Cache enthält sowohl geparste als auch vom Server vorbereitete Anweisungen.
Github-Problem:https://github.com/pgjdbc/pgjdbc/pull/319
pgjdbc-ng
https://github.com/impossibl/pgjdbc-ng
Ich mag pgjdbc-ng nicht, aber es sieht so aus, als würde es beides analysieren (die Standard-Cache-Größe ist 250 Abfragen) und Server-Vorbereitung (Standard-Cache-Größe ist 50 Anfragen). Die Unterstützung von serverseitig vorbereiteten Anweisungen wurde am 24. Februar 2014 eingeführt. Wenn Sie also eine etwas neuere Version verwenden, können Sie das Zwischenspeichern von Anweisungen erhalten.
Hinweis:Wenn Sie versehentlich sehr lange Abfragen verwenden, können Sie auf OutOfMemory
klicken da pgjdbc-ng keine Einträge basierend auf der Anzahl der zurückbehaltenen Bytes entfernen kann.
Der Cache ist pro Verbindung, daher wird er transparent verwendet, selbst wenn Sie Anweisungen schließen.
Ich kann nicht viel über die Leistung von pgjdbc-ng sagen, obwohl ich das letzte Mal versucht habe, jmh darauf zu werfen, es ist mit zufälligen Ausnahmen fehlgeschlagen.
Github-Problem:https://github.com/impossibl/pgjdbc-ng/pull/ 69
Server-vorbereitete Pläne
PostgreSQL hat PREPARE
und DEALLOCATE
Befehle, um beim Senden von EXEC
auf die Anweisung zu verweisen über den Draht. Es optimiert zwei Dinge:
- Bei Verwendung von
PREPARE
d-Anweisung (mit anderen Worten eine vom Server vorbereitete) muss der Client den Abfragetext nicht immer wieder senden. Es sendet nur einen kurzen Abfragenamen und die Werte für Bind-Variablen. - Seit 9.2 versucht die Datenbank immer noch, die ersten paar Ausführungen einer Abfrage neu zu planen. Dies geschieht, um zu testen, ob die Abfrage mehrere Pläne benötigt oder ob ein generischer Plan gut genug ist. Schließlich (sofort, wenn die Abfrage keine Parameter hat), die Datenbank möglicherweise zu einem generischen Tarif wechseln .
- Seit 12 gibt es eine Einstellung, um zu erzwingen, dass ALLE vom Server vorbereiteten Anweisungen mit generischen oder benutzerdefinierten Plänen ausgeführt werden:plan_cache_mode
=
auto | force_custom_plan | force_generic_plan
Mit anderen Worten, PreparedStatement
optimiert sowohl die Abfrageanalyse auf der JDBC-Seite als auch die Abfrageplanung auf der Datenbankseite.
Weitere Informationen hier:http://blog.endpoint .com/2014/04/custom-plans-prepared-statements-in.html
Vorbereitete Anweisungen in PL/pgSQL
Laut Dokumentation speichert PostgreSQL Caches Pläne für Abfragen, die in PL/pgSQL verwendet werden. Dies geschieht nach einigen Ausführungen (3 oder 5, ich erinnere mich nicht an den genauen Schwellenwert). Nachdem Sie eine gespeicherte Prozedur erstellt haben, kann es etwas langsam sein, aber dann wird zu zwischengespeicherten Plänen gewechselt (vorausgesetzt, die Datenbank stimmt der Verwendung eines generischen Plans zu). für eine bestimmte Abfrage).
Mit anderen Worten, um "zwischengespeicherte Ausführungspläne" zu erreichen, müssen Sie entweder den aktuellen JDBC-Treiber verwenden oder alle Ihre Abfragen in gespeicherte Prozeduren einpacken. Der Aufruf der Prozedur wird bei jeder Ausführung neu geplant, wie auch immer der Aufruf selbst ist normalerweise viel kürzer als Abfragen, aus denen sich die Prozedur zusammensetzt.