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

Come funziona COPY e perché è molto più veloce di INSERT?

Ci sono una serie di fattori all'opera qui:

  • Latenza di rete e ritardi di andata e ritorno
  • Spese generali per istruzione in PostgreSQL
  • Cambiamenti di contesto e ritardi nella pianificazione
  • COMMIT costi, se per le persone che fanno un commit per inserto (non lo sei)
  • COPY -ottimizzazioni specifiche per il caricamento in blocco

Latenza di rete

Se il server è remoto, potresti "pagare" un "prezzo" a tempo fisso per dichiarazione di, diciamo, 50 ms (1/20 di secondo). O molto di più per alcuni DB ospitati nel cloud. Poiché l'inserimento successivo non può iniziare finché l'ultimo non viene completato correttamente, ciò significa il tuo massimo la velocità di inserimento è di 1000 righe/latenza di andata e ritorno in ms al secondo. Con una latenza di 50 ms ("tempo di ping"), sono 20 righe al secondo. Anche su un server locale, questo ritardo è diverso da zero. Dove COPY riempie semplicemente le finestre di invio e ricezione TCP e trasmette le righe alla velocità con cui il DB può scriverle e la rete può trasferirle. Non è influenzato molto dalla latenza e potrebbe inserire migliaia di righe al secondo sullo stesso collegamento di rete.

Costi per rendiconto in PostgreSQL

Ci sono anche costi per l'analisi, la pianificazione e l'esecuzione di un'istruzione in PostgreSQL. Deve prendere lock, aprire file di relazione, cercare indici, ecc. COPY prova a fare tutto questo una volta, all'inizio, quindi concentrati solo sul caricamento delle righe il più velocemente possibile.

Costi di cambio attività/contesto

Ci sono ulteriori costi di tempo pagati a causa del fatto che il sistema operativo deve passare da un postgres all'altro in attesa di una riga mentre l'app la prepara e la invia, e quindi l'app in attesa della risposta di postgres mentre postgres elabora la riga. Ogni volta che passi dall'uno all'altro, perdi un po' di tempo. È potenzialmente sprecato più tempo per sospendere e riprendere vari stati del kernel di basso livello quando i processi entrano ed escono dagli stati di attesa.

Perdere le ottimizzazioni COPY

Inoltre, COPY ha alcune ottimizzazioni che può utilizzare per alcuni tipi di carichi. Se non c'è una chiave generata e tutti i valori predefiniti sono costanti, ad esempio, può pre-calcolarli e bypassare completamente l'esecutore, caricando rapidamente i dati nella tabella a un livello inferiore che salta completamente parte del normale lavoro di PostgreSQL. Se CREATE TABLE o TRUNCATE nella stessa transazione COPY , può fare ancora più trucchi per rendere il carico più veloce bypassando la normale contabilità delle transazioni necessaria in un database multi-client.

Nonostante ciò, COPY di PostgreSQL potrebbe fare ancora molto di più per velocizzare le cose, cose che non sa ancora fare. Potrebbe saltare automaticamente gli aggiornamenti degli indici, quindi ricostruire gli indici se stai modificando più di una certa proporzione della tabella. Potrebbe eseguire aggiornamenti dell'indice in batch. Molto di più.

Impegna i costi

Un'ultima cosa da considerare sono i costi di commit. Probabilmente non è un problema per te perché psycopg2 per impostazione predefinita apre una transazione e non si impegna finché non glielo dici tu. A meno che tu non gli abbia detto di usare autocommit. Ma per molti driver DB il commit automatico è l'impostazione predefinita. In questi casi faresti un commit per ogni INSERT . Ciò significa uno svuotamento del disco, in cui il server si assicura di scrivere tutti i dati in memoria su disco e dice ai dischi di scrivere le proprie cache nella memoria permanente. Questo può richiedere un lungo tempo e varia molto in base all'hardware. Il mio laptop NVMe BTRFS basato su SSD può eseguire solo 200 fsync al secondo, contro 300.000 scritture non sincronizzate al secondo. Quindi caricherà solo 200 righe al secondo! Alcuni server possono eseguire solo 50 fsync/secondo. Alcuni possono fare 20.000. Quindi, se devi impegnarti regolarmente, prova a caricare e impegnare in batch, eseguire inserimenti su più righe, ecc. Perché COPY solo un commit alla fine, i costi di commit sono trascurabili. Ma questo significa anche COPY non può recuperare da errori a metà dei dati; annulla l'intero carico di massa.