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

Comprensione delle operazioni batch JDBC

Potrebbero essere coinvolti vari tipi di batch e ne tratterei parte del driver JDBC PostgreSQL (pgjdbc).

TL; DR:pgjdbc utilizza meno roundrip di rete nel caso in cui venga utilizzata l'API batch. BatchedQuery viene utilizzato solo se reWriteBatchedInserts=true viene passato alle impostazioni di connessione pgjdbc.

Potresti trovare https://www.slideshare.net/VladimirSitnikv/postgresql-and-jdbc-striving-for-high-performance rilevante (diapositiva 44,...)

Quando si tratta di eseguire query, la latenza di rete è spesso una parte significativa del tempo trascorso.

Supponiamo che il caso sia inserire 10 righe.

  1. Nessun batching (ad es. solo PreparedStatement#execute in un ciclo). Il driver eseguirà quanto segue

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

    Notevole tempo sarebbe stato speso nell'"attesa del DB"

  2. API batch JDBC. Questo è PreparedStatement#addBatch() consente al conducente di inviare più "esecuzioni di query" in un unico roundtrip di rete. L'attuale implementazione, tuttavia, dividerebbe comunque i batch di grandi dimensioni in batch più piccoli per evitare il deadlock del TCP.

    Le azioni sarebbero molto migliori:

    execute query
    ...
    execute query
    execute query
    execute query
    sync <-- wait for the response from the DB
    
  3. Nota che anche con #addBatch , c'è un sovraccarico dei comandi "esegui query". Il server impiega molto tempo per elaborare ogni messaggio individualmente.

    Uno dei modi per ridurre il numero di query consiste nell'utilizzare l'inserimento a più valori. Ad esempio:

    insert into tab(a,b,c) values (?,?,?), (?,?,?), ..., (?,?,?)
    

    Questo PostgreSQL consente di inserire più righe contemporaneamente. Lo svantaggio è che non hai un messaggio di errore dettagliato (per riga). Attualmente Hibernate non implementa l'inserimento multivalore.

    Tuttavia pgjdbc può riscrivere inserimenti batch regolari in multi-valori al volo dal 9.4.1209 (2016-07-15).

    Per attivare la riscrittura multivalore, devi aggiungere reWriteBatchedInserts=true proprietà di connessione. La funzionalità è stata inizialmente sviluppata in https://github.com/pgjdbc/pgjdbc/pull/491

    È abbastanza intelligente usare 2 istruzioni per inserire 10 righe. La prima è un'istruzione a 8 valori e la seconda è un'istruzione a 2 valori. L'uso di poteri di due consente a pgjdbc di mantenere sano il numero di istruzioni distinte e ciò migliora le prestazioni poiché le istruzioni utilizzate spesso sono preparate dal server (vedi Qual è la durata di un'istruzione preparata lato server PostgreSQL)

    BatchedQuery rappresenta quel tipo di istruzioni multivalore, quindi vedrai quella classe usata in reWriteBatchedInserts=true solo caso.

    Gli svantaggi della funzione potrebbero includere:dettagli inferiori come "risultato batch". Ad esempio, il batch regolare ti dà "per conteggio righe per istruzione", tuttavia nel caso di più valori ottieni semplicemente lo stato "istruzione completata". Inoltre, il riscrittore al volo potrebbe non riuscire ad analizzare alcune istruzioni SQL (ad es. https://github.com/pgjdbc/pgjdbc/issues/1045).