2014-10-06 4 views
0

Я создаю иногда большие файлы 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 нет новых переменных, и все «повторно используется». То же самое происходит во втором сценарии только в другом цикле.

+0

Вы пытались работать как концепция разбивки на страницы. Получите счетчик, а затем повторите его, чтобы создать csv. –

+0

Я думаю, вы можете попробовать добавить '' '' ob_end_clean(); '' '' перед '' '' $ fp = fopen ($ log_path. $ Log_file, 'wb'); '' '' –

+0

@rajeshujade - не следует ... что вы имеете в виду? У меня есть массив данных строки в $ results, тогда я использую цикл foreach, чтобы добавить каждую строку в csv ... – user756659

ответ

1

fetchВсе извлекает все записи, которые не просто запрашивают его и выполняют цикл while с помощью fetch, тогда ему не нужно загружать весь набор результатов в память.

http://php.net/manual/en/pdostatement.fetch.php

+0

Это тоже будет 100k плюс выборки ... Я могу использовать fetchAll и получить полный результат почти сразу. – user756659

+0

Использование 'while ($ result = $ log_stmt-> fetch (PDO :: FETCH_ASSOC))' все еще вызывает ошибку памяти. – user756659

+0

Обновлено op ... есть ли у вас какие-либо ответы относительно того, почему два сценария ведут себя по-разному с точки зрения использования памяти? – user756659

-1

Я использую РНР Csv себя, я даже использовать его в качестве системы Databse (NoSQL) попробовать

CSV код для чтения <?php
$CSVfp = fopen("filename.csv", "r"); if($CSVfp !== FALSE) { $con=1; while(! feof($CSVfp)) { do something }?>

**csv code for writting ** 

<?php 
$list = array 
(
"edmond,dog,cat,redonton", 
"Glenn,Quagmire,Oslo,Norway", 
);$file = fopen("filename.csv","w");foreach ($list as $line)  

{fputcsv($file,explode(',',$line));}fclose($file); ?> 
+0

Я думаю, что вы пропустили точку сообщения - этот код по существу делает то же самое, что и я. Теперь попробуйте ваши с 80k строк в вашем массиве $ list. – user756659

0

Тогда я думаю вы должны попробовать прочитать файлы в битах. Прочитайте их и добавьте в один файл csv, таким образом вы освободите память во время процесса. Вы можете сделать счет (*), но попытайтесь найти общий счет перед множественной коллекцией

+0

Итак, подсчитайте (*) запрос, чтобы получить общее количество, а затем вытащите его несколько раз, используя лимиты? Или есть более предпочтительный метод для этого? – user756659

 Смежные вопросы

  • Нет связанных вопросов^_^