Andreas: Sehr große Datenmenge in eine Datenbank schreiben

Hallo,

ich habe foldendes Problem.
Ich ziehe eine sehr große Menge an Daten aus einer Informix Datenbank. Diese möchte ich in eine MySQL Datenbank schreiben.

Zuerst hatte ich eine Schleife die aus 3 verschiedenen Tabellen die erforderlichen Daten für einen Eintrag ausliest und dann diesen "einen" Eintrag per Insert in meine MySql DB schreibt.Dann holt er den nächsten aus der Informix DB und schreibt diesen wieder in die My SQL DB, usw...

Jetzt habe ich es so das er mir mit jedem einzelnen Datensatz einen String zusammenbaut der wenn er komplett ist, alle Daten mit einem einzigen Insert in die MySql DB schreibt.

Das ist jetzt wesentlich schneller reicht aber trotzdem nicht aus wenn ich ca. 8000 Datensätze hab, bekomme ich ein Timeout Fehler im Browser.

Was gibts denn noch für eine Möglichkeit mein Vorhaben zu realisieren? Vieleicht alles in ein Array schreiben und dann damit arbeiten?

Bin dankbar für jede Hilfe.

Gruß
Andreas

  1. Hello,

    also alles in einen String zu schreiben erscheint mir schon in Anbetracht der Datenmenge eine schlechte Idee. Davon mal ganz abgesehen, dass String-Konkatenationen in den meisten Programmiersprachen keine besonders performanten Operation sind. Das mit dem Array wäre eine Möglichkeit. Ich würde auf jeden Fall zunächst versuchen stoßweise, wenn nicht sogar datensatzweise, zu arbeiten, aber nicht alles auf einmal. Bei sowas kann einem auch immer mal das Transaktionsprotokoll der Datenbank überlaufen oder die Indexaktualisierung dauert zu lange. Generell kann es aber in Anbetracht des Datenumfangs sein, dass dein Ziel nur mit einer höheren maximum execution time realisierbar ist. Oder du verteilst du Operation auf mehrere nacheinander laufende Skripte, so eine Art "Blättern" nur für den Vorgang und automatisch, also exemplarisch "starte go.php?offset=0, lies 100 Datensätze ab 0, schreibe 100 Datensätze, leite weider zu go.php?offset=99, ..."

    MfG
    Rouven

    --
    -------------------
    He is entertaining both out of the car and in the car because if you tell him that a corner is almost flat then he is the guy who is going to try to take it flat even if it means shunting it the other side of it, he will come with the data and say 'hey, I may have crashed and destroyed the car, but I was flat-out'. That is an interesting quality that he has!  --  Team Member on Jacques Villeneuve
  2. Hallo!

    Das ist jetzt wesentlich schneller reicht aber trotzdem nicht aus wenn ich ca. 8000 Datensätze hab, bekomme ich ein Timeout Fehler im Browser.

    Wenn es über Webinterface sein muss, dann würde ich es häppchenweise pro Seitenaufruf machen. Einfach pro Seitenaufruf ein paar Hundert (was sich halt als locker machbar erweist) Datensätze kopieren und dann per header(Location: ...) oder per meta refresh die Seite so lange sich selber aufrufen lassen bis alle Datensätze durch sind.
    Über eine Sessionverwaltung musst du dir halt merken welcher der aktuelle Datensatz ist, mit dem fortgesetzt werden soll.

    Der Nachteil dabei ist aber, dass du das ganze in verschiedenen Transaktionen abwickelst und nicht in einer einzigen. Das kommt jetzt auf denien Anwendungsfall an ob das praktikabel ist oder nicht.

    mfg
      frafu

  3. echo $begrüßung;

    bekomme ich ein Timeout Fehler im Browser.

    Wer erzeugt den Fehler? Doch sicher nicht der Browser. Wenn es PHP ist, dann kannst du die max_execution_time zu verändern versuchen.

    Ich ziehe eine sehr große Menge an Daten aus einer Informix Datenbank. Diese möchte ich in eine MySQL Datenbank schreiben.

    Ist dieses eine einmalige Angelegenheit oder muss das regelmäßig passieren und möglicherweise für technisch weniger geübte Personen per Knopfdruck gemacht werden?

    Was gibts denn noch für eine Möglichkeit mein Vorhaben zu realisieren?

    Alternativen wären:

    • PHP auf der Kommandozeile auszuführen, dann gibt es kein Timeout.
    • Eine Textdatei mit den INSERT-Statements erzeugen und diese über MySQLs Kommandozeilentool an MySQL zu verfüttern.
    • Eine CSV-Datei erzeugen und diese über MySQLs Kommandozeilentool mysqlimport an MySQL zu verfüttern.

    echo "$verabschiedung $name";

    1. echo $begrüßung;

      • PHP auf der Kommandozeile auszuführen, dann gibt es kein Timeout.

      Ich korrigiere mich präzisierend: Der Timeout von max_execution_time schlägt hier auch zu, aber er ist per Default auf 0 gesetzt. Ein Umschreibversuch in der php.ini ändert daran nichts, aber man kann zur Laufzeit den Wert anders setzen.

      echo "$verabschiedung $name";

  4. Tach auch.

    ich habe foldendes Problem.
    Ich ziehe eine sehr große Menge an Daten aus einer Informix Datenbank. Diese möchte ich in eine MySQL Datenbank schreiben.

    Zuerst hatte ich eine Schleife die aus 3 verschiedenen Tabellen die erforderlichen Daten für einen Eintrag ausliest und dann diesen "einen" Eintrag per Insert in meine MySql DB schreibt.Dann holt er den nächsten aus der Informix DB und schreibt diesen wieder in die My SQL DB, usw...

    Jetzt habe ich es so das er mir mit jedem einzelnen Datensatz einen String zusammenbaut der wenn er komplett ist, alle Daten mit einem einzigen Insert in die MySql DB schreibt.

    Das ist jetzt wesentlich schneller reicht aber trotzdem nicht aus wenn ich ca. 8000 Datensätze hab, bekomme ich ein Timeout Fehler im Browser.

    Das schreit förmlich nach Prepared-Statements. Die gibts aber bei mysql nur im verbesserten MySQL-Interface (genannt mysqli). Wenn du darauf Zugriff hast, nutze dies!
    http://de.php.net/manual/de/function.mysqli-prepare.php

    Bei prepared-Statements wird dein MySQL-Insert-Statement quasi vorkompiliert, die Werte setzt du erst nachträglich ein. So kannst du ein gleiches Statement mit unterschiedlichen Werten immer wieder verwenden. Und (als Bonus obendrauf) werden deine Werte automatisch gequotet.

    Bis die Tage,
    Matti

    1. echo $begrüßung;

      Das schreit förmlich nach Prepared-Statements.

      Ich glaube nicht, dass das noch sehr viel bringt. Der Flaschenhals wird auch hier die Einzelübertragung der Befehlszeilen inklusive des Wartens auf deren Abarbeitung sein.

      Bei prepared-Statements [...] werden deine Werte automatisch gequotet.

      Das stimmt so nicht. Richtig ist, man muss sich nicht darum kümmern. Das liegt aber daran, dass die Werte ihren eigenen Weg zum Server gehen und nicht in den Text-Kontext eines SQL-Statements eingefügt werden, weswegen auch keine Sonderbehandlung bestimmter Zeichen notwendig ist.

      echo "$verabschiedung $name";

      1. Tach auch.

        Das schreit förmlich nach Prepared-Statements.

        Ich glaube nicht, dass das noch sehr viel bringt. Der Flaschenhals wird auch hier die Einzelübertragung der Befehlszeilen inklusive des Wartens auf deren Abarbeitung sein.

        Nunja ... bei dynamischen SQL muss allerdings der SQL-Code jedesmal neu aufgearbeitet werden .. also ist durch den Übergang auf Prepared-Statements (und der "vorkompilierung" des Codes (nen besseres Wort fällt mir nicht ein)) eine deutliche Geschwindigkeitssteigerung zu erwarten. Allerdings halt nur, wenn das Statement wirklich vorbereitet wird. Wenn der Datenbanktreiber nur dynamischen SQL-code zusammenfügt, gewinnt man durch prepared Statements in der Tat nix.

        Das stimmt so nicht. Richtig ist, man muss sich nicht darum kümmern. Das liegt aber daran, dass die Werte ihren eigenen Weg zum Server gehen und nicht in den Text-Kontext eines SQL-Statements eingefügt werden, weswegen auch keine Sonderbehandlung bestimmter Zeichen notwendig ist.

        Und wo ist der Unterschied zwischen "das geschieht automatisch" und "man muss sich nicht drum kümmern"? :) Sieht irgendwie nach dem gleichen aus.

        Bis die Tage,
        Matti

        1. echo $begrüßung;

          Der Flaschenhals wird auch hier die Einzelübertragung der Befehlszeilen inklusive des Wartens auf deren Abarbeitung sein.

          Nunja ... bei dynamischen SQL muss allerdings der SQL-Code jedesmal neu aufgearbeitet werden .. also ist durch den Übergang auf Prepared-Statements (und der "vorkompilierung" des Codes (nen besseres Wort fällt mir nicht ein)) eine deutliche Geschwindigkeitssteigerung zu erwarten. Allerdings halt nur, wenn das Statement wirklich vorbereitet wird. Wenn der Datenbanktreiber nur dynamischen SQL-code zusammenfügt, gewinnt man durch prepared Statements in der Tat nix.

          Ich hatte da nicht das geschrieben, was ich meinte. Der Statement-Code wird in der Tat (bei echten, nicht nur simulierten P.S.) nur einmal übertragen und "vorkompiliert" (oder was auch immer). Doch die Daten werden immer noch für jeden Datensatz einzeln übertragen und die Verarbeitung bestätigt. Dieser Handshake bleibt erhalten, und der ist vermutlich deutlich langsamer als das Parsen von vielen INSERT-Statements, die in einer Datei an MySQL übergeben werden.

          Und wo ist der Unterschied zwischen "das geschieht automatisch" und "man muss sich nicht drum kümmern"? :) Sieht irgendwie nach dem gleichen aus.

          Hier ein (wie üblich hinkendes) Beispiel: Wenn man Wasser von A nach B über eine Rohrleitung transportieren kann, muss es dazu nicht in Flaschen abgefüllt werden. Auch nicht automatisch.

          Bei P.S. müssen die Daten deshalb nicht quotiert und maskiert werden, weil sie nicht in einem Text-Kontext übertragen werden. Sie werden stattdessen nativ an die Datenbank-API übergeben, die sich um den Transport kümmert.

          echo "$verabschiedung $name";

  5. Das ist jetzt wesentlich schneller reicht aber trotzdem nicht aus wenn ich ca. 8000 Datensätze hab, bekomme ich ein Timeout Fehler im Browser.

    Du musst nur diese funktion oben in dein PHP-Skript mit reinpacken.

    set_time_limit (0);

    und schon läuft dein Browser unendlich.