У меня есть таблица mysql, в которой каждая запись может иметь неограниченные пользовательские поля (модель EAV, не имеет значения), и каждое поле может иметь неограниченные параметры, и каждый параметр может иметь неограниченные значения.
Сейчас я пытаюсь создать инструмент экспорта, который будет экспортировать все эти настраиваемые поля со своими значениями, то есть: name => пары значений для каждого поля. Это не важная часть, здесь просто подчеркнуть, что мы говорим о множестве запросов mysql для одной записи и что размер экспорта будет довольно большим.Экспорт большого CSV-файла
Для каждой строки из моей основной таблицы я должен сделать около 100 отдельных запросов sql для получения полей, полей и значений полей. Эти запросы довольно быстрые, потому что все они используют правильные индексы, но все же мы говорим о 100 запросах для одной записи, и я ожидаю иметь около 50 тыс. Записей в моей основной таблице только для начала.
Прямо сейчас, что я делаю это:
set_time_limit(0);
ini_set('memory_limit', '1G');
ini_set("auto_detect_line_endings", true);
$count = $export->count();
$date = date('Y-m-d-H-i-s');
$fileName = CHtml::encode($export->name) .'-'. $date . '.csv';
$processAtOnce = 100;
$rounds = round($count/$processAtOnce);
header("Content-disposition: attachment; filename={$fileName}");
header("Content-Type: text/csv");
$headerSet = false;
for ($i = 0; $i < $rounds; ++$i) {
$limit = $processAtOnce;
$offset = $i * $processAtOnce;
$rows = $export->find($limit, $offset);
if (empty($rows)) {
continue;
}
$outStream = fopen('php://output', 'w');
if (!$headerSet) {
fputcsv($outStream, array_keys($rows[0]), ',', '"');
$headerSet = true;
}
foreach ($rows as $row) {
fputcsv($outStream, array_values($row), ',', '"');
}
echo fgets($outStream);
fclose($outStream);
}
В основном я рассчитывать все записи и я «постраничный» их на экспорт, а затем запустить через страницу для загрузки Avoin слишком много SQL результатов сразу.
Мне интересно, если это действительный подход? Есть предположения?
Моей альтернативой было бы считать все записи, разделить их на «страницы» и для каждой страницы выполнить запрос ajax (рекурсивная функция, вызванная после успешного выполнения предыдущего запроса). При выполнении запроса ajax обрабатывайте, возможно, 1k записей сразу (эти 1k также будут разбиты, как в приведенном выше примере, запустите внутренне 10 раз с 100 результатами, например), напишите их во временный каталог (например, part-1.csv, part-2.csv), а в конце, когда все записи обрабатываются, создайте архив из папки, содержащей все части csv, и заставьте браузер загрузить ее, а затем удалите ее с сервера (window.location.href изнутри последний вызов ajax).
Это хорошая альтернатива вышесказанному?
Обратите внимание: моя цель - ограничить объем использования памяти, поэтому я думаю, что второй подход поможет мне больше.
Пожалуйста, дайте мне знать, что вы думаете.
Спасибо.
Если ваши данные структурированы, почему бы вам не выбрать формат JSON вместо CSV? Просто «первая мысль» ... – Powerslave
Он будет использоваться в OpenOffice/Office и импортирован в другие системы, поддерживающие только csv, и json не является вариантом для этого, он должен быть csv :) – Twisted1919