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

Compreensão das operações em lote JDBC


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.

  1. Sem lotes (por exemplo, apenas PreparedStatement#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"

  2. 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
    

  3. 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 adicionar reWriteBatchedInserts=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 em reWriteBatchedInserts=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 ).