PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Inserimento lento su PostgreSQL utilizzando JDBC

Sembra che questa sia una combinazione di un "bug" Spring e un "bug" del driver.

Spring cerca di determinare il tipo di dati di una colonna ogni volta setValue() è chiamato. Lo fa chiamando PreparedStatementMetaData.getParameterMetaData()

Questo apparentemente fa sì che un'istruzione "prepara" venga inviata al database che di per sé è abbastanza veloce (mai più di 1 ms sul mio laptop) ma come viene chiamato per ogni colonna per ogni riga si somma un sacco di tempo (viene chiamato per ogni valore non nullo che si traduce in circa 23.000 chiamate)

In una certa misura questo è più un bug di primavera che un bug del driver perché non memorizzare nella cache i metadati dei parametri non ha davvero senso (almeno secondo me). Il driver MySQL JDBC non supporta getParameterMetaData() e Spring lo sa e quindi questo "bug" non viene visualizzato con MySQL perché la primavera non chiama mai quel metodo.

Non sono sicuro che il comportamento del driver JDBC di Postgres possa essere classificato come un bug, ma sarebbe sicuramente bello se il driver stesse memorizzando nella cache quei metadati dopo la prima chiamata.

Spring può essere convinto a non ottenere i metadati dell'istruzione tramite la proprietà spring.jdbc.getParameterType.ignore

Quindi mettendo:

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

prima la linea:

LetsGo letsGo = new LetsGo();

questo comportamento è disabilitato.

La proprietà deve essere impostata prima La primavera è inizializzata.

Quando lo faccio con il tuo progetto di esempio, l'inserto viene eseguito in 500 ms sul mio laptop.

Modifica

Dopo aver visto il commento sull'uso del driver Postgres-NG ho scavato nelle fonti del driver "ufficiale" e del driver NG, e il driver NG memorizza nella cache i metadati dei parametri dopo la prima chiamata mentre il driver ufficiale non lo fa spiega perché usare il driver NG è molto più veloce (senza disabilitare la chiamata in primavera)