PHP-скрипту не хватает памяти, когда большие объемы данных записываются в файл пакетами - PullRequest
0 голосов
/ 03 января 2012

У меня постоянно возникают проблемы с моим скриптом, использующим нашу память.

Мне нужен скрипт, чтобы пройтись по каждому клиенту в базе данных, а затем получить все данные о продукте и сгенерировать текстовый файл.Каждый клиент может иметь от 1 до 100 000 товаров.

Я вывожу данные о продукте партиями по 1000 и записываю в файл, чтобы попытаться остановить выполнение сценария по тайм-ауту.Это значительно улучшилось, однако, у меня все еще есть проблемы с клиентами, у которых есть большое количество продуктов.Кажется, у него проблемы с клиентами, у которых более 5000 продуктов.

Кажется, что перестает записывать в файл после 5-го пакета (5000 продуктов), но браузер просто зависает, как будто он все еще генерирует файл, но продуктнет в файле никогда не увеличится.

Кто-нибудь может помочь?

set_time_limit(0);

$db = new msSqlConnect('db');

$select = "SELECT customer FROM feeds ";

$run = mssql_query($select);

while($row = mssql_fetch_array($run)){
    $arg = $row['customer'];
    $txt_file = 'shopkeeper/'. $arg . '.txt';   
    $generated = generateFeed($db, $arg, $txt_file);

    if ($generated){
        $update = "UPDATE feeds SET lastGenerated = '$generated' WHERE customer = '$arg' ";
        mssql_query($update);
    }

}

function generateFeed($db, $customer, $file){
    //if file already exists then delete file so can write new file
    if (file_exists($file)){
        unlink($file);
    }   

    $datafeed_separator = "|";

    //get product details       
    $productsObj = new Products($db, customer)

    //find out how many products customer has
    $countProds = $productsObj->countProducts();

    $productBatchLimit = 1000;          

        //create new file
    $fh = fopen($file, 'a');

    $counter = 1;

    for ($i = 0; $i < $countProds; $i += $productBatchLimit) {

        $txt = '';

        $limit = $productBatchLimit*$counter;

        $products = $productsObj->getProducts($i, $limit);      

            foreach($products as $product){

                    $txt .=   
                    $prod_name . $datafeed_separator . 
                    $prod_brand . $datafeed_separator . 
                    $prod_desc . $datafeed_separator .
                    $prod_price . $datafeed_separator . "\n";   
                }
            }   

        fwrite($fh, $txt);
        flush();
        $counter++;     
    }
    fclose($fh);

    $endTime = date('Y-m-d H:i:s');

    return $endTime;
}

1 Ответ

1 голос
/ 03 января 2012

Я вижу одну вещь, которая может помочь при использовании вашей памяти. Если вы переместите fwrite () внутри цикла foreach, вы можете освободить $ txt также внутри цикла. Так что это будет что-то вроде:

foreach($products as $product){
  $txt =   
  $prod_name . $datafeed_separator . 
  $prod_brand . $datafeed_separator . 
  $prod_desc . $datafeed_separator .
  $prod_price . $datafeed_separator . "\n";  

  fwrite($fh, $txt);
}

Это предотвратит рост $ txt, если у вас много продуктов.

...