PHP сокращение использования памяти при использовании fputcsv в php: / / output
Мы столкнулись с немного странной проблемой. Все происходит вот так. У нас есть большие объемы данных, которые мы должны вывести клиенту. Эти файлы данных не могут быть предварительно построены, они должны обслуживаться из живых данных.
Моим предпочтительным решением было записать в CSV строку за строкой из выборки, подобной этой:
while($datum = $data->fetch(PDO::FETCH_ASSOC)) {
$size += fputcsv($outstream, $datum, chr(9), chr(0));
}
Это обошло много нелепого использования памяти (чтение 100000 записей в память сразу-плохой Моджо), но у нас все еще есть затяжные проблемы для больших таблиц, которые только будет становиться все хуже по мере увеличения объема данных. И, пожалуйста, обратите внимание, что нет никакого разделения данных; они не загружают в сегментах года, но они загружают все свои данные, а затем сегментируют их сами. Это соответствует требованиям; я не в состоянии изменить это настолько, насколько это полностью устранит проблему.
В любом случае, на самой большой таблице у него заканчивается память. Одним из решений является увеличение доступной памяти, что решает одну проблему, но предполагает создание проблемы с загрузкой сервера позже или даже сейчас, если загружается более одного клиента.
В этом случае $outstream-это:
$outstream = fopen("php://output",'w');
Который кажется довольно очевидным не совсем физическое расположение диска. Я мало что знаю о php: / / output с точки зрения того, где находятся данные, прежде чем они будут отправлены клиенту, но кажется очевидным, что есть проблемы с памятью при простой записи таблицы базы данных manifold в csv с помощью этого метода.
Чтобы быть точным, промежуточный блок позволяет около 128 Мб для PHP, и этот вызов в частности был коротким около 40mb (он пытался выделить еще 40mb.) Это кажется немного странным для поведения, так как вы ожидаете, что он попросит памяти в меньших частях.
Кто-нибудь знает, что можно сделать, чтобы справиться с этим?
1 ответ:
Таким образом, похоже, что потребление памяти вызвано буферизацией выходных данных Zend Framework. Лучшее решение, которое я придумал, было таково.
Выполнение ob_end_clean () непосредственно перед началом потоковой передачи файла клиенту. Этот конкретный экземпляр ZF не будет производить никакой нормальной продукции или делать что-либо еще после этого момента, поэтому осложнений не возникает. Что странно происходит (возможно, с точки зрения пользователя) , так это то, что они действительно получают файл в потоковом режиме. их.
Вот код:
ob_end_clean(); while($datum = $data->fetch(PDO::FETCH_ASSOC)) { $size += fputcsv($outstream, $datum, chr(9), chr(0)); }Использование памяти(в соответствии с функцией memory_get_peak_usage (true), предложенной где-то на форуме ZF) сократилось с 90 мегабайт до 9 мегабайт, что и было использовано здесь на моем поле разработки до любого чтения файла.
Спасибо за помощь, ребята!
Comments