flashnfantasy: Queries brechen unter Last ein

Die folgende Queries (und davon habe ich mehrere) arbeiten eigentlich ziemlich schnell.
Durch Indizierung habe ich erreicht, daß von den abgearbeiteten Zeile 90% Treffer sind, zudem sind es ja nicht gerade viele Zeilen...

SELECT m.*, c.header, u.id AS userID FROM mail m, mailContent c, userm u LEFT JOIN crossb b ON (b.userID=1 AND b.userTo=u.id) WHERE m.toID=1 AND (m.status=1 OR m.status=2 OR m.status=4 OR m.status=6) AND u.id=m.fromID AND m.contentId=c.id AND u.memberMode!=9 AND (b.status != 2 OR b.status IS NULL)

table type   possible_keys key     key_len ref         rows Extra
m     ref    fromID,toID   toID    5       const       128  Using where
c     eq_ref PRIMARY       PRIMARY 4       m.contentId 1
u     eq_ref PRIMARY       PRIMARY 4       m.fromID    1    Using where
b     eq_ref PRIMARY       PRIMARY 8       const,u.id  1    Using where
Anzahl Abfragen = 128

Nun ist mein Problem, sobald ziemlich viel Last auf die Datenbank kommt, dauert diese Query sehr lange, bis zu 5 Sekunden. Normalerweise braucht sie 30msec.
Andere Queries brechen nicht so ein.

Nun meine allgemeinen Fragen:
a.) bedeuten diese 5 Sekunden, daß solange die Datenbank mit dieser Query beschäftigt ist ?
Weil ich den Eindruck habe, daß die 5 Sekunden eventuell ein Puffern der Abfrage beinhalten.
b.) was bedeutet das, wenn einige Abfragen unter Last länger dauern und andere nicht ? Kann es mit der Tabellengröße zu tun haben ?
c.) manchmal kriege ich den Fehler '...more than 'max_user_connections' active connections....'. Ich vermute einen Zusammenhang - das Einbrechen der Queries ist immer so das was vor diesem Fehler passiert.
Ich habe die Anzahl der 'max_user_connections' bereits erhöht, aber ohne wirklichen Erfolg.
Was habe ich noch für Möglichkeiten ?

