Что делать если файл для загрузки в базу слишком большой и не помещается в память
Что проверяют
Знаете ли ленивую обработку в Python и умеете ли грузить в базу пакетно, а не построчными вставками. Память тут решается легко, а вот время на этом вопросе теряют почти все.
Как отвечать
Файл читается потоком. Никаких read() и readlines() на весь объём.
- Текст построчно: итерация по файловому объекту ленива и держит в памяти буфер, а не файл. CSV через
csv.readerповерх того же объекта. - JSON целиком разобрать нельзя, поэтому либо построчный формат (JSON Lines), либо потоковый разбор.
- Пачки: копить записи в список фиксированного размера, отдавать в базу и очищать. Несколько тысяч строк на пачку обычно оптимальны.
- Загрузка в PostgreSQL:
COPYиз потока на порядок быстрее, чемINSERTна строку, и данные при этом в памяти не накапливаются. Нужен апсерт, значитCOPYво временную таблицу и одно слияние запросом. - pandas с
chunksizeуместен, когда нужна именно обработка средствами pandas. Сам по себе он не быстрее и памяти просит заметно щедрее чистого потока. - Генераторы по всей цепочке: один
list(...)в середине сводит потоковую обработку на нет.
Отдельно про надёжность: коммитить по пачкам и уметь продолжить с места обрыва, иначе падение на середине откатит часы работы.
Где спотыкаются
Читают потоком, но вставляют по одной строке. Память сэкономили, время увеличили в десятки раз: каждая вставка это отдельный сетевой обмен и отдельная транзакция.
Открывают файл в бинарном режиме и работают с прочитанным как с текстом. Из бинарного потока приходят байты, сравнение с текстовым литералом молча не срабатывает, и строки тихо отбрасываются.
Оборачивают весь файл в одну транзакцию. Она распухает, держит блокировки и откатывается целиком на первой битой строке, а повторный запуск начинается с нуля.