Es können verschiedene Arten von Batching beteiligt sein, und ich würde einen Teil davon des PostgreSQL-JDBC-Treibers (pgjdbc) behandeln.
TL;DR:pgjdbc verwendet weniger Netzwerk-Roundrips, falls die Batch-API verwendet wird. BatchedQuery
wird nur verwendet, wenn reWriteBatchedInserts=true
wird an die pgjdbc-Verbindungseinstellungen übergeben.
Möglicherweise finden Sie https://www.slideshare.net/VladimirSitnikv/postgresql-and-jdbc-striving-for-high-performance relevant (Folie 44,...)
Wenn es um die Ausführung von Abfragen geht, ist die Netzwerklatenz oft ein wesentlicher Teil der verstrichenen Zeit.
Angenommen, es sollen 10 Zeilen eingefügt werden.
-
Kein Batching (z. B. nur
PreparedStatement#execute
in einer Schleife). Der Treiber würde Folgendes ausführenexecute query sync <-- wait for the response from the DB execute query sync <-- wait for the response from the DB execute query sync <-- wait for the response from the DB ...
Eine beträchtliche Zeit würde mit dem "Warten auf die DB"
verbracht -
JDBC-Batch-API. Das ist
PreparedStatement#addBatch()
ermöglicht es dem Treiber, mehrere "Abfrageausführungen" in einem einzigen Netzwerk-Roundtrip zu senden. Die aktuelle Implementierung würde jedoch immer noch große Batches in kleinere aufteilen, um TCP-Deadlocks zu vermeiden.Die Aktionen wären viel besser:
execute query ... execute query execute query execute query sync <-- wait for the response from the DB
-
Beachten Sie, dass dies auch bei
#addBatch
der Fall ist , gibt es Overhead von Befehlen zum Ausführen von Abfragen. Der Server benötigt beträchtliche Zeit, um jede Nachricht einzeln zu verarbeiten.Eine der Möglichkeiten, die Anzahl der Abfragen zu reduzieren, ist die Verwendung von Inserts mit mehreren Werten. Zum Beispiel:
insert into tab(a,b,c) values (?,?,?), (?,?,?), ..., (?,?,?)
Dieses PostgreSQL ermöglicht das gleichzeitige Einfügen mehrerer Zeilen. Der Nachteil ist, dass Sie keine detaillierte Fehlermeldung (pro Zeile) haben. Derzeit implementiert Hibernate keine Mehrfachwert-Einfügung.
Allerdings kann pgjdbc seit 9.4.1209 (2016-07-15) reguläre Batch-Einfügungen in Mehrfachwerte umschreiben.
Um das Umschreiben mehrerer Werte zu aktivieren, müssen Sie
entwickeltreWriteBatchedInserts=true
hinzufügen Verbindungseigenschaft. Die Funktion wurde ursprünglich in https://github.com/pgjdbc/pgjdbc/pull/491Es ist schlau genug, 2 Anweisungen zu verwenden, um 10 Zeilen einzufügen. Die erste ist eine 8-wertige Aussage und die zweite eine 2-wertige Aussage. Die Verwendung von Zweierpotenzen ermöglicht es pgjdbc, die Anzahl unterschiedlicher Anweisungen vernünftig zu halten, und dies verbessert die Leistung, da häufig verwendete Anweisungen serverseitig vorbereitet werden (siehe Was ist die Lebensdauer einer serverseitig vorbereiteten PostgreSQL-Anweisung)
BatchedQuery
stellt diese Art von mehrwertigen Anweisungen dar, sodass Sie sehen, dass diese Klasse inreWriteBatchedInserts=true
verwendet wird nur Fall.Die Nachteile des Features können sein:niedrigere Details als das "Batch-Ergebnis". Zum Beispiel gibt Ihnen der reguläre Stapel "pro Anweisung Zeilenanzahl", aber im Fall von mehreren Werten erhalten Sie nur den Status "Anweisung abgeschlossen". Darüber hinaus kann der On-the-Fly-Rewriter bestimmte SQL-Anweisungen möglicherweise nicht analysieren (z. B. https://github.com/pgjdbc/pgjdbc/issues/1045 ).