2016-03-31 15 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 
相关问题