2016-03-31 10 views
0

1 milyon satıra sahip MySQL InnoDB tablomuz var ve ihracat için 100K satır seçiyorum. Tabloda yaklaşık 200 sütun var.PHP, MySQL - yaklaşık 100 bin kayıt yükleyin ve bunları xml'ye aktarın

şimdiye kadar ne yaptım:

  1. *

    SEÇ sütun1, sütun2 ... my_table GELEN silinmiş = 0 ile tüm seçemezsiniz - Yük 100k kayıtları

  2. floş

    $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++; 
    } 
    
ile

kullanarak XMLWriter php kütüphanesi

Ama yine de önemli bir hatam var: İzin verilen bellek boyutu ... bayt bitkin

Bunu nasıl optimize edebileceğiniz başka yollar var mı? Sanırım veriyi başka yollardan yükleyebilirim, örneğin ilk turda sadece ids yükler ve sonra IN'yi (10k_ids) seçebilirim, ama bu fikri henüz test etmiyorum.

Görüşleriniz için teşekkür ederiz.


Ben How to export HTML table with 100K records with number formatting without memory exhaust

gibi çok benzer bir soru var ama düşük bellek tüketimi nasıl ulaşılacağını bir yolu yoktur.

+1

İnsanlar hala XML kullanabilirsiniz? ;-) – Strawberry

+0

Her biri 10k gibi birkaç dosya yazabilir misiniz? – michi

+0

bir dosya olmalı. Benim fikrim veritabanından foreach ile 10k yük oldu, böylece değişken daha küçük veri kaydedildi –

cevap

0

Çözümü buldum, sorun çok fazla veri yükledim.

I 3 yükseltmeleri yapılan:

/** 
* @param $message 
*/ 
protected function logMemoryUsage($message) 
{ 
    Debugger::log($message . ": " . memory_get_usage()/1048576 ." MB"); 
} 
  • sonra kullanmak bellek sınırı açmak için

    1. kullanım işlevi Fopen + fwrite + fclose yerine file_put_contents

      $file = fopen($this->getFilePath(), 'a+'); 
      fwrite($file, $writer->flush(TRUE)); 
      fclose($file); 
      
    2. yükü döngü içindeki veriler (bir seferde sadece 10k kayıt)

      $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(); 
      } 
      

    Ve çıkış şimdi:

    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 
    
  • İlgili konular