URL: https://www.overclockers.at/coding-stuff/php_mysql_geschwindigkeitsproblem_134486/page_1 - zur Vollversion wechseln!
db1:
Code:Feld Typ Null Standard Verweise Kommentare MIME id mediumint(8) Nein uid int(10) Nein 0 name varchar(50) Nein account varchar(15) Nein gilde varchar(50) Ja NULL klasse varchar(15) Ja NULL rasse varchar(10) Ja NULL lehen varchar(50) Ja NULL last_online int(10) Nein 0 sum_online mediumint(8) Nein 1 Indizes : Name Typ Kardinalität Feld id UNIQUE 660 id uid INDEX 660 uid
Code:Feld Typ Null Standard Verweise Kommentare MIME charid mediumint(8) Nein 0 chars -> id zeit int(10) Nein 0 x smallint(5) Nein 0 y smallint(5) Nein 0 Indizes : Name Typ Kardinalität Feld zeit INDEX 15317 zeit charid INDEX 850 charid
Code: PHP$time_start = getmicrotime(); $query = 'SELECT gilde AS name, count(*) AS mitglieder FROM chars WHERE last_online>' . $temp . ' AND klasse<>\'\' GROUP BY gilde ORDER BY gilde ASC'; $result = mysql_query($query) OR die(mysql_error()); for ($gild_summe = $i = 0; $i < mysql_num_rows($result); $i++) { $gilden[$i] = mysql_fetch_assoc($result); $gild_summe += $gilden[$i]['mitglieder']; if (strlen($gilden[$i]['name']) < 2) { $gilden[$i]['name'] = 'gildenlos'; } } for ($i = 0; $i < count($gilden); $i++) { $temp = ($gilden[$i]['mitglieder']/$gild_summe)*100; $gilden[$i]['proz'] = round($temp, '2'); unset($temp); } for ($i=0; isset($gilden[$i]['name']);$i++) { if ($gilden[$i]['name'] != 'gildenlos') { $query1 = 'SELECT id FROM chars WHERE gilde=\'' . mysql_escape_string($gilden[$i]['name']) . '\''; $result1 = mysql_query($query1); $temp = $time-60*60*24*30; $zeile1 = mysql_fetch_assoc($result1); $query2 = 'SELECT charid, count(*) AS online FROM cstatus WHERE zeit>' . $temp . ' AND (charid=\'' . $zeile1['id'] . '\''; while ($zeile1 = mysql_fetch_assoc($result1)) { $query2 .= ' OR charid=\'' . $zeile1['id'] .'\''; } unset($temp); $query2 .= ') GROUP BY charid'; $result2 = mysql_query($query2); $gilden[$i]['online'] = 0; while ($zeile2 = mysql_fetch_assoc($result2)) { $gilden[$i]['online'] += $zeile2['online']; } $gilden[$i]['onlineprochar'] = $gilden[$i]['online'] / $gilden[$i]['mitglieder']; $gilden[$i]['onlineprochar'] = round($gilden[$i]['onlineprochar']); unset($temp); } else { $gilden[$i]['onlineprochar'] = $gilden[$i]['online'] = '-'; } } $time_end = getmicrotime(); $time_used = $time_end - $time_start; echo "$time_used<br>\n\n";
Code: PHP$time_start = getmicrotime(); $query = 'SELECT chars.gilde AS name, COUNT(DISTINCT chars.name) AS mitglieder, COUNT(cstatus.charid) AS online FROM chars LEFT JOIN cstatus ON chars.id=cstatus.charid WHERE cstatus.zeit>' . $temp . ' AND chars.klasse<>\'\' GROUP BY chars.gilde ORDER BY chars.gilde ASC'; $result = mysql_query($query) OR die(mysql_error()); for ($i=0;$i<mysql_num_rows($result); $i++) { $zeile[$i] = mysql_fetch_assoc($result); $zeile[$i][onlineprochar] = $zeile[$i][online]/$zeile[$i][mitglieder]; $zeile[$i][onlineprochar] = round($zeile[$i][onlineprochar]); } $time_end = getmicrotime(); $time_used = $time_end - $time_start; echo "$time_used\n\n";
zeit sollte kein index sein - man beachte die kardinalität
ich denke zwar nicht, dass es daran liegt, allerdings sollte 1 query meistens (wenn nicht immer) schneller sein, alles mehrere.
btw: ich habe mir den oberen code nicht wirklich angesehen, der ist imo unlesbar und hat einige no-nos (zB deutsch-englisch mischen, keine temporären variablen verwendet.. lieber immer asdfasdf[$i] usw).
chars.gilde -> INDEX!
chars.klasse -> INDEX!
ausserdem verwendest du beim langsameren einen join und verbindest somit 2 tables miteinander (wohlgemerkt tables, nich datenbanken...), ausserdem verwendest du ja im 1. 3 queries - und 2 davon sogar in einer doppelten for-schleife - kann mir nicht vorstellen, dass du die geschwindigkeit des ganzen scripts gemessen hast...
edit: probier' mal so:
kann man sich das auch in laufendem zusatand ansehen? vor allem würd mich interessieren, um was für zeiten es sich da handelt...Code: PHP// Query: (Hoffe, ich hab mich mit den funktionen nicht vertan...) SELECT chars.gilde AS name, COUNT(DISTINCT chars.name) AS mitglieder, COUNT(cstatus.charid) AS online ROUND(online/mitglieder) as onlineprochar FROM chars LEFT JOIN cstatus ON chars.id=cstatus.charid WHERE cstatus.zeit>' . $temp . ' AND chars.klasse<>'' GROUP BY chars.gilde ORDER BY chars.gilde ASC // Loop: while($zeile[] = mysql_fetch_assoc($result)) { ; }
@mat: was sagt die kardinalität aus? sicher kein index? denn es wird bei jedem query, das cstatus verwendet nach der zeit sortiert und in der where-clausel kommts auch vor. cstatus hat derzeit knapp 350.000 einträge.
englisch - deutsch mischen passiert mir immer wieder. wußte aber nicht, daß das ein pfui-pfui ist. und das temp-variablen auch pfui sind, wußte ich ebenso nicht. weshalb eigentlich? dadurch daß ich sie immer wieder lösche spare ich doch speicher, oder?
@watchout: doch, ich messe die geschwindigkeit des ganzen scripts. drum hab ich die zeilen sogar noch dazugenommen, wo er die zeit ausliest (getmicrotime()). ich werds mal mit index austesten, wobei da müßten ja eigentlich beide scripts schneller werden.
thx fürs erste
MIK
Darf man fragen, wozu du die Bedingung chars.klasse<>'' hast?
edit: mpf, ich sollte mir angewöhnen gleich alles rein zu schreiben
in JOINS profitiert MySQL besonders von Indezes - aber auch nicht immer, ein lebendbeispiel wär mal ganz gut, und in welchem bereich sich die runtimes bewegen
ausserdem wieviel % der datenbank du mit einer solchen abfrage ausliest, denn je mehr %, desto weniger bedingungen sind sinnvoll
wenn ein char creiert wird, muß er eine klasse wählen. hat er die (noch) nicht gewählt, dann spielt er (noch) nicht und daher uninteressant.
ich hab das ganze skript noch angehängt, das die unterschiedliche geschwindigkeit testen soll: click here
ich hab es ein paar mal laufen lassen, und werde es noch einige male heute abends anstoßen. akutelle ergebnisse gibts unter: http://infow.kleinerchemiker.net/test.txt
hier die vorläufigen ergebnisse:
Code:lang: 0.2281551361084<br> kurz: 1.0547528266907<br> lang: 0.42916989326477<br> kurz: 0.88980007171631<br> lang: 0.38035011291504<br> kurz: 0.93206810951233<br> lang: 0.32431507110596<br> kurz: 1.2448098659515<br> lang: 0.24889516830444<br> kurz: 0.83910298347473<br>
mess' auch mal die reine mysql-zeit
der zeitunterschied könnte auch an einem unterschiedlich grossen resultset liegen...
nur mysql-zeiten gibts unter: http://infow.kleinerchemiker.net/test2.php (inklusive array)
und unter: http://infow.kleinerchemiker.net/test2.txt (speichert alle bisherigen durchläufe)
auf alle fälle schon mal danke für die hilfe
ich bin einfach nur unfähig
irgendwie hab ich einen teil verloren, wie ich die queries der langen version (die mit vielen queries) in die testfiles kopiert habe. und natürlich war genau das der teil, der so ewig braucht. mit dem braucht die lange version nicht mehr unter einer sekunde, sondern knapp 30 sekunden und damit ist die kurze version mit einem query natürlich wesneltich schneller.
aber thx für die hilfe
overclockers.at v4.thecommunity
© all rights reserved by overclockers.at 2000-2025