Я создаю иногда большие файлы csv из информации db для пользователей, а затем загружаю - 100k или более строк. Кажется, у меня проблема с памятью во время создания csv на некоторых более крупных файлах. Вот пример того, как я сейчас обрабатываю создание csv.fputcsv - нехватка памяти при создании файлов большего размера
Есть ли способ обойти это? Первоначально был 32 МБ и изменил его на 64 МБ и все еще имел проблему.
//columns array
$log_columns = array(
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9'
);
//results from the db
$results = $log_stmt->fetchAll(PDO::FETCH_ASSOC);
$log_file = 'test.csv';
$log_path = $_SERVER['DOCUMENT_ROOT'].'/../user-data/'.$_SESSION['user']['account_id'].'/downloads/';
// if location does not exist create it
if(!file_exists($log_path))
{
mkdir($log_path, 0755, true);
}
// open file handler
$fp = fopen($log_path.$log_file, 'wb');
// write the csv column titles/labels
fputcsv($fp, $log_columns);
//are there any logs?
if($results)
{
//write the rows
foreach($results as $row)
{
//rows array
$log_rows = array(
$row['1'],
$row['2'],
$row['3'],
$row['4'],
$row['5'],
$row['6'],
$row['7'],
$row['8'],
$row['9']
);
//write the rows
$newcsv = fputcsv($fp, $log_rows);
}//end foreach
}
// there were no results so just return an empty log
else
{
$newcsv = fputcsv($fp, array('No results found.'));
}
//close handler
fclose($fp);
// if csv was created return true
if($newcsv)
{
return true;
}
ОБНОВЛЕНИЕ:
Используя время цикла выборки и вместо того, чтобы Еогеасп и fetchAll до сих пор производит ошибку памяти.
while($result = $log_stmt->fetch(PDO::FETCH_ASSOC))
Как это возможно, если я загружаю только одну строку за раз?
ОБНОВЛЕНИЕ 2:
я дополнительно отслеживаются это вниз к петле при использовании memory_get_usage();
echo (floor(memory_get_usage()/1024)).' kb<br />';
Перед время цикла начинается результат 4658 кб, а затем для каждой итерации время цикл увеличивается на 1kb каждые 2-3 цикла до тех пор, пока не достигнет допустимой памяти 32748 kb.
Что можно сделать для решения этой проблемы?
UPDATE 3:
игры вокруг больше с этим сегодня ... как это работает просто не имеет смысла для меня - я могу только предположить, что это странное поведение с GC PHP.
сценарий 1: Мой запрос получает все строки 80k и использует цикл while для вывода их. Используемая память составляет около 4500 КБ после запроса, а затем увеличивает 1 кб каждые две-три строки, которые выводятся в цикле. Память не выпускается, что когда-либо, и в какой-то момент она падает без достаточной памяти.
while($results = $log_stmt->fetch(PDO::FETCH_ASSOC))
{
echo $results['timestamp'].'<br/>';
}
сценарий 2: Мой запрос теперь петельные и получает 1000 строк за один раз с петлей внутри этого вывода каждой строки. Максимум памяти при 400k, когда он петлиет и завершает весь вывод без проблем с памятью.
Для этого примера я просто использовал счетчик 80 раз, так как знаю, что для извлечения более 80 тыс. Строк. На самом деле я должен был бы сделать это совершенно очевидно.
$t_counter = 0;
while($t_counter < 80)
{
//set bindings
$binding = array(
'cw_start' => $t_counter * 1000,
//some other bindings...
);
$log_stmt->execute($binding);
echo $t_counter.' after statement '.floor(memory_get_usage()/1024).' kb<br />';
while($results = $log_stmt->fetch(PDO::FETCH_ASSOC))
{
echo $results['capture_timestamp'].'<br/>';
}
echo $t_counter.' after while'.floor(memory_get_usage()/1024).' kb<br />';
$t_counter++;
}
Поэтому, я думаю, мой вопрос в том, почему первый сценарий имеет увеличение использования памяти и ничего не выпущено? В этом цикле while нет новых переменных, и все «повторно используется». То же самое происходит во втором сценарии только в другом цикле.
Вы пытались работать как концепция разбивки на страницы. Получите счетчик, а затем повторите его, чтобы создать csv. –
Я думаю, вы можете попробовать добавить '' '' ob_end_clean(); '' '' перед '' '' $ fp = fopen ($ log_path. $ Log_file, 'wb'); '' '' –
@rajeshujade - не следует ... что вы имеете в виду? У меня есть массив данных строки в $ results, тогда я использую цикл foreach, чтобы добавить каждую строку в csv ... – user756659