Fabienne: Geschwindigkeit PHP optimieren

Hi zusammen,

ich habe eine sehr umfangreiche DB-Abfrage, bei der ca. 10.000 Datensätze auls Ergebnis herauskommen.
Ziel ist eine CSV-Ausgabe.

Momentan arbeite ich über

while($array=mysql_fetch_array())
{
...
}

Innerhalb der while-Schleife gibt es _nur_ Datenausgabe, keine weitere VErarbeitung, also auch keine Funktionen oder weitere DB-Abrufe.
Das dauert aber trotzdem ca. 15 Minuten, bis alle Datensätze verarbeitet sind.

Gibt es bessere / schnellere Möglichkeiten auf die Daten zuzugreifen?

Vielen Dank
Fabienne

  1. Hi,

    Innerhalb der while-Schleife gibt es _nur_ Datenausgabe, keine weitere VErarbeitung, also auch keine Funktionen oder weitere DB-Abrufe.
    Das dauert aber trotzdem ca. 15 Minuten, bis alle Datensätze verarbeitet sind.

    Gibt es bessere / schnellere Möglichkeiten auf die Daten zuzugreifen?

    entweder läuft Dein Server auf einem 486er-Prozessor mit 32MB RAM, oder Dein DB-Layout ist suboptimal.

    Cheatah

    --
    X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
    X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
    X-Will-Answer-Email: No
    X-Please-Search-Archive-First: Absolutely Yes
    1. Re Hi,

      entweder läuft Dein Server auf einem 486er-Prozessor mit 32MB RAM, oder Dein DB-Layout ist suboptimal.

      Habe einen Server mit 4GB RAM, 2 x 2,2GHz. Sollte also genau Power da sein!

      Viele Grüße
      Fabienne

      1. Hi,

        entweder läuft Dein Server auf einem 486er-Prozessor mit 32MB RAM, oder Dein DB-Layout ist suboptimal.
        Habe einen Server mit 4GB RAM, 2 x 2,2GHz. Sollte also genau Power da sein!

        demnach stimmst Du mir also zu, dass das Problem in Deinem DB-Layout anzusiedeln ist. Umso weniger verstehe ich, dass Du hierüber keine Details nennst.

        Cheatah

        --
        X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
        X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
        X-Will-Answer-Email: No
        X-Please-Search-Archive-First: Absolutely Yes
        1. Hi Cheatah,

          dazu hatte ich bereits einige Einträge: <?t=165619>
          Es liegt meines Achtens nach nicht an der DB-Abfrage. Die geht inzwischen "ratz-fatz" (ca. 20sec).
          Hast Du noch Ideen, wie man das optimieren könnte?

          Habe meine Fehler aber schon gefunden: https://forum.selfhtml.org/?t=166035&m=1082687

          Viele Grüße
          Fabienne

          1. Hi,

            Es liegt meines Achtens nach nicht an der DB-Abfrage. Die geht inzwischen "ratz-fatz" (ca. 20sec).

            das sind annähernd 20 Sekunden zu viel.

            Hast Du noch Ideen, wie man das optimieren könnte?

            Ich sehe in Deiner Beschreibung des DB-Layouts keinerlei Information über Indizes, und auch Ausführungspläne des Statements fehlen. Dies solltest Du noch nachliefern, dann lassen sich weitere Analysen durchführen.

            Cheatah

            --
            X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
            X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
            X-Will-Answer-Email: No
            X-Please-Search-Archive-First: Absolutely Yes
            1. Hi nochmals,

              die Indizes hatte ich ursprünglich jeweils einzeln gesetzt.
              Jetzt hab ich die Indizes kombiniert gesetzt, d.h. alle Spalten die im SubSELECT vorkommen.

              Ist das korrekt?

              Viele Grüße
              Fabienne

              1. Hi,

                die Indizes muessen auf die Spalten gesetzt werden auf die selektiert wird, und nicht auf die projeziert wird, d.h. es muessen die Spalten sein, die in der WHERE-Klausel stehen.

  2. echo $begrüßung;

    ich habe eine sehr umfangreiche DB-Abfrage, bei der ca. 10.000 Datensätze auls Ergebnis herauskommen.

    10000 Datensätze können eine Datenmenge von nur 10000 Byte (ohne Metadaten) oder aber deutlich mehr sein. An dieser Anzahl lässt sich nicht erkennen, ob die Datenmenge ein Problem darstellt oder nicht.

    Momentan arbeite ich über
    while($array=mysql_fetch_array())

    PHP holt bei einem mysql_query() im Hintergund bereits alle Datensätze ab und puffert sie. Das muss so sein, damit Funktionen wie mysql_num_rows() ein Ergebnis bringen können, denn dazu muss man als Client die Ergebnismenge durchgezählt haben. Diese automatische Pufferung kann man mit mysql_unbuffered_query() umgehen.

    Innerhalb der while-Schleife gibt es _nur_ Datenausgabe, keine weitere VErarbeitung, also auch keine Funktionen oder weitere DB-Abrufe.
    Das dauert aber trotzdem ca. 15 Minuten, bis alle Datensätze verarbeitet sind.

    Hast du mal eine Zeitmessung der einzelnen Teile deines Programms durchgeführt? Wie lange braucht mysql_query()? Wie lange braucht die while-Schleife? Um irgendetwas zu optimieren muss man zuerst analysieren, an welcher Stelle der Verlust auftritt, damit man dort ansetzen kann. Ansonsten optimiert man an der falschen Stelle, und erzielt dabei vielleicht marginale Ergebnisse oder auch das Gegenteil.

    echo "$verabschiedung $name";

    1. Hi,

      Hast du mal eine Zeitmessung der einzelnen Teile deines Programms durchgeführt? Wie lange braucht mysql_query()? Wie lange braucht die while-Schleife?

      Ja habe ich:
      Für den Query (siehe <?t=165619>) brauche ich ca. 20Sek (21,52900).
      Gut, da könnte noch was drin sein, aber lohnt sich nicht wirklich.
      Ist eine Abfrage mit 7 JOINs und zahlreichen SUBSELECTS.

      Als Ergbenis bekomme ich ca 20 Spalten mit jeweils wenig Inhalt (z.B. Name, Adresse, PLZ, Ort, ...).

      Ab dem Query brauche ich pro Datensatz ca. 0,07sek mal 12.000 Datensätze = 840sek => 14min

      Ergo: Whileschleife hat Löwenanteil!

      Viele Grüße
      Fabienne

      1. Hey ho,
        hab doch noch was gefunden:
        Meine Aussage "Es wird also auch keine Funktionen oder weitere DB-Abrufe." stimmt nicht. Es gibt eine Funktion, die tatsächlich für jeden Datensatz einmal in die DB reinschaut.

        Werde das gleich mal fixen.

        Trotzdem hab ich noch eine Frage:
        Ist aber mysql_fetch_array() eine schnelle Funktion oder sollte man eher auf andere ausweichen?

        Viele Grüße
        Fabienne

        1. Hopla ho!

          Werde das gleich mal fixen.

          Hatte noch eine DB-Anfrage in einer Funktion drin.
          Die ist jetzt raus (einmal in die DB, Daten in ein Array, dann Daten aus Array während Schleife).

          Jetzt: Nur noch 37sek.
          Das ist erträglich für 12.000 Datensätze!

          Viele Grüße
          Fabienne

          1. Hi,

            Jetzt: Nur noch 37sek.
            Das ist erträglich für 12.000 Datensätze!

            hm, für mich beginnt es ab etwa einer halben Sekunde, unerträglich zu werden. Egal ob 12 Datensätze, 12.000 oder 12 Millionen.

            Cheatah

            --
            X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
            X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
            X-Will-Answer-Email: No
            X-Please-Search-Archive-First: Absolutely Yes
            1. Moin Moin!

              Jetzt: Nur noch 37sek.
              Das ist erträglich für 12.000 Datensätze!

              hm, für mich beginnt es ab etwa einer halben Sekunde, unerträglich zu werden. Egal ob 12 Datensätze, 12.000 oder 12 Millionen.

              Lange kein DB-Backup mehr gemacht, was? ;-)

              Aber fast 40 Sekunden auf einem dermaßen fetten Server für 12.000 mutmaßlich kleine Datensätze ist wirklich viel. Spricht für ein extrem kompliziertes SELECT und/oder eine extrem kaputte Datenbank (Indices falsch oder fehlend, Hardware-Schaden, ...) und/oder eine extrem schlechte Verbindung zur Datenbank (10 MBit/s Ethernet, Kabel defekt, Switch defekt, ...).

              MySQL hat doch die "SELECT ... INTO OUTFILE ..."-Syntax, um direkt in eine CSV-Datei zu schreiben, entsprechende Privilegien vorausgesetzt. Das sollte für richtig große Datenmengen schneller gehen als alles durch PHP zu pumpen.

              Alexander

              --
              Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
        2. echo $begrüßung;

          Ist aber mysql_fetch_array() eine schnelle Funktion oder sollte man eher auf andere ausweichen?

          Nun, diese Antwort könntest du dir selbst durch vergleichende Messungen geben. Allgemein gilt: Wenn du sie ohne den zweiten Parameter (oder mit MYSQL_BOTH) aufrufst, hast du die Feldwerte immer doppelt im Ergebnis. Einmal mit einem numerischem Key und einmal mit dem Feldnamen. Das doppelte Anlegen gibt es natürlich nicht zum Nulltarif. Inwieweit dies das Kraut fett macht, müsstest du messen. Es gibt die spezialisierten Funktionen mysql_fetch_assoc() und mysql_fetch_row()[*]. Beide dürften sich PHP-intern darin beschränken, mysql_fetch_array() mit einem zweiten Parameter aufzurufen. Inwieweit sich dieser zweifache Funktionsaufruf im Verhältnis zu mysql_fetch_array() mit zweitem Parameter zeitlich verhält, müsste wiederum Gegenstand einer Messung sein. Allerdings glaube ich nicht an einen gravierenden Unterschied.

          [*] mysql_fetch_object() gibt es auch noch, doch das spielt in einer etwas anderen Liga.

          echo "$verabschiedung $name";