Moin Moin!
Eigentlich teste ich meine Anwendungen immer auf ein Uralt Linux Server und wenn es dort läuft gehts erst bzw. auch online.
Natürlich. Mit wie vielen Usern testest Du auf dem Testserver? Mit einem? Zwei?
Mit zwei Usern läuft mein aktueller Job auch locker auf einem 486er, ohne dass irgendetwas klemmt.
Laß mal 50 bis 200 (simulierte) User gleichzeitig auf deinen Testserver los und fang dann an, Deine Bottlenecks zu suchen. Und wenn das nicht reicht, leg noch 500 oder 1000 User nach.
long_query_time = 5 <- ist dieser Wert ist ok ?
Deine Frage ist sinngemäß gleich zu "Sind 100 PS gut?"
Für einen PKW mit knapp einer Tonne Leergewicht sind 100 PS mehr als gut (hehehe), für einen haushaltsüblichen Rasenmäher eher tödlicher Wahnsinn, für die Queen Mary II reichen 100 PS wahrscheinlich nichtmal als Anlasser. Und als EINZIGES Kaufkriterium für eines der drei Dinger sind "100 PS" absolut ungeeignet.
Der Engländer pflegt in diesem Fall mit "it depends" zu antworten.
1.)
SELECT SQL_NO_CACHE * FROM db WHERE Ausdruck AND Ausdruck
AND Ausdruck2.)
SELECT SQL_NO_CACHE * FROM db WHERE Ausdruck AND Ausdruck
HAVING Ausdruck
<ironie>Ich liebe MySQL.</ironie> Das sowas als SQL durchgeht, will mir nicht in den Kopf. Ich hab wohl zu lange mit Oracle und PostgreSQL gearbeitet.
- ist erstaunlicher weise langsammer als 2.)
obwohl die Spaltenanzahl des Index bei gleicher Abfrage größer ist.
Bei MySQL wundert mich gar nichts mehr. Vielleicht hat der Query Optimizer gemerkt, dass es cleverer ist, den HAVING-Ausdruck mit ins WHERE zu ziehen, und optimiert dann noch etwas weiter, was beim ersten Statement aus irgendwelchen Gründen (Tidestand in Emden, Luftfeuchtigkeit in Stockholm, Anzahl der in den letzten 10 Minuten umgefallenen Reissäcke, ...) nicht passiert.
Oder Du hast einfach MIST gemessen.
Wenn Du jedes Statement nur einmal laufen läßt, mißt Du auch die Startup-Zeiten (z.B. Tabelle von Platte ins RAM laden). Wenn die beiden Statements sich nur in HAVING vs. AND unterscheiden, und die Ausdrücke nicht zu kompliziert sind, dann hast Du bei der ersten Messung hauptsächlich die Startup-Zeiten gemessen, die vermutlich weit über der Execute-Zeit liegen. Deswegen ist das zweite Statement dann auch deutlich schneller, weil dann die Tabelle schon/noch im RAM liegt, da fällt das HAVING kaum ins Gewicht, sofern es der Optimizer nicht ohnehin ins WHERE gezogen hat.
Laß jedes einzelne Statement ein paar Mal (100 bis 1000) in einer Schleife laufen und vergleiche dann nochmal die Zeiten für die gesamte Schleife. Die Startup-Zeiten verteilen sich dann viel besser und fallen nicht mehr so ins Gewicht. Vergiß nicht, die Daten auch aus der DB zu lesen (und sei es nur, um sie gleich zu vergessen). Pseudocode:
var db=connect_db();
var start=now();
for (var i=0; i<1000; i++) {
var sth=db->prepare('SELECT ...');
sth->execute();
while (sth->fetch()) {
/* nix */
}
sth->finish();
}
var stop=now();
printf("%f Sekunden\n",(stop-start)/1000.0);
Wahllos alle SQL-Statements auf diese Art zu testen ist allerdings Zeitverschwendung und schlimmstenfalls Optimierung für die Mülltonne, weil Du nur Statements optimierst, die kaum Einfluß auf die Geschwindigkeit oder CPU-Last haben. Finde (mit dem Printf-Debugger) die Stellen in Deiner Anwendung, die langsam sind. Optimiere dort zuerst, z.B. durch anwendungsinternes Caching, z.B. durch memcached, usw. Dazu habe ich bereits einiges geschrieben.
Und um noch eine Ungenauigkeit zu korrigieren:
Ich denke es liegt wirklich am Mysql.
Nein, definitiv nicht. MySQL ist zwar nicht gerade mein Lieblings-RDBMS (unterstelle ich gerade, MySQL sei ein RDBMS?), aber es ist enorm auf Geschwindigkeit getrimmt, besonders beim Lesen.
Das Problem ist das, was Du ins MySQL reinstopfst: Deine SQL-Abfragen, die unnötige Häufung von SQL-Abfragen, und vermutlich Dein Datenbank-Schema.
Mit einem kaputten DB-Schema kann man jeden Server in die Knie zwingen. Ich hab mal aus Versehen auf einem wirklich fetten Oracle-Server eine Tabelle ohne Index (genauer: ohne Primary Key) angelegt. Ergebnis: Die Anwendung hat ein einem primitiven SELECT ... WHERE column=value mehrere Minuten geknabbert, weil Oracle einen FULL TABLE SCAN machen mußte: Jede einzelne Tabellenzeile durchkauen. Bei ein paar Mio. Datensätzen dauert das schonmal etwas. Fehler behoben, Laufzeit im Bereich von Sekundenbruchteilen, Oracle weil seinen Index für diese Spalte nutzen konnte.
Von den Reports, die einige Ex-Kollegen über andere Datenbanken (bevorzugt Microsofts Karrikatur eines RDBMS) laufen lassen/ließen, will ich jetzt besser nicht anfangen. Nur so viel: Die Laufzeiten lagen im zwei- bis dreistelligen Minutenbereich ...
Alexander
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".