COPY, временное отключение триггеров/индексов в контролируемом окне и последующую дозагрузку метаданных.
Как оптимизировать bulk insert на миллионах строк?
Подробный ответ
Главная идея
Миллионы строк нельзя вставлять по одной. Основной выигрыш даёт уменьшение количества round-trip к базе и сокращение работы, которую СУБД делает на каждую строку: индексы, триггеры, проверки, WAL и блокировки.
Что обычно помогает
Пакетная вставка — отправлять данные батчами, а не отдельные
INSERTна каждую строку;COPY— в PostgreSQL это самый быстрый путь для больших объёмов;Транзакции — группировать большое количество строк в разумные коммиты, чтобы не платить за
COMMITна каждой записи;Временное отключение вторичных индексов — если это допустимо и индекс можно восстановить после загрузки;
Отключение лишней бизнес-логики — триггеры и сложные проверки могут сильно замедлять импорт.
Практический пример
COPY events (id, created_at, payload)
FROM '/path/events.csv'
WITH (FORMAT csv, HEADER true);Для API-загрузки часто используют пакетный INSERT ... VALUES (...), (...), (...) или вставку из staging-таблицы.
Что ещё важно
заранее подготовить данные, чтобы не тратить время на преобразования на стороне БД;
контролировать размер батча, чтобы не упереться в память или лимиты пакета;
загрузку в критичных системах делать в staging или через отдельную таблицу, а потом переключать данные атомарно.
Как ответить на собеседовании
Для bulk insert на миллионах строк я стараюсь использовать COPY или пакетные вставки, а не одиночные INSERT. Перед загрузкой думаю о стоимости индексов, триггеров и WAL, а если это безопасно, перегружаю данные через staging-таблицу и потом делаю атомарное переключение.
Оцени свой прогресс