Der kan være forskellige slags batching involveret, og jeg vil dække PostgreSQL JDBC driver (pgjdbc) en del af det.
TL;DR:pgjdbc bruger færre netværk roundrips i tilfælde af at batch API bruges. BatchedQuery
bruges kun hvis reWriteBatchedInserts=true
videregives til pgjdbc-forbindelsesindstillingerne.
Du finder måske https://www.slideshare.net/VladimirSitnikv/postgresql-and-jdbc-striving-for-high-performance relevant (slide 44,...)
Når det kommer til udførelse af forespørgsler, er netværksforsinkelse ofte en væsentlig del af den forløbne tid.
Antag, at sagen skal indsætte 10 rækker.
-
Ingen batching (f.eks. kun
PreparedStatement#execute
i en løkke). Driveren ville udføre følgendeexecute 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 ...
Bemærkelsesværdig tid ville blive brugt i "venter på DB"
-
JDBC batch API. Det er
PreparedStatement#addBatch()
gør det muligt for driveren at sende flere "forespørgselsudførelser" på en enkelt netværksrundtur. Den nuværende implementering ville dog stadig opdele store batches i mindre for at undgå TCP-deadlock.Handlingerne ville være meget bedre:
execute query ... execute query execute query execute query sync <-- wait for the response from the DB
-
Bemærk, at selv med
#addBatch
, der er overhead af "eksekver forespørgsel"-kommandoer. Det tager serveren bemærkelsesværdig tid at behandle hver besked individuelt.En af måderne at reducere antallet af forespørgsler på er at bruge multi-values insert. For eksempel:
insert into tab(a,b,c) values (?,?,?), (?,?,?), ..., (?,?,?)
Denne PostgreSQL gør det muligt at indsætte flere rækker på én gang. Ulempen er, at du ikke har en detaljeret (per række) fejlmeddelelse. I øjeblikket implementerer Hibernate ikke indsættelse af flere værdier.
Men pgjdbc kan omskrive almindelige batch-indsættelser til multi-værdier på farten siden 9.4.1209 (2016-07-15).
For at aktivere omskrivning af flere værdier skal du tilføje
reWriteBatchedInserts=true
forbindelsesejendom. Funktionen blev oprindeligt udviklet på https://github.com/pgjdbc/pgjdbc/pull/491Det er smart nok at bruge 2 sætninger for at indsætte 10 rækker. Den første er 8-værdiudsagn, og den anden er 2-værdiudsagn. Brug af kræfter til to gør det muligt for pgjdbc at holde antallet af distinkte sætninger fornuftigt, og det forbedrer ydeevnen, da ofte brugte sætninger er serverforberedte (se Hvad er levetiden for en PostgreSQL server-side forberedt erklæring)
BatchedQuery
repræsenterer den slags udsagn med flere værdier, så du vil se den klasse brugt ireWriteBatchedInserts=true
kun tilfælde.Ulemperne ved funktionen kan omfatte:lavere detaljer som "batchresultat". F.eks. giver almindelig batch dig "per erklæring rækkeantal", men i tilfælde med flere værdier får du bare status som "erklæring fuldført". Oven i det kan on-the-fly-omskriveren muligvis ikke parse visse SQL-sætninger (f.eks. https://github.com/pgjdbc/pgjdbc/issues/1045 ).