Günther S: MySQL Query dauert über PHP sehr viel länger als über PHPmyAdmin

Hallo zusammen,

ich habe eine MySQL-Tabelle mit 6 Spalten und rund 70.000 Datensätzen darin.

Es geht um folgenden Query:

  
SELECT id, user_id FROM comments ORDER BY datum DESC  

Wenn ich diesen Query in PHP via mysql_query() ausführen lasse, dauert das ca. 1 Sekunde, also sehr lange (nur das ausführen selbst, ich habe alles drum rum schon auskommentiert).
Ich habe mal den Query von PHP mittels var_dump ausgeben lassen und hab das direkt vom Browser in PHPmyAdmin kopiert.
Dort habe ich wie gewünscht die ca. 70.000 Ergebnisse bekommen und zwar in 0.02 Sekunden.
Woran kann das liegen?

Gruß,
Günther

  1. hi,

    Ich habe mal den Query von PHP mittels var_dump ausgeben lassen und hab das direkt vom Browser in PHPmyAdmin kopiert.
    Dort habe ich wie gewünscht die ca. 70.000 Ergebnisse bekommen und zwar in 0.02 Sekunden.

    PMA zeigt doch nicht alle Datensätze auf einmal an, sondern schränkt mittels LIMIT die Ergebnismenge ein - oder hast du irgendwo explizit angegeben, dass PMA dir alle Ergebnisse auf einer Seite anzeigen soll?

    gruß,
    wahsaga

    --
    /voodoo.css:
    #GeorgeWBush { position:absolute; bottom:-6ft; }
    1. Hi wahsaga!

      Ich muss dir mal ein Kompliment aussprechen. Deine Antworten sind immer wohl durchdacht und zeugen von Kompetenz.

      Ich weiß nicht, wie du es machst, aber wo ich (und sicher viele andere auch) lange grübeln, wo der Fehler liegt, kommst du und knallst die Lösung auf den Tisch.

      Du hast meinen tiefsten Respekt.

      MfG H☼psel

      --
      "It's amazing I won. I was running against peace, prosperity, and incumbency."
      George W. Bush speaking to Swedish Prime Minister unaware a live television camera was still rolling, June 14, 2001
      Selfcode: ie:% fl:( br:> va:) ls:& fo:) rl:? n4:& ss:| de:] js:| ch:? sh:( mo:) zu:)
      1. hi,

        Ich weiß nicht, wie du es machst, aber wo ich (und sicher viele andere auch) lange grübeln, wo der Fehler liegt, kommst du und knallst die Lösung auf den Tisch.

        Woll'n wir vorm Lobhudeln nicht erst mal abwarten, ob das auch wirklich die "Erklärung des Phänomens" ist ...?

        gruß,
        wahsaga

        --
        /voodoo.css:
        #GeorgeWBush { position:absolute; bottom:-6ft; }
        1. Hallo,

          Ich weiß nicht, wie du es machst, aber wo ich (und sicher viele andere auch) lange grübeln, wo der Fehler liegt, kommst du und knallst die Lösung auf den Tisch.

          Das Kompliment kann ich nur bestätigen :)

          Woll'n wir vorm Lobhudeln nicht erst mal abwarten, ob das auch wirklich die "Erklärung des Phänomens" ist ...?

          Ist es.

          Gruß,
          Günther

    2. Hallo,

      Ich habe mal den Query von PHP mittels var_dump ausgeben lassen und hab das direkt vom Browser in PHPmyAdmin kopiert.
      Dort habe ich wie gewünscht die ca. 70.000 Ergebnisse bekommen und zwar in 0.02 Sekunden.

      PMA zeigt doch nicht alle Datensätze auf einmal an, sondern schränkt mittels LIMIT die Ergebnismenge ein - oder hast du irgendwo explizit angegeben, dass PMA dir alle Ergebnisse auf einer Seite anzeigen soll?

      ... Manchmal sieht man den Wald vor lauter Bäumen nicht. Daran lag's, richtig ;)

      Damit stoße ich allerdings auf ein anderes Problem:
      Es handelt sich, wie der Tabellenname schon sagt, um Kommentare. Von diesen soll eine Teilmenge 'seitenweise' auf der Website angezeigt werden.

      Es würde mir also reichen, je 20 - 30 Kommentare aus dieser Teilmenge der Tabelle auf einmal auswählen zu lassen.

      Doch zuvor muss ich wissen, wie viele Seiten es gibt, um bewerten zu können, ob die vom Benutzer angeforderte Seite überhaupt gültig ist (was ist, wenn der User mittels Direkteingabe in der URL als Seitennummer eine viel zu hohe Zahl eingibt?).

      Das wird aber wohl nicht funktionieren, ohne zu wissen, wie viele Elemente zu dieser Teilmenge der Tabelle gehören ("WHERE typ = '...'"). (Falls doch, bin ich sehr dankbar für Denkanstöße)

      Gibt es irgendeine Möglichkeit, das herauszufinden, ohne den Query explizit auszuführen?

        
      SELECT COUNT(*) FROM comments WHERE ...  
      
      

      dauert ähnlich lange, fällt also leider auch weg.

      Klar kann man die Tabelle indizieren (werde ich auch noch machen), aber ich hätte lieber eine Lösung, die das Problem "an den Wurzeln" packt.

      Gruß,
      Günther

      1. Hi Günther!

        Gibt es irgendeine Möglichkeit, das herauszufinden, ohne den Query explizit auszuführen?

        Wenn du mit LIMIT StartEintrag, AnzahlDerEinträge auf die Einträge zugreifst, gibt es kein Problem. Du musst nur eventuell überprüfen, ob überhaupt ein Eintrag ausgelesen wurde.

        MfG H☼psel

        --
        "It's amazing I won. I was running against peace, prosperity, and incumbency."
        George W. Bush speaking to Swedish Prime Minister unaware a live television camera was still rolling, June 14, 2001
        Selfcode: ie:% fl:( br:> va:) ls:& fo:) rl:? n4:& ss:| de:] js:| ch:? sh:( mo:) zu:)
      2. hi,

        Gibt es irgendeine Möglichkeit, das herauszufinden, ohne den Query explizit auszuführen?

        Nein. Wenn du was von der Db wissen willst, musst du sie danach fragen.

        SELECT COUNT(*) FROM comments WHERE ...

        
        > dauert ähnlich lange, fällt also leider auch weg.  
        >   
        > Klar kann man die Tabelle indizieren (werde ich auch noch machen), aber ich hätte lieber eine Lösung, die das Problem "an den Wurzeln" packt.  
          
        Sinnvoll Indizes zu setzen, packt Datenbankprobleme an der Wurzel.  
        Indizes sind integraler Bestandteil eines guten Datenbankdesigns, auf sie zu verzichten, wäre also unsinnig.  
          
          
        Wenn du LIMIT nutzt, um für eine Blätterfunktion nur jeweils X Einträge pro Seite auszulesen, schau dir auch mal [FOUND_ROWS()](http://dev.mysql.com/doc/refman/4.1/en/information-functions.html) an - das kann dir unter Beibehaltung der LIMIT-Einschränkung trotzdem noch mitteilen, wie viele Ergebnisse die Query ohne LIMIT gebracht hätte.  
          
        gruß,  
        wahsaga  
          
        
        -- 
        /voodoo.css:  
        #GeorgeWBush { position:absolute; bottom:-6ft; }
        
        1. Hallo,

          Wenn du LIMIT nutzt, um für eine Blätterfunktion nur jeweils X Einträge pro Seite auszulesen, schau dir auch mal FOUND_ROWS() an - das kann dir unter Beibehaltung der LIMIT-Einschränkung trotzdem noch mitteilen, wie viele Ergebnisse die Query ohne LIMIT gebracht hätte.

          Das ist zwar nicht ganz das, was ich gerne gehabt hätte, aber immerhin kann man im Normalfall (DAU gibt keine unsinnige Seitennummer ein) auf den sehr zeitintensiven Query verzichten und diesen nur dann ausführen, falls das nötig ist (FOUND_ROWS() == 0).

          Daher, danke!

          Gruß,
          Günther

          1. Das ist zwar nicht ganz das, was ich gerne gehabt hätte, aber immerhin kann man im Normalfall (DAU gibt keine unsinnige Seitennummer ein) auf den sehr zeitintensiven Query verzichten und diesen nur dann ausführen, falls das nötig ist (FOUND_ROWS() == 0).

            Eventuell mal einen Index auf das DF 'datum' setzen und eventuell mal prüfen, ob Du die Anzahl der Datensätze in einer Tabelle bei MySQL nicht auch herausbekommst ohne ein SELECT auf die gesamte Tabelle (mit oder ohne LIMIT) zu machen, bspw. über Systemtabellen oder Systemsichten...

            BTW - kennst Du den DAE?

          2. Das ist zwar nicht ganz das, was ich gerne gehabt hätte, aber immerhin kann man im Normalfall (DAU gibt keine unsinnige Seitennummer ein) auf den sehr zeitintensiven Query verzichten und diesen nur dann ausführen, falls das nötig ist (FOUND_ROWS() == 0).

            Das ist falsch, FOUND_ROWS gibt dir nicht an wieviele Zeilen deine Abfrage hat, sondern wieviele Zeilen deine Abfrage ohne LIMIT hätte.

            Was du meinst ist die Anzahl der Zeilen deiner Abfrage, die kann man ohne Probleme ermitteln (ich kann kein PHP, aber es gibt eine Funktion mysql_rows() oder so ähnlich) ausserdem wird die Schleife mit der du die Daten abfragst in dem Falle nicht ausgeführt, da die abfrage bei rows=0 leer ist.

            du kannst mit FOUND_ROWS() ohne die Abfrage erneut auszuführen, die Anzahl der tasächlichen Zeilen deiner Abfrage ermitteln um damit eine "Blätternfunktion" umzusetzen.

            Struppi.

            --
            Javascript ist toll (Perl auch!)
            1. hi,

              Was du meinst ist die Anzahl der Zeilen deiner Abfrage, die kann man ohne Probleme ermitteln (ich kann kein PHP, aber es gibt eine Funktion mysql_rows() oder so ähnlich)

              Genau, mysql_num_rows.

              gruß,
              wahsaga

              --
              /voodoo.css:
              #GeorgeWBush { position:absolute; bottom:-6ft; }