L'inserimento di massa di dati (bulk insert) è un compito comune durante la migrazione, l'importazione o il riempimento di grandi tabelle. L'efficienza di tale operazione dipende da diversi fattori:
BULK INSERT o COPY (PostgreSQL) — essi funzionano più velocemente rispetto agli INSERT normali in un ciclo.BULK INSERT my_table FROM 'C:\data\bulkdata.csv' WITH ( FIELDTERMINATOR = ',', ROWTERMINATOR = ' ', BATCHSIZE = 5000, TABLOCK );
TABLOCKriduce i conflitti di blocco durante le inserzioni di massa.
Domanda: È possibile disattivare e ricreare indici in qualsiasi momento per accelerare l'inserimento di massa, se la tabella è coinvolta in transazioni?
Risposta: No, se la tabella è coinvolta in transazioni attive, disattivare o ricreare gli indici può portare a blocchi, violazioni dell'integrità dei dati o persino perdita di dati, se la transazione viene annullata. Questa operazione dovrebbe essere eseguita solo al di fuori delle transazioni, o pianificare in anticipo le finestre di manutenzione.
-- Errato: BEGIN TRAN; ALTER INDEX ALL ON my_table DISABLE; -- ... bulk insert ... ALTER INDEX ALL ON my_table REBUILD; COMMIT;
Tale disattivazione è inaccettabile all'interno di lunghe transazioni!
Storia 1: In un progetto, inserimenti di massa paralleli in una tabella con diversi indici univoci hanno portato a frequenti deadlock e a un calo drastico delle prestazioni. La soluzione è stata la disattivazione temporanea degli indici non chiave durante il periodo di importazione e la riduzione della dimensione delle operazioni batch.
Storia 2: Gli sviluppatori hanno dimenticato di disattivare il controllo delle chiavi esterne durante il caricamento dei dati, e ogni inserimento verificava l'esistenza di record correlati in altre tabelle di grandi dimensioni. Ciò ha aumentato il tempo di caricamento da 40 minuti a 9 ore. Dopo la disattivazione dei vincoli, l'inserimento ha richiesto 12 minuti.
Storia 3: Un tentativo di inserire un grande file con una singola query (senza batching e senza transazioni) ha portato al riempimento del registro delle transazioni (transaction log full) e all'arresto anomalo del server del database. Dopo essere passati al processamento batch, il problema è scomparso.