Вопрос проверяет понимание приёмов работы с большими файлами (Excel/CSV/логами) без вылета по памяти.
Большие файлы нельзя загружать целиком в память — их нужно обрабатывать потоково. Для этого используют построчное чтение или чтение небольшими порциями (батчами), где каждая порция данных сразу обрабатывается и сбрасывается из памяти. Также важно ограничивать размер батча, использовать генераторы, отключать ненужное кеширование и делить работу на несколько шагов (например, предварительный парсинг и отдельную фазу записи в БД). Такой подход позволяет обрабатывать файлы хоть на гигабайты, не упираясь в лимит памяти PHP.
Основная цель — никогда не держать весь файл в памяти. Работать нужно кусками, а обработанные данные как можно быстрее освобождать.
Определение: Потоковая обработка — это чтение и обработка файла небольшими кусками (строками, блоками), без загрузки всего содержимого в память.
Для текстовых форматов (CSV, лог-файлы):
использовать fopen, fgets, fgetcsv
сразу обрабатывать строку и забывать о ней
не накапливать массив из тысяч строк, если это не нужно
php
$handle = fopen($filepath, 'r');
while (($row = fgetcsv($handle)) !== false) {
processRow($row); // обработка строки
// никаких больших массивов
}
fclose($handle);
Для Excel (XLSX) — использовать библиотеки со streaming-режимом (Spout, PhpSpreadsheet в режиме чтения по строкам).
Определение: Батч — это небольшая порция данных, обрабатываемая единым блоком (обычно 100–1000 строк).
Зачем:
уменьшить количество SQL-запросов (bulk insert)
контролировать память (размер батча фиксирован)
обновлять прогресс и логировать между батчами
Паттерн:
читаем строки по одной
складываем в батч
при достижении лимита — обрабатываем батч и очищаем память
php
$batch = [];
$batchSize = 1000;
while (($row = fgetcsv($handle)) !== false) {
$batch[] = normalizeRow($row);
if (count($batch) >= $batchSize) {
saveBatchToDb($batch);
$batch = []; // очищаем массив
}
}
if ($batch) {
saveBatchToDb($batch);
}
Так мы всегда контролируем, сколько именно данных держим в памяти.
yield для ленивой обработкиГенераторы позволяют превратить чтение файла в ленивый источник данных:
Определение: Ленивая обработка — вычисление значений по мере запроса, а не заранее.
php
function readCsv(string $filepath): Generator {
$handle = fopen($filepath, 'r');
while (($row = fgetcsv($handle)) !== false) {
yield $row;
}
fclose($handle);
}
Дальше:
php
foreach (readCsv($path) as $row) {
processRow($row);
}
Генератор держит в памяти только одну текущую строку + немного состояния.
Для сложных сценариев полезно разделять:
Фаза чтения/парсинга
разбираем файл
нормализуем данные
складываем в промежуточное хранилище (например, временную таблицу или очередь)
Фаза бизнес-логики
читаем нормализованные данные
делаем валидацию, проверку связей, сложные операции
Это помогает:
проще повторно запускать обработку
легче логировать и отлаживать
не завязываться жёстко на формат файла
Несколько практических моментов:
Не накапливать массивы без необходимости
избегать allRows[] = $row на миллионы строк
чистить большие структуры ($batch = []; unset($buffer);)
Вызывать gc_collect_cycles() при подозрении на утечки
не злоупотреблять, но иногда полезно в больших скриптах
Не держать открытые ресурсы
закрывать файлы, соединения, курсоры
Если файл очень большой:
можно физически разбить его на несколько более мелких файлов
либо заранее (на стороне отправителя)
либо на бэкенде (например, резать CSV по N строк и обрабатывать по частям)
Каждый кусок становится отдельной задачей в очереди.
Почти всегда обработка больших файлов:
запускается в фоне (воркеры)
не делается в HTTP-запросе
состояние хранится в БД (progress, status)
есть retry на уровне задач
Это снижает риск падения из-за таймаутов и даёт контролируемое использование ресурсов.
Эффективная обработка больших файлов строится вокруг:
потокового чтения (строка за строкой)
батчей фиксированного размера
ленивой обработки через генераторы
разделения этапов работы
вынесения тяжёлой логики во фоновые процессы
Такой подход позволяет безопасно обрабатывать очень большие файлы, не упираясь в лимиты памяти PHP.