2015-04-15 22 views
1

我創建使用Excel工作表:PHPExcel Writer對象使用大量的內存和超時最終

  1. 笨2.2.1
  2. PHP 25年5月4日
  3. 的Apache 2.4.7
  4. XAMPP 1.8.2
  5. PHPExcel 1.8.0

我從數據庫79列獲取35000行(大部分是空的),並寫入Excel文件(Excel5)。

它適用於30000行,峯值內存使用率爲1.44GB,文件大小爲24MB。但是,當我去爲35000個超時說,

致命錯誤:內存(分配1780219904)(試圖分配17301483個字節)在E:\ XAMPP \ htdocs中\項目名\程序\庫\ PHPExcel \作家\ Excel5 \ BIFFwriter.php on line 144

當我創建PHPExcel對象時,它最終使用了大量的內存和超時。我在php.ini文件中設置了「memory_limit = -1」和「max_execution_time = 1000」,並在PHPExcel中嘗試了不同的緩存存儲方法。

我在控制器算法看起來像這樣

public function write_controller() {  
    error_reporting(E_ALL); 
    ini_set("display_errors", 1); 
    ini_set('memory_limit', '-1'); //-1 for unlimited memory 
    $dir = "assets/output/"; 

    //FIRST CHECK IF PREVIOUS FILE EXISTS OR NOT 
    $this->clear_directory($dir); 

    // Loading PHPExcel library 
    $this->load->library('PHPExcel'); 
    $this->load->library('PHPExcel/IOFactory'); 

    $cacheMethod = PHPExcel_CachedObjectStorageFactory::cache_to_phpTemp; 
    $cacheSettings = array('memoryCacheSize' => '5000MB', 'cacheTime' => '1000'); 

    PHPExcel_Settings::setCacheStorageMethod($cacheMethod, $cacheSettings); 

    //First Create the xls file and then insert rest of the data 
    $objPHPExcel = new PHPExcel(); 
    $objPHPExcel->getProperties()->setTitle("export")->setDescription("none"); 

    //activate sheet number 1 
    $objPHPExcel->setActiveSheetIndex(0); 

    //Setting font styles 
    $objPHPExcel->getActiveSheet()->getDefaultStyle()->getFont()->setName('Arial')->setSize(8)->setBold(false); 

    //Setting number format as TEXT 
    $objPHPExcel->getActiveSheet()->getDefaultStyle()->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_TEXT); 

    //Freezing first top row 
    $objPHPExcel->getActiveSheet()->freezePane('A2'); 


    $objWorksheet = $objPHPExcel->getActiveSheet(); 

    $row1 = 1; 

    $objWorksheet->setCellValueByColumnAndRow(0, $row1, "Site name"); 
    $objWorksheet->setCellValueByColumnAndRow(1, $row1, "Vendor_1"); 
    $objWorksheet->setCellValueByColumnAndRow(2, $row1, "Status"); 
    $objWorksheet->setCellValueByColumnAndRow(3, $row1, "Easting"); 
    $objWorksheet->setCellValueByColumnAndRow(4, $row1, "Northing"); 
    $objWorksheet->setCellValueByColumnAndRow(5, $row1, "Sector_1"); 
    . 
    . 
    . 
    //Rest of the 74 columns 

    $style = array(
     'alignment' => array(
      'horizontal' => PHPExcel_Style_Alignment::HORIZONTAL_CENTER, 
      'vertical' => PHPExcel_Style_Alignment::VERTICAL_CENTER) 
    ); 

    $objWorksheet->getDefaultStyle()->applyFromArray($style); 

    $objWriter = IOFactory::createWriter($objPHPExcel, 'Excel5'); 

    $saved_location ='assets/output/Piano11.xls'; 
    $objWriter->save($saved_location); 

    //Now reading the saved xls file 
    $objReader = new PHPExcel_Reader_Excel5(); 

    $newPHPExcel = $objReader->load($saved_location); 

    $newWorksheet = $newPHPExcel->getActiveSheet(); 

    //Now insert rest of the data from Piano table which will come from database 
    $table_name = 'piano_test'; 

    $query = $this->db->get('tbl_piano'); 

    if (!$query) { 
     return false; 
    } 

    // Fetching the data from table 
    $fields = $query->list_fields(); 

    $row = 2; 
    foreach ($query->result() as $data) { 
     set_time_limit(0); 
     $col = 0; 
     foreach ($fields as $field) { 
      $newWorksheet->setCellValueByColumnAndRow($col, $row, $data->$field); //<- This skips leading 0s 
      $col++; 
     } 
     $row++; 
    } 

    $newobjWriter = IOFactory::createWriter($newPHPExcel, 'Excel5'); 
    $newobjWriter->save('assets/output/Piano11.xls'); 

    echo 'Memory peak usage: <b>'.$this->convert(memory_get_peak_usage(true)).'</b><br/>'; 
    gc_collect_cycles();//garbage collector 
    echo 'inserted.'; 
} 

任何解決方案,我怎麼可以最大限度地減少內存使用&執行時間?還是有其他解決方案?還是應該改變我的算法?

+0

清除內存,計算需要的數量與清除你可以使用的內存,然後使用memory_limt http://davidwalsh.name/increase-php-memory-limit-ini_set ...這些都是我所需要的,我處理地理數據庫80 + gb ..你會有內存泄漏或什麼的。有時更好的批量這個..檢查你的PHP版本是否有已知的內存泄漏,因爲這經常發生。嘗試https://www.airpair.com/php/fatal-error-allowed-memory-size,否則你可能會走運。在某種程度上它始終是個問題 – Mayhem

+0

當你在這個腳本中創建多個Writer時,您可能想要在爲Writer調用save()方法後取消設置每個對象 –

+0

您可以看到我已將內存限制設置爲-1,這是所有可能的內存分配。 –

回答

1

您使用緩存phptemp,但設置

$cacheSettings = array('memoryCacheSize' => '5000MB', 'cacheTime' => '1000'); 

這意味着PHPExcel會使用你的PHP內存5000MB的(5GB),其開始利用phptemp的緩存之前....我想,如果你有php.ini的最大內存設置允許PHP使用吃驚的是多少內存

您應該使用memoryCacheSize值低得多,也許512MB,這意味着PHPExcel將只使用PHP 512MB內存在切換到使用php之前緩存單元格數據:// temp

+0

我已經改變和測試它,但是因爲你是PHPExcel主持人我問你,有什麼可能(或最好)緩存方法來編寫excel工作表?另一方面,如果執行時間和內存不是我的問題,我怎麼能解決這個問題? –

+0

就內存而言,最有效的緩存方法是SQLite或SQLite3,但它比其他一些方法更慢......實際上沒有「最好」的東西,因爲它取決於個人情況 –

+0

如果您正在工作對於大量數據,將任務作爲後臺進程運行通常也是一個好主意,可能來自命令行而不是Web請求,因爲您沒有時間限制。 –

相關問題