PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Inserção lenta no PostgreSQL usando JDBC


Parece que esta é uma combinação de um "bug" do Spring e um "bug" do driver.

O Spring tenta determinar o tipo de dados de uma coluna toda vez que setValue() é chamado. Ele faz isso chamando PreparedStatementMetaData.getParameterMetaData()

Isso aparentemente faz com que uma instrução "prepare" seja enviada para o banco de dados, o que em si é bastante rápido (nunca mais de 1 ms no meu laptop), mas como é chamado para cada coluna para cada linha isso soma muito tempo (é chamado para cada valor não nulo que resulta em aproximadamente 23.000 chamadas)

Até certo ponto, isso é mais um bug do Spring do que um bug do driver, porque não armazenar em cache os metadados do parâmetro realmente não faz sentido (pelo menos na minha opinião). O driver MySQL JDBC não suporta getParameterMetaData() e o Spring sabe disso e, portanto, esse "bug" não aparece com o MySQL porque o Spring nunca chama esse método.

Não tenho certeza se o comportamento do driver JDBC do Postgres pode ser classificado como um bug, mas com certeza seria bom se o driver estivesse armazenando em cache esses metadados após a primeira chamada.

O Spring pode ser convencido a não obter os metadados da instrução através da propriedade spring.jdbc.getParameterType.ignore

Então colocando:
System.setProperty("spring.jdbc.getParameterType.ignore", "true");

antes a linha:
LetsGo letsGo = new LetsGo();

este comportamento está desabilitado.

A propriedade deve ser definida antes Spring é inicializado.

Quando faço isso com seu projeto de exemplo, a inserção é executada em 500ms no meu laptop.

Editar

Depois de ver o comentário sobre o uso do driver Postgres-NG, pesquisei nas fontes do driver "oficial" e do driver NG, e o driver NG armazena em cache os metadados do parâmetro após a primeira chamada, enquanto o driver oficial não explica por que usar o driver NG é muito mais rápido (sem desabilitar a chamada no Spring)