Daniela Koller: Optimierung von grosser MySQL Abfrage

Beitrag lesen

Hi Chris

$data=mysql_query("SELECT hoster_id FROM watch GROUP BY hoster_id ORDER by hoster_id LIMIT ".$_POST["von"].",".$_POST["max"]." ");

Die erste Query ist nicht wirklich richtig, was macht da ein Group By? In diesem Zusammenhang tut der gar nichts ausser vielleicht das was ein Distinct hier tun sollte (wenn der nötig ist, solltest du dein DB-Design überdenken).

Die Hauptlast liegt im SELECTEN der einzellnen Online und Offline Ergebnisse der einzellnen Hoster ...

Ich würde es anders lösen (deinen Limit-Teil hab ich mal
weggelassen, den einfach wieder anfügen):

Du brauchst nur 2 Queries:

Zuerst holst du die Anzahl der Ausfälle pro Hoster indem du die beiden Tabellen hoster und watch zusammen joinst:

SELECT hoster.hoster_id, count(id) as ausfaelle
  FROM hoster
    INNER JOIN watch ON(watch.hoster_id = hoster.hoster_id)
  WHERE watch.ping = '0'
  ORDER by hoster.hoster_id

Achja, warum ist ping ein String? Wenn es keiner ist, gehören da auch keine ' um die 0 rum.

Als zweites holst du analog die Anzahl der Ping-Anfragen. Dazu kannst du einfach die Where-Bedingung der ersten Anfrage weglassen.

Erst jetzt fängst du an mit deinem Loop. Du fügst jeweils die beiden passenden Einträge zusammen. Für $gesamt und $erreicht musst du jetzt die beiden count Werte aus dem Ergebnis auslesen. Deswegen unbedingt beiden mit as einen Namen geben. Vorsicht, die beiden Listen haben nicht dieselbe Länge falls ein Hoster keinen einzigen Ausfall hatte. Das musst du umgehen indem du jeweils die hoster_id prüfst und allenfalls ein 0 bei den Ausfällen einfügst. Für die Loop-Bedingung nimmst du die längere Liste, also die in der alle Pings stehen.

Weiter wichtig sind Indizes. Ich nehme mal an hoster.hoster_id ist Primärschlüssel, deswegen hat das automatisch einen Index. Was hier wichtig ist, ist ein Index über watch.hoster_id.

Noch etwas zu deinem Limit: Da direkt die HTTP-Parameter zu verwenden ist gefährlich. Die solltest du in jedem Fall Escapen, dazu gibt es eine PHP-Funktion deren Name ich gerade nicht weis.

Das ganze wäre mit CASE in einer einzigen Query zu lösen, afaik beherrscht das MySQL jedoch nicht.

Gruss Daniela