2016-03-31 17 views
0

我有MySQL InnoDB表,其中有100萬行,我選擇100K行導出。表格大約有200列。PHP,MySQL - 載入大約100k條記錄並將它們導出到xml

我有什麼迄今所做的:

  1. 不是*

    SELECT列1,列2,... FROM MY_TABLE WHERE刪除= 0全選 - 負載100K記錄

  2. 使用XMLWriter php庫沖洗

    $writer = new XMLWriter(); 
    $writer->openMemory(); 
    $writer->setIndent(true); 
    $writer->startDocument('1.0', 'UTF-8'); 
    $writer->startElement('export'); 
    
    $iterator = 0; 
    $data = $this->getData(); 
    
    foreach($adverts as $advert) { 
        $writer->startElement('ad'); 
        $writer->writeElement('id', $data->id); 
        // .. other columns 
    
        $writer->endElement(); // end ad 
    
        if (0 == $iterator % 1000) { 
         file_put_contents($this->getFilePath(), $writer->flush(TRUE), FILE_APPEND); 
        } 
    
        $iterator++; 
    } 
    

但我仍然有致命錯誤:允許的內存大小......字節耗盡

是否有任何其他方式如何優化?我想我可以用其他方式從數據庫加載數據,比如在第一輪加載id,然後選擇IN(10k_ids),但我還沒有測試這個想法。

謝謝您的意見。


我有非常類似的問題在How to export HTML table with 100K records with number formatting without memory exhaust

但沒有辦法如何實現低內存消費。

+1

人仍然使用XML? ;-) – Strawberry

+0

寫幾個文件,如每個10K? – michi

+0

它必須是一個文件。我的想法是用數據庫的foreach加載10k,所以在變量中保存了更小的數據 –

回答

0

我發現解決方案,問題是我加載了很多數據。

我發3個升級:

  1. 使用功能登錄存儲器限制

    /** 
    * @param $message 
    */ 
    protected function logMemoryUsage($message) 
    { 
        Debugger::log($message . ": " . memory_get_usage()/1048576 ." MB"); 
    } 
    
  2. 然後我使用的fopen +的fwrite + FCLOSE代替file_put_contents

    $file = fopen($this->getFilePath(), 'a+'); 
    fwrite($file, $writer->flush(TRUE)); 
    fclose($file); 
    
  3. 負載數據在循環中(一次只能記錄10K條記錄)

    $this->logMemoryUsage("Memory usage before load"); 
    $data = $this->getData($lastId); 
    
    do { 
        $this->logMemoryUsage("Memory usage"); 
        $lastId = NULL; 
    
        foreach($data as $item) { 
         $writer->startElement('ad'); 
         $writer->writeElement('id', $item->id); 
         ... 
    
         if (0 == $iterator % 5000) { 
          fwrite($file, $writer->flush(TRUE)); 
         } 
    
         $lastId = $item->id; 
         $iterator++; 
        } 
    
        $data = $this->getData($lastId); 
    
    } while(!empty($data)); 
    
    $this->logMemoryUsage("Memory usage after"); 
    fwrite($file, $writer->flush(TRUE)); 
    fclose($file); 
    
    
    
    public function getData($fromId = NULL, $limit = 10000) 
    { 
        $data = db::query("SELECT a,b,c FROM my_table WHERE deleted=0 AND id>? ORDER BY id ASC LIMIT ?", $fromId, $limit)->fetchAll(); 
    } 
    

而現在的輸出是:

export start 
    Memory usage before load: 3.6202011108398 MB 
    Memory usage: 59.487106323242 MB 
    Memory usage: 124.53610229492 MB 
    Memory usage: 124.89745330811 MB 
    Memory usage: 124.43883514404 MB 
    Memory usage: 124.20503234863 MB 
    Memory usage: 124.2151184082 MB 
    Memory usage: 124.46990966797 MB 
    Memory usage: 106.50185394287 MB 
    Memory usage: 53.009048461914 MB 
    export end 
相關問題