Pode haver vários tipos de lotes envolvidos, e eu cobriria parte do driver JDBC do PostgreSQL (pgjdbc).
TL;DR:pgjdbc usa menos roundrips de rede caso a API em lote seja usada.
BatchedQuery
é usado somente se reWriteBatchedInserts=true
é passado para as configurações de conexão do pgjdbc. Você pode achar https://www.slideshare.net/VladimirSitnikv/postgresql-and-jdbc-striving-for-high-performance relevante (slide 44,...)
Quando se trata de execução de consultas, a latência da rede geralmente é uma parte significativa do tempo decorrido.
Suponha que o caso seja inserir 10 linhas.
-
Sem lotes (por exemplo, apenasPreparedStatement#execute
em um laço). O motorista faria o seguinte
execute 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 ...
Um tempo notável seria gasto na "espera pelo DB"
-
API em lote JDBC. Isso éPreparedStatement#addBatch()
permite que o driver envie várias "execuções de consulta" em uma única viagem de ida e volta à rede. A implementação atual, no entanto, ainda dividiria grandes lotes em menores para evitar o impasse do TCP.
As ações seriam muito melhores:
execute query ... execute query execute query execute query sync <-- wait for the response from the DB
-
Observe que, mesmo com#addBatch
, há sobrecarga de comandos "execute query". O servidor leva um tempo notável para processar cada mensagem individualmente.
Uma das maneiras de reduzir o número de consultas é usar a inserção de vários valores. Por exemplo:
insert into tab(a,b,c) values (?,?,?), (?,?,?), ..., (?,?,?)
Este PostgreSQL permite inserir várias linhas de uma vez. A desvantagem é que você não tem uma mensagem de erro detalhada (por linha). Atualmente o Hibernate não implementa a inserção de múltiplos valores.
No entanto, o pgjdbc pode reescrever inserções de lote regulares em vários valores em tempo real desde 9.4.1209 (2016-07-15).
Para ativar a reescrita de vários valores, você precisa adicionarreWriteBatchedInserts=true
propriedade de conexão. O recurso foi desenvolvido inicialmente em https://github.com/pgjdbc/pgjdbc/pull/491
É inteligente o suficiente usar 2 instruções para inserir 10 linhas. A primeira é uma instrução de 8 valores e a segunda é uma instrução de 2 valores. O uso de potências de dois permite que o pgjdbc mantenha o número de instruções distintas sã e isso melhora o desempenho, pois as instruções usadas com frequência são preparadas pelo servidor (consulte Qual é a vida útil de uma instrução preparada do lado do servidor PostgreSQL )
BatchedQuery
está representando esse tipo de instrução de vários valores, então você verá essa classe usada emreWriteBatchedInserts=true
caso apenas.
As desvantagens do recurso podem incluir:detalhes mais baixos como o "resultado do lote". Por exemplo, o lote regular fornece "por contagem de linhas por instrução", no entanto, no caso de vários valores, você obtém apenas o status "instrução concluída". Além disso, o reescritor on-the-fly pode falhar ao analisar determinadas instruções SQL (por exemplo, https://github.com/pgjdbc/pgjdbc/issues/1045 ).