Masowa wstawka danych (bulk insert) to typowe zadanie podczas migracji, importu lub zapełniania dużych tabel. Efektywność takiej operacji zależy od kilku czynników:
BULK INSERT lub COPY (PostgreSQL) — działają one szybciej niż normalne INSERT w pętli.BULK INSERT my_table FROM 'C:\data\bulkdata.csv' WITH ( FIELDTERMINATOR = ',', ROWTERMINATOR = ' ', BATCHSIZE = 5000, TABLOCK );
TABLOCKzmniejsza konflikty blokad podczas masowych wstawek.
Pytanie: Czy można w dowolnym momencie wyłączać i odbudowywać indeksy w celu przyspieszenia bulk insert, jeśli tabela uczestniczy w transakcjach?
Odpowiedź: Nie, jeśli tabela uczestniczy w aktywnych transakcjach, wyłączenie lub odbudowanie indeksów może prowadzić do blokad, naruszenia integralności danych lub nawet utraty danych, jeśli transakcja zostanie wycofana. Operację tę należy przeprowadzać tylko poza transakcjami lub z wyprzedzeniem planować okna serwisowe.
-- Nieprawidłowo: BEGIN TRAN; ALTER INDEX ALL ON my_table DISABLE; -- ... bulk insert ... ALTER INDEX ALL ON my_table REBUILD; COMMIT;
Takie wyłączenie jest niedopuszczalne w długich transakcjach!
Historia 1: W jednym projekcie równoległe bulk insert do tabeli z wieloma unikalnymi indeksami doprowadziły do częstych deadlocków i gwałtownego spadku wydajności. Rozwiązaniem było tymczasowe wyłączenie indeksów niekluczowych na czas importu oraz zmniejszenie rozmiaru operacji batch.
Historia 2: Programiści zapomnieli wyłączyć kontrolę kluczy obcych na czas ładowania danych, a każdy insert sprawdzał istnienie powiązanych rekordów w innych dużych tabelach. To zwiększyło czas ładowania z 40 minut do 9 godzin. Po wyłączeniu constraintów wstawka zajęła 12 minut.
Historia 3: Próba wstawienia dużego pliku jednym zapytaniem (bez pakietowania i bez transakcji) doprowadziła do przepełnienia dziennika transakcji (transaction log full) i awaryjnego zakończenia serwera baz danych. Po przejściu na przetwarzanie wsadowe problem zniknął.