sql >> Database >  >> RDS >> PostgreSQL

Hoe werkt COPY en waarom is het zoveel sneller dan INSERT?

Er zijn hier een aantal factoren aan het werk:

  • Netwerklatentie en retourvertragingen
  • Overheadkosten per verklaring in PostgreSQL
  • Contextwisselingen en plannervertragingen
  • COMMIT kosten, als voor mensen die één commit per insert doen (dat ben je niet)
  • COPY -specifieke optimalisaties voor bulklading

Netwerklatentie

Als de server zich op afstand bevindt, "betaalt" u mogelijk een vaste tijdprijs per verklaring van bijvoorbeeld 50 ms (1/20e van een seconde). Of nog veel meer voor sommige door de cloud gehoste DB's. Aangezien de volgende invoeging pas kan beginnen als de laatste succesvol is voltooid, betekent dit dat uw maximum snelheid van invoegingen is 1000/round-trip-latentie-in-ms rijen per seconde. Bij een latentie van 50 ms ("ping-tijd") is dat 20 rijen/seconde. Zelfs op een lokale server is deze vertraging niet nul. Waar COPY vult gewoon de TCP-verzend- en ontvangstvensters en streamt rijen zo snel als de DB ze kan schrijven en het netwerk ze kan overbrengen. Het wordt niet veel beïnvloed door latentie en kan duizenden rijen per seconde invoegen op dezelfde netwerklink.

Kosten per afschrift in PostgreSQL

Er zijn ook kosten verbonden aan het ontleden, plannen en uitvoeren van een instructie in PostgreSQL. Het moet locks hebben, relatiebestanden openen, indexen opzoeken, enz. COPY probeert dit allemaal één keer te doen, in het begin, en concentreer je dan op het zo snel mogelijk laden van rijen.

Taak/contextomschakelingskosten

Er worden nog meer tijdskosten betaald omdat het besturingssysteem moet schakelen tussen postgres die wacht op een rij terwijl uw app deze voorbereidt en verzendt, en vervolgens wacht uw app op de reactie van postgres terwijl postgres de rij verwerkt. Elke keer dat u van de ene naar de andere overschakelt, verspilt u wat tijd. Er wordt mogelijk meer tijd verspild aan het opschorten en hervatten van verschillende kernelstatussen op laag niveau wanneer processen een wachtstatus binnengaan en verlaten.

KOPIE-optimalisaties mislopen

Bovendien, COPY heeft enkele optimalisaties die het voor sommige soorten belastingen kan gebruiken. Als er geen gegenereerde sleutel is en eventuele standaardwaarden constanten zijn, kan het deze vooraf berekenen en de uitvoerder volledig omzeilen, waarbij gegevens snel in de tabel worden geladen op een lager niveau dat een deel van het normale werk van PostgreSQL volledig overslaat. Als u CREATE TABLE of TRUNCATE in dezelfde transactie die u COPY , het kan nog meer trucjes doen om het laden sneller te maken door de normale transactieboekhouding te omzeilen die nodig is in een multi-clientdatabase.

Ondanks dit, PostgreSQL's COPY zou nog veel meer kunnen doen om dingen te versnellen, dingen waarvan het nog niet weet hoe het moet. Het kan automatisch indexupdates overslaan en vervolgens indexen opnieuw opbouwen als u meer dan een bepaald deel van de tabel wijzigt. Het zou indexupdates in batches kunnen doen. Veel meer.

Kosten vastleggen

Een laatste ding om te overwegen zijn de vastleggingskosten. Het is waarschijnlijk geen probleem voor u omdat psycopg2 standaard is om een ​​transactie te openen en niet vast te leggen totdat u het zegt. Tenzij je hem hebt verteld om autocommit te gebruiken. Maar voor veel DB-stuurprogramma's is autocommit de standaardinstelling. In dergelijke gevallen zou je één commit doen voor elke INSERT . Dat betekent één schijfspoeling, waarbij de server ervoor zorgt dat alle gegevens in het geheugen op schijf worden weggeschreven en de schijven opdraagt ​​hun eigen caches naar de permanente opslag te schrijven. Dit kan lang duren tijd, en varieert sterk op basis van de hardware. Mijn op SSD gebaseerde NVMe BTRFS-laptop kan slechts 200 fsyncs/seconde, versus 300.000 niet-gesynchroniseerde schrijfbewerkingen/seconde. Dus het laadt maar 200 rijen/seconde! Sommige servers kunnen slechts 50 fsyncs/seconde doen. Sommigen kunnen 20.000 doen. Dus als je regelmatig moet committen, probeer dan in batches te laden en vast te leggen, voeg meerdere rijen toe, enz. Omdat COPY slechts één commit aan het einde, de kosten van de commit zijn te verwaarlozen. Maar dit betekent ook COPY kan niet halverwege de gegevens herstellen van fouten; het maakt de hele bulklading ongedaan.



  1. Is de NOLOCK (Sql Server hint) een slechte gewoonte?

  2. Hoe vind ik de rechten en rollen die in Oracle aan een gebruiker zijn toegekend?

  3. Hoe gebruik je een Oracle Ref Cursor van C# ODP.NET als een ReturnValue-parameter, zonder een opgeslagen functie of procedure te gebruiken?

  4. SQL, gegevens aan een tabel toevoegen