Массовая вставка данных (bulk insert) — типичная задача при миграции, импорте или пополнении больших таблиц. Эффективность такой операции зависит от нескольких факторов:
BULK INSERT или COPY (PostgreSQL) — они работают быстрее обычных INSERT в цикле.BULK INSERT my_table FROM 'C:\data\bulkdata.csv' WITH ( FIELDTERMINATOR = ',', ROWTERMINATOR = ' ', BATCHSIZE = 5000, TABLOCK );
TABLOCKуменьшает конфликты блокировок при массовых вставках.
Вопрос: Можно ли в любой момент времени отключать и пересоздавать индексы для ускорения bulk insert, если таблица участвует в транзакциях?
Ответ: Нет, если таблица участвует в активных транзакциях, отключение или пересоздание индексов может привести к блокировкам, нарушению целостности данных или даже потере данных, если транзакция откатится. Эту операцию следует выполнять только вне транзакций, или заранее планировать окна обслуживания.
-- Неправильно: BEGIN TRAN; ALTER INDEX ALL ON my_table DISABLE; -- ... bulk insert ... ALTER INDEX ALL ON my_table REBUILD; COMMIT;
Такое отключение недопустимо внутри длинных транзакций!
История 1: В одном проекте параллельные bulk insert в таблицу с несколькими уникальными индексами привели к частым deadlock'ам и резкому проседанию производительности. Решением было временное отключение неключевых индексов на период импорта и уменьшение размера batch операций.
История 2: Разработчики забыли отключить контроль внешних ключей на период загрузки данных, и каждый insert проверял наличие связанных записей в других крупных таблицах. Это увеличило время загрузки с 40 минут до 9 часов. После отключения constraint'ов вставка заняла 12 минут.
История 3: Попытка вставить большой файл единым запросом (без пакетирования и без транзакций) привела к переполнению журнала транзакций (transaction log full) и аварийному завершению сервера баз данных. После перехода к batch processing проблема ушла.