Gruß, Flash

  1. Hello,

    welche Datenbank?

    I.d.R. kann man die meisten DBs bezüglich ihrer Speichernutzung konfogurieren.

    Wenn mehrere Queries mit vielen Indexen benutzt werden, wird der für die temporären Indexlisten benötigte Speicher sehr groß. Das DBMS muss dann swapen lassen. Das bläst den Zeitbedarf so auf.

    Vergrößere, wenn es geht, den Index-Buffer.

    Harzliche Grüße vom Berg
    http://www.annerschbarrich.de

    Tom

    --
    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
    Nur selber lernen macht schlau

    1. welche Datenbank?

      mySQL

      I.d.R. kann man die meisten DBs bezüglich ihrer Speichernutzung konfogurieren.

      Wenn mehrere Queries mit vielen Indexen benutzt werden, wird der für die temporären Indexlisten benötigte Speicher sehr groß. Das DBMS muss dann swapen lassen. Das bläst den Zeitbedarf so auf.

      Vergrößere, wenn es geht, den Index-Buffer.

      Bräuchte da aber mal eine konkrete Übersicht, was das dann für Auswirkungen hat. Weil ich schon mal auf gut Glück ein paar Parameter geändert habe, und das hat nichts bewirkt oder alles noch schlechter gemacht.

      Bin gerade am Suchen, was ich noch für Infos über eine Query rauskriege, zB wie lange sie gebuffert wird, wie lange der reine Datenbank-Zugriff ist, wieviel Speicher notwendig ist etc...
      Weil ich inzwischen der Überzeugung bin, daß die Query selber schon nicht mehr weiter zu optimieren ist, es liegt an einer anderen Sache, daß die Query 5sec braucht. Und diese andere Sache suche ich nun.

      Aber ich muß auch abschätzen können, was das wirklich nun bedeutet.
      Denn anscheinend steht diese 5sec der Rechner nicht still, sondern beantwortet lustig flott andere Anfragen, weswegen ich das mit dem buffern vermute.
      Und dann muß ich überlegen, ob es wirklich so tragisch ist, ob sich die Seite in 2 oder 12 Sekunden aufbaut.
      Oder ob das Buffern irgendwann zu einem Überlauf führt - weil ich mehrmals schon 40 Sekunden gemessen habe, und dann halt irgendwann den Fehler '...max-user-connection...'

      Gruß, Mathias

      1. Hello,

        Bräuchte da aber mal eine konkrete Übersicht, was das dann für Auswirkungen hat. Weil ich schon mal auf gut Glück ein paar Parameter geändert habe, und das hat nichts bewirkt oder alles noch schlechter gemacht.

        Es gibt dazu ein ganzes Kapitel im MySQL-Manual mit einigen Beispielkonfigurationen.
        Leider finde ich das immer nicht wieder und wenn ich es dann habe, vergesse ich, es zu bookmarken :-(

        Du musst also bitte mal selber suchen und dann bitte aber auch hier eine Erfolgsmedlung hinterlassen.

        Ich weiß nur aus Erfahrung mit diversen Servern, auf denen Communities schnell gewachsen sind, dass es bei MySQL meistens Lost Result Handles und / oder falsches Speichermodell sind, die das Ding zum Stehen bringen.

        Harzliche Grüße vom Berg
        http://www.annerschbarrich.de

        Tom

        --
        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
        Nur selber lernen macht schlau

        1. Du musst also bitte mal selber suchen und dann bitte aber auch hier eine Erfolgsmedlung hinterlassen.

          Sicher lasse ich auch mal eine Erfolgsmeldung hören...
          Bin gerade zwei Sachen am ausprobieren:

          Cache-Übersicht:
          http://dev.mysql.com/doc/refman/4.1/en/query-cache-status-and-maintenance.html

          DB-Server:
          http://dev.mysql.com/doc/refman/4.1/en/server-status-variables.html

          Bin aber gerade da eher an nutzbaren Daten am Suchen, um die anschliessend zu interpretieren.
          Das Problem ist, daß ich das an meinem Testsystem nicht testen kann, weil da keine Last drauf ist. Ich muß diese Übersicht also in mein 'Live'-System einbauen. Und da ich meine Benutzer nicht mit irgendwelchen System-Tabellen schocken will, muß diese Übersicht also nur für den Admin kommen. Das ist momentan der Stand.

          Gruß,
          Mathias

          P.S.: das ist ein kleines Programm, daß ich mir dazu geschrieben habe.
          Die Funktion 'query' im Programm ist ein ALIAS für mysql_query...

          function dbStatus ($file = __FILE__, $line = __LINE__)
          {
           print "<table border="1" cellspacing="0"><tr><td colspan="6" class="tinytableCC">Cache</td>";
           $i = 0;
           $qcache = query("SHOW STATUS LIKE 'Qcache%'",$file, $line);
           while ($dcache = mysql_fetch_array($qcache))
           {
             if ($i++ % 3 == 0) print "</tr><tr>";
             $cacheName = $dcache["Variable_name"];
             $cacheValue = $dcache["Value"];
             print "<td class="tinytableCC">" . $cacheName . "</td><td class="tinytableCC">" . $cacheValue . "</td>";
           }

          print "</tr><tr><td colspan="6" class="tinytableCC">Status</td>";
           $i = 0;
           $qstat = query("SHOW STATUS;",$file, $line);
           while ($dstat = mysql_fetch_array($qstat))
           {
             if ($i++ % 3 == 0) print "</tr><tr>";
             $statName = $dstat["Variable_name"];
             $statValue = $dstat["Value"];
             print "<td class="tinytableCC">" . $statName . "</td><td class="tinytableCC">" . $statValue . "</td>";
           }
           print "</tr></table>";
           query("FLUSH STATUS;",$file, $line);
          }

  2. yo,

    Durch Indizierung habe ich erreicht, daß von den abgearbeiteten Zeile 90% Treffer sind, zudem sind es ja nicht gerade viele Zeilen...

    was meinst du mit 90% treffer, willst du damit sagen, dass die ergebnismenge 90% des datenbestandes der tabellen entspricht ? oder hat das einen anderen hintergrund ?

    Ilja

    1. was meinst du mit 90% treffer, willst du damit sagen, dass die ergebnismenge 90% des datenbestandes der tabellen entspricht ? oder hat das einen anderen hintergrund ?

      Nein, durch Indizierung wird die Abfrage-Menge verkleinert, also keine Full-Table-Scans gemacht.

      Im Beispiel, die Tabelle m hat etwa 66000 Zeilen, die Tabelle c ebenfalls, die Tabelle u hat 6000 Datensätze und b etwa 2220.
      Durch Indizierung wurden aber nicht 58000000000000000 (5.8*10^16) Kombinationen getestet, sondern nur 128.
      Von den 128 Kombinationen erfüllen etwa 115 die WHERE-Bdingung, daher die 90%.

      Mathias