2012-03-28 8 views
0

Wir haben ein Registrierungssystem Datenbank und im Grunde, was diese Abfrage tut, überprüft die Schüler, die in der Klasse sind, so dass sie als abwesend markiert werden können, wenn sie abwesend sind. Aus irgendeinem Grund dauert es 30 Sekunden. Weiß jemand warum?Abfrage dauert 30 Sekunden lang

FROM Stdts 
    LEFT JOIN StdtReg ON StdtReg.StdtID = Stdts.ID 
    LEFT JOIN usrs ON StdtReg.userID = usrs.ID 
    WHERE (SELECT ID FROM ClssInstncEnrol cie WHERE cie.status = 0 AND classInstanceID={$_GET['ci']} AND StdtID = Stdts.ID LIMIT 1) IS NOT NULL 
    OR (SELECT ID FROM DropIns di WHERE di.type <> -1 AND classInstanceID= {$_GET['ci']} AND StdtID = Stdts.ID LIMIT 1) IS NOT NULL 
    AND (CONCAT(Stdts.firstName, ' ', Stdts.lastName) OR CONCAT(usrs.firstName,' ', usrs.lastName)) 
    ORDER BY firstName, lastName 
+5

Unterabfragen, Berechnungen (CONCAT) in jeder Zeile, und ich würde auch nicht genügend Indizes setzen. – ceejayoz

+1

Versuchen Sie, eine 'explain' in der Abfrage zu machen und sehen Sie, welche Indizes (falls vorhanden) verwendet werden. –

+7

Dieser Code sollte null Sekunden dauern und sofort einen Fehler auslösen, da es keine gültige Abfrage ist :) –

Antwort

1

die Abfrage starten mit „Explain“ vor, und es wird Ihnen sagen, wie jeder Reiter le wird verbunden, und Sie könnten einen Index vermissen.

Sie haben auch eine SQL-Injection, die auf Anfragen dieses Formulars mit HTTP-Parametern wartet, die direkt in der Abfrage interpoliert werden.

Schließlich haben Sie einige der Abfrage und das Schema abgebrochen, aber das scheint mir etwas, das mit Joins statt Subselects oder sogar als separate Abfragen, um die Liste der Student IDs effizienter vorher generiert werden könnte Sie führen sogar die Hauptanfrage aus.

+0

Das war meine Lösung . Ich muss noch den mysql_real_escape_string einfügen, aber momentan benutze ich nicht wirklich die Suchfunktion in dieser Abfrage. Es war hauptsächlich wegen der Größe der Tabelle (über 5000 Zeilen), warum die alte Abfrage so langsam war. Als ich es in meiner Testumgebung mit nur wenigen Zeilen getestet habe, war es schnell. Hier ist, was ich mir ausgedacht habe, ist wirklich schnell. Es kann immer noch einige Fehler geben, aber es funktioniert gut. – user495216

+0

SELECT Stdts.ID AS studentID, Stdts.firstName, Stdts.lastName, \t \t \t \t \t \t usrs.firstName als ufirstname, usrs.nachName als ulastname, \t \t \t \t \t \t usrs.email1 als E-Mail, usrs.homePhone wie zu Hause \t \t VON Stdts \t \t LEFT JOIN StdtReg ON StdtReg.StudentID = Stdts.ID \t \t LEFT JOIN usrs ON StdtReg. userID = usrs.ID \t \t LEFT JOIN ClssInstncEnrol cie ON Stdts.ID = cie.studentID \t \t WHERE ( \t \t \t cie.cl assInstanceID = {$ _GET [ 'ci']} \t \t) \t \t UND (CONCAT (Stdts.firstName, '', Stdts.lastName) LIKE 's% $%' OR CONCAT (usrs.firstName,‘‘, usrs.lastName) LIKE '% $ s%') \t \t GROUP BY Stdts.ID \t \t ORDER BY vorname, nachname – user495216

+0

es sieht aus wie es alle Formatierungen verloren, so dass es wirklich schwierig ist, zu lesen. Es tut uns leid. – user495216

0

Versuchen Sie, den Ausführungsplan der Abfrage zu überprüfen, um zu sehen, was falsch sein könnte (wenn Sie große Tabellen und verwenden Sie keinen entsprechenden Index kann es lange dauern,)

0

Vielleicht:

AND (CONCAT(Stdts.firstName, ' ', Stdts.lastName) OR CONCAT(usrs.firstName,' ', usrs.lastName)) 

sollte sein:

AND (CONCAT(Stdts.firstName, ' ', Stdts.lastName) = CONCAT(usrs.firstName,' ', usrs.lastName)) 
+1

Nicht zu erwähnen, gibt es wirklich einen Grund, die zwei zu concatchen, anstatt sie nur direkt zu vergleichen (Vorname = Vorname, Nachname = Nachname)? – Amber

+0

Ja, das wäre vernünftiger. Aber die concat-Sache könnte da sein, um falsche Einträge zu korrigieren (wobei eines der beiden Felder den vollständigen Namen enthält). Aber in diesem Fall würde ich sie wahrscheinlich zuerst trimmen. – wildplasser

+0

Sorry für die Verwirrung. Ich habe einen Teil dieser Abfrage beim Testen weggelassen und vergessen, sie erneut hinzuzufügen. Das könnte sein, wo die Verwirrung mit der Queery war. Hier ist die ursprüngliche letzte Zeile, die den LIKE und den Suchstring enthält, von dem ich weiß, dass er mit mysql_real_escape_string gemacht werden muss.
AND (CONCAT (Stdts.firstName, '', Stdts.lastName) LIKE '% $ s%' ODER CONCAT (usrs.firstName, '', usrs.lastName) WIE '% $ s%') – user495216

Verwandte Themen