sql >> Databasteknik >  >> RDS >> PostgreSQL

Hur fungerar COPY och varför är det så mycket snabbare än INSERT?

Det finns ett antal faktorer som spelar in här:

  • Nätverkslatens och tur och retur förseningar
  • Omkostnader per påstående i PostgreSQL
  • Kontextväxlingar och schemaläggningsfördröjningar
  • COMMIT kostnader, om för personer som gör en commit per infogning (det är du inte)
  • COPY -specifika optimeringar för bulklastning

Nätverkslatens

Om servern är avlägsen, kanske du "betalar" ett fast tids-"pris" per påstående på, till exempel, 50 ms (1/20 av en sekund). Eller mycket mer för vissa molnvärdade DB:er. Eftersom nästa infogning inte kan börja förrän den sista har slutförts, betyder detta ditt maximum frekvensen av infogning är 1000/round-trip-latency-in-ms rader per sekund. Vid en latens på 50 ms ("pingtid") är det 20 rader/sekund. Även på en lokal server är denna fördröjning inte noll. Medan COPY fyller bara TCP:s sändnings- och mottagningsfönster och strömmar rader så snabbt som DB kan skriva dem och nätverket kan överföra dem. Den påverkas inte mycket av latens och kan infoga tusentals rader per sekund på samma nätverkslänk.

Kostnader per rapport i PostgreSQL

Det finns också kostnader för att analysera, planera och utföra ett uttalande i PostgreSQL. Den måste ta lås, öppna relationsfiler, slå upp index etc. COPY försöker göra allt detta en gång, i början, och fokusera sedan på att ladda rader så snabbt som möjligt.

Kostnader för att byta uppgifter/sammanhang

Det finns ytterligare tidskostnader som betalas på grund av att operativsystemet måste växla mellan postgres som väntar på en rad medan din app förbereder och skickar den, och sedan väntar din app på postgres svar medan postgres bearbetar raden. Varje gång du byter från det ena till det andra slösar du bort lite tid. Mer tid slösas potentiellt bort på att avbryta och återuppta olika lågnivåkärntillstånd när processer går in i och lämnar väntelägen.

Missar COPY-optimeringar

Utöver allt det, COPY har några optimeringar som den kan använda för vissa typer av belastningar. Om det inte finns någon genererad nyckel och eventuella standardvärden är konstanter, till exempel, kan den förkalkylera dem och förbigå executorn helt och hållet, snabbt ladda in data i tabellen på en lägre nivå som hoppar över en del av PostgreSQL:s normala arbete helt. Om du CREATE TABLE eller TRUNCATE i samma transaktion COPY , den kan göra ännu fler knep för att göra laddningen snabbare genom att kringgå den normala transaktionsbokföring som behövs i en multiklientdatabas.

Trots detta, PostgreSQL:s COPY kunde fortfarande göra mycket mer för att påskynda saker, saker som den ännu inte vet hur man gör. Det kan automatiskt hoppa över indexuppdateringar och sedan bygga om index om du ändrar mer än en viss del av tabellen. Det kan göra indexuppdateringar i omgångar. Mycket mer.

Avsluta kostnader

En sista sak att tänka på är åtagandekostnader. Det är förmodligen inte ett problem för dig eftersom psycopg2 öppnar som standard en transaktion och inte binder sig förrän du säger till den. Såvida du inte sa åt den att använda autocommit. Men för många DB-drivrutiner är autocommit standard. I sådana fall skulle du göra en commit för varje INSERT . Det betyder en diskspolning, där servern ser till att den skriver ut all data i minnet till disken och säger åt diskarna att skriva ut sina egna cachar till beständig lagring. Detta kan ta lång tid tid, och varierar mycket beroende på hårdvaran. Min SSD-baserade NVMe BTRFS-laptop kan bara göra 200 fsyncs/sekund, mot 300 000 osynkroniserade skrivningar/sekund. Så det kommer bara att ladda 200 rader/sekund! Vissa servrar kan bara göra 50 fsyncs/sekund. Vissa kan göra 20 000. Så om du måste commit regelbundet, försök att ladda och commit i batcher, gör multi-rad inserts, etc. Eftersom COPY bara ett åtagande i slutet, åtagandekostnader är försumbara. Men detta betyder också COPY kan inte återställa från fel halvvägs genom data; det ångrar hela bulklasten.



  1. Oracle Lås &bordslås:Hur det fungerar

  2. Android SQLite LIKE escape jokertecken

  3. Viktig PostgreSQL-övervakning - Del 3

  4. SQL Server Error 110:Det finns färre kolumner i INSERT-satsen än de värden som anges i VALUES-satsen.