PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Langsames Einfügen auf PostgreSQL mit JDBC

Es scheint, dass dies eine Kombination aus einem Spring-"Bug" und einem Treiber-"Bug" ist.

Spring versucht bei jedem setValue() den Datentyp einer Spalte zu bestimmen wird genannt. Dazu wird PreparedStatementMetaData.getParameterMetaData() aufgerufen

Dies bewirkt anscheinend, dass eine "prepare"-Anweisung an die Datenbank gesendet wird, die an sich ziemlich schnell ist (nie mehr als 1 ms auf meinem Laptop), aber da sie für jede Spalte aufgerufen wird für jede Zeile summiert sich das zu einer Menge Zeit (es wird für jeden Nicht-Null-Wert aufgerufen, was ca. 23.000 Aufrufe ergibt)

Bis zu einem gewissen Grad ist dies eher ein Spring-Bug als ein Treiber-Bug, da das Zwischenspeichern der Parameter-Metadaten nicht wirklich sinnvoll ist (zumindest meiner Meinung nach). Der MySQL-JDBC-Treiber unterstützt getParameterMetaData() nicht und Spring weiß das und daher taucht dieser "Bug" bei MySQL nicht auf, weil Spring diese Methode nie aufruft.

Ich bin mir nicht sicher, ob das Verhalten des JDBC-Treibers von Postgres als Fehler eingestuft werden kann, aber es wäre sicher nett, wenn der Treiber diese Metadaten nach dem ersten Aufruf zwischenspeichern würde.

Spring kann davon überzeugt werden, die Metadaten der Anweisung nicht über die Eigenschaft spring.jdbc.getParameterType.ignore zu erhalten

Also durch Setzen:

System.setProperty("spring.jdbc.getParameterType.ignore", "true");

vorher die Zeile:

LetsGo letsGo = new LetsGo();

dieses Verhalten ist deaktiviert.

Die Eigenschaft muss vor gesetzt werden Der Frühling wird initialisiert.

Wenn ich das mit Ihrem Beispielprojekt mache, läuft das Insert auf meinem Laptop in 500 ms.

Bearbeiten

Nachdem ich den Kommentar zur Verwendung des Postgres-NG-Treibers gesehen hatte, habe ich mich in die Quellen des "offiziellen" Treibers und des NG-Treibers vertieft, und der NG-Treiber speichert die Parameter-Metadaten nach dem ersten Aufruf, während der offizielle Treiber dies nicht tut erklärt, warum die Verwendung des NG-Treibers so viel schneller ist (ohne den Aufruf in Spring zu deaktivieren)