Ankündigung

Einklappen
Keine Ankündigung bisher.

Große Daten in csv schreiben

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Große Daten in csv schreiben

    Tach,

    Fall: Ich möchte den Inhalt einer Tabelle nach bestimmten Kriterien auslesen und in eine CSV-Datei schreiben. Grundsätzlich kein Problem.

    Problem: Die Datenmenge übersteigt die in PHP eingestellen Größen. Es sollen ~150.000 Zeilen geschrieben werden, doch bei ~ 60.000 ist schluss.

    Welche Möglichkeiten gibt es da? Hatte mir zuerst überlegt das mit temporären Tabellen zu machen, habe aber noch nicht damit gearbeitet. Kennt ihr eine Möglichkeit dies zu bewerkstelligen? Es besteht nicht die Möglichkeit an der PHP.ini oder Apache oder sonst wo was zu verändern.

    Ich mache es so, dass die Daten in einer Schleife aus der Tabelle geholt werden und formatiert in ein Array geschrieben werden.

    Später kommt eine zweite Schleife, die dieses Array Zeile für Zeile in CSV-Datei schreibt, was bis zu den ca. 60.000 Zeilen auch einwandfrei klappt.

    Ich mache die ganze Sache (das rausholen aus der DB) mit AdoDB.
    fg


  • #2
    Hi.

    Wie sieht dein Code dafür aus? Verwendest du fputs oder fputcsv? Normalerweise ist die Größe "egal" - soweit ich weiß. Ich denke eher, dass irgendwann das Limit deines Server Platzes erreicht wurde, oder wenn das Skript länger als das Zeitlimit läuft, wird es abgeschossen (Fehler 500).

    Wolf29
    while (!asleep()) sheep++;

    Unterschätze nie jemanden der einen Schritt zurück geht! Er könnte Anlauf nehmen.

    Kommentar


    • #3
      ouh man, alles nochmal von vorne... (Eingabe gelöscht)

      PHP-Code:
      <?php
      //Statement
      $sql['main'] =  "...";


      $sql['count'] =  "...";

      $sum $db->getOne($sql['count']);

      echo 
      'Zu erzeugende Dateien: '. ($sum) .'<br>';

      $from 0;
      $to $step 10000;
      $zaehler 0;

      while(
      $from $sum)
      {
          
      $limit ' LIMIT '.$from.', '.$to;

          
      $rs $db->getArray($sql['main'] . $limit);

          
      $count count($rs);

          
      // Informationen nach Vorgabe formatieren
          // jeweils eine Zeile
          
      foreach($rs as $in => $ds)
          {
              
      $zaehler++;

              
      // (Daten formatiert speichern ($src)

              // Aktuelle Zeile speichern
              
      foreach ($src as $cell)
              {
                  
      $dst[$zaehler] .= $cell .'|';
              }
              
      $dst[$zaehler] .= "\n";
          }

          
      $c_count += $count;

          echo 
      $count.' erzeugt ('.$c_count.') '.     $limit ' (LIMIT '.$from.', '.$to .')<br>';

          
      $from += $step;

      }

      $file 'files/NamederDatei.csv';
      $fp fopen ($file"wb");
      $i 0;

      foreach (
      $dst as $line)
      {
          
      // Fehler
          
      if(!fwrite($fp$line))
          {
              echo 
      '<p style="padding: 4px; background: red; color: #fff;"><b>Fehler:</b> Die Datei '$file.' konnte nicht beschrieben werden</p>';
              exit;
          }
          
      // Anzahl Zeilen festhalten
          
      else $i++;
      }

      // Erfolgreich erstellt
      echo '<p style="padding: 4px; background: #cdffcc;">Die Datei <b>'.$file.'</b> wurde erfolgreich erstellt. Es wurden <b>'$i .'</b> Zeilen geschrieben.</p>';

      fclose($fp);
      ?>
      Es wird auch kein Fehler ausgegeben, sondern irgendwann wird einfach nicht mehr geschrieben (habe es getestet, es wird nicht mehr ins Array geschrieben, irgendwann)

      Zu erzeugende Dateien: ...
      10000 erzeugt (10000) (LIMIT 0, 10000)
      10000 erzeugt (20000) (LIMIT 10000, 10000)
      10000 erzeugt (30000) (LIMIT 20000, 10000)
      10000 erzeugt (40000) (LIMIT 30000, 10000)
      10000 erzeugt (50000) (LIMIT 40000, 10000)
      10000 erzeugt (60000) (LIMIT 50000, 10000)
      1510 erzeugt (61510) (LIMIT 60000, 10000)
      0 erzeugt (61510) (LIMIT 70000, 10000)
      0 erzeugt (61510) (LIMIT 80000, 10000)
      0 erzeugt (61510) (LIMIT 90000, 10000)
      0 erzeugt (61510) (LIMIT 100000, 10000)
      0 erzeugt (61510) (LIMIT 110000, 10000)
      0 erzeugt (61510) (LIMIT 120000, 10000)
      0 erzeugt (61510) (LIMIT 130000, 10000)
      0 erzeugt (61510) (LIMIT 140000, 10000)
      Habe dort eine Schleife eingebaut, um den Prozess etwas zu beschleunigen.

      Kommentar


      • #4
        150000 DS in ein Array zu prügeln, ist auch nicht gerade ein Pappenstiel. Wieso benutzt Du nicht reguläre Filefunktionen und gehst nach read-write-read-write vor?

        $rs = $db->getArray($sql['main'] . $limit);
        sieht auch verdächtig nach Query in Schleife aus.
        --

        „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
        Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


        --

        Kommentar


        • #5
          Zitat von nikosch Beitrag anzeigen
          150000 DS in ein Array zu prügeln, ist auch nicht gerade ein Pappenstiel. Wieso benutzt Du nicht reguläre Filefunktionen und gehst nach read-write-read-write vor?

          sieht auch verdächtig nach Query in Schleife aus.
          Ja, ich habe es so gemacht dass es das Hauptstatement in kleinere unterteilt (LIMIT ..., 10000).

          Sonst funktioniert überhaupt garnichts.

          Kommentar


          • #6
            Nachdem, was du gepostet hast, gibt es einfach keine weiteren Datensätze. Es liegt ja an keinem Timeout oder Memory-Limit, da das Script ja weiter läuft.

            Und warum wird die Summe nicht ausgegeben?
            PHP-Code:
            echo 'Zu erzeugende Dateien: '. ($sum) .'<br>'
            Code:
            Zu erzeugende Dateien: ...
            [EDIT]
            Achso, hast du unkenntlich gemacht, wie hier
            PHP-Code:
            $sql['main'] =  "...";
            $sql['count'] =  "..."
            Die wichtigste Information lässt du also weg - so geheim?
            Schonmal dran gedacht, dass die Statements vielleicht unterschiedliche Resultate liefern?

            Kommentar


            • #7
              Das Statement mit der Summe ist identisch mit dem Hauptstatement, nur habe ich die SELECT-Anweisung komplett durch COUNT(*) ersetzt.

              Und es stimmt wohl, irgendwas an dem Statement scheint wohl falsch gewesen zu sein. In einem hatte ich wohl was mit GROUP BY verwechselt (weggelassen). Nun ja, es funktioniert nun.

              Die Summe lese ich jetzt wohl komplett (umständlicher?) aus:

              PHP-Code:
              $from 0;
              $to $step 10000;
              $zaehler 1;

              do(
              $rs)
              {
                  
              $limit ' LIMIT '.$from.', '.$to;
                  
                  
              $sum += count($rs $db->getArray($sql[1] . $limit));
                  
                  
              $from += $step;
              }while(
              $rs);

              ... 
              Jetzt stimmen die Ergebnisse auch.

              Vielen Dank,

              fg

              Kommentar

              Lädt...
              X