zorg.ch
#46400 by @ 07.09.2004 11:45 - nach oben -
Forumübersicht

Die Forumübersicht ist in letzter Zeit sau langsam. Da sie so wichtig ist, müssen wir sie schneller machen. Das Herzstück unserer Forum-Übersicht ist das SQL Query.

Wenn wir da drauf mal explain machen:

EXPLAIN SELECT c.board, c.id, c.parent_id, c.text last_post_text, UNIX_TIMESTAMP( c.date ) last_post_date
FROM comments c
LEFT JOIN comments ct ON ( ct.thread_id = c.thread_id AND ct.date > c.date )
LEFT JOIN comments_threads tt ON ( tt.board = c.board AND tt.thread_id = c.thread_id )
WHERE ( 1 =2 OR c.board = 'e' OR c.board = 'i' OR c.board = 'f' OR c.board = 'b' OR c.board = 't' ) AND ct.id IS NULL
GROUP BY tt.thread_id
ORDER BY c.date DESC
LIMIT 0 , 23

table type possible_keys key key_len ref rows Extra
c range BOARD_THREAD_PARENT,BOARD_PARENT BOARD_THREAD_PARENT 1 NULL 45813 Using where; Using temporary; Using filesort
ct ref DATE_THREAD,THREAD_DATE THREAD_DATE 5 c.thread_id 21 Using where; Not exists
tt eq_ref BOARD_THREAD_COMMENT BOARD_THREAD_COMMENT 5 c.board,c.thread_id 1 Using index


sehen wir dass c 45813 rows hat, also sau viel. Das ist nicht gut, weil diese Zahl mit jeder weiteren rows-spalte multipliziert wird. Hier ist noch nicht alles angehängt, es kommen noch 2-3 mehr die um die 20 records haben.

Wenn wir jetzt für jeden dieser 45813 rows noch 20*10*21 records kriegen gibt das sau viel. Sau viel bedeutet Sau langsam. Wer das besser lösen kann kriegt von mir ein Guetzli.
zorg.ch
#46409 by @ 07.09.2004 13:46, edited @ 07.09.2004 13:50 - nach oben -
"Where 1=2 or c.board ..."
könnte man nicht den ganzen where löschen?
1=2 ist immer falsch
der rest der Bedingung trifft aber immer zu weil es keine anderen Boards als diejenigen die angegeben sind gibt.
zorg.ch
#46414 by @ 07.09.2004 14:06 - nach oben -
Natürlich stehen da nicht immer alle Boards drinm, sondern immer nur die die der User angewählt hat.
zorg.ch
#46416 by @ 07.09.2004 14:17 - nach oben -
Ach so,
Das könnte man etwas schöner schreiben indem man where c.board in ('b', 'e'... wählt (steht so in der mysql doc)
zorg.ch
#46421 by @ 07.09.2004 14:59 - nach oben -
*hust* stimmt :-) danke
zorg.ch
#46410 by @ 07.09.2004 13:55 - nach oben -
Vielleicht haben wir auch zu viele Indexes für die Tabelle Comments.
Data 8,746 KB
Index 11,043 KB
Dann zieht er nicht den richtigen und es geht zu lang.
zorg.ch
#46415 by @ 07.09.2004 14:07 - nach oben -
Zuviele Indexes haben wir sicher nicht :-) (Eher zuwenige). Ich hab den Explain angeschaut und festgestellt dass er überall den richtigen nimmt.

Sogar bei der Table c - das Problem ist dort ein anderes.
zorg.ch
#46419 by @ 07.09.2004 14:34, edited @ 07.09.2004 14:35 - nach oben -
Das Problem wirds sein, das neuste Datum zu finden oder?

Wär ein 2 Query Bastel ne Idee?
Zuerst die Threads mit den Neusten Daten finden, so ala:

SELECT max( UNIX_TIMESTAMP( date ) ) datum, thread_id
FROM comments
GROUP BY thread_id
ORDER BY datum DESC
LIMIT 23

Und dann in einem zweiten Query die 23 Posts dazu zu lesen?

SELECT *, UNIX_TIMESTAMP(date) datum FROM `comments` WHERE
(UNIX_TIMESTAMP(date) = $resultset[datum] AND thread_ID= $restultset[datum]) OR
(UNIX_TIMESTAMP(date) = $resultset[datum] AND thread_ID= $restultset[datum])
...
order by datum desc
zorg.ch
#46426 by @ 07.09.2004 15:09 - nach oben -
Eine Temporäre Tabelle wäre wohl die Idee... eine, die das Forum drin hat wie wirs sehen, und die bei jedem Post neu generiert wird.
zorg.ch
#46429 by @ 07.09.2004 15:15 - nach oben -
Apropos: weiss jemand wie man in PHP was callen kann das lange dauert, ohne dass der user X Sekunden warten muss bis sein script weiter ausgeführt wird?
zorg.ch
#46435 by @ 07.09.2004 15:47 - nach oben -
Bastelmethode:
system("nohup php /path/to/script &");
zorg.ch
#46455 by @ 07.09.2004 16:52 - nach oben -
Vielleicht gar nicht die dümmste Idee. Wenn wir davon ausgehen, dass mehr gelesen als geschrieben wird und das Updaten der Tabelle einigermassen flott geht, müsste man das fast mal in betracht ziehen.
Was gescheht aber wenn jemand auf die 2te Seite blättern will?
zorg.ch
#46459 by @ 07.09.2004 17:02 - nach oben -
Die Temp. Tabelle hätte denk alle daten drin, nicht nur die der ersten Seite.
zorg.ch
#46480 by @ 07.09.2004 18:22 - nach oben -
Ja klar, sorry war nicht ganz bei der Sache.
Das dürfte wohl eine einfache und wahrscheinlich auch schnelle Variante sein.
zorg.ch
#46418 by @ 07.09.2004 14:34 - nach oben -
Ne, das ist eigentlich schon okay so.
zorg.ch
#46417 by @ 07.09.2004 14:33 - nach oben -
Du musst einfach irgendwie das 'using temporary' wegkriegen ;)
zorg.ch
#46423 by @ 07.09.2004 15:01 - nach oben -
Using temporary ist wahrsch. gar nicht so schlimm, eher das 'using filesort' - das bedeutet dass er die 45813 Records durchloopt und bei jedem einzeln überprüfen geht ob das WHERE stimmt.
zorg.ch
#46436 by @ 07.09.2004 15:48 - nach oben -
Using temporary heisst das er die 45813 Records auf ein File in /tmp pappt, und dann dort drin rumwurstelt.
zorg.ch
#46439 by @ 07.09.2004 15:56 - nach oben -
Wenn er eine temporäre Tabelle braucht mag ihn das zwar langsamer machen, aber er könnte ja dort drin mit indexes/ranges arbeiten anstatt mit filtern.

Ich denke dass er in diesem Fall sowieso eine temporäre Tabelle braucht, da die gleiche Tabelle 2x vorkommt im Query.
zorg.ch
#46450 by @ 07.09.2004 16:21 - nach oben -
Die neu angelegte Temp Table hat latuernich keine Indizes.
zorg.ch
#46460 by @ 07.09.2004 17:02 - nach oben -
Wenn ich herausfände warum er hier eine temp. Tabelle macht...
zorg.ch
#46477 by @ 07.09.2004 18:10 - nach oben -
Weil du zweimal die gleiche Tabelle scanst?
zorg.ch
#46543 by @ 08.09.2004 09:11 - nach oben -
Ich glaub er hat doch die richtigen Indizes für beide Bedingungen? Threadid->Date haben wir zb..
zorg.ch
#46438 by @ 07.09.2004 15:54, edited @ 07.09.2004 15:57 - nach oben -
Hm...

SELECT *
FROM comments c
LEFT JOIN comments ct ON ( ct.thread_id = c.thread_id AND ct.date > c.date )
WHERE ct.id IS NULL
GROUP BY c.thread_id

ist 100 Mal schneller als:

SELECT *
FROM comments c
LEFT JOIN comments ct ON ( ct.thread_id = c.thread_id AND ct.date > c.date )
WHERE ct.id IS NULL
ORDER BY c.date DESC
GROUP BY c.thread_id
zorg.ch
#46441 by @ 07.09.2004 16:00 - nach oben -
Vielleicht wärs trotzdem gut selbst eine temp Tabelle zu machen (um den date-sort erst nachher zu machen).
Weiss jemand warum PHP nicht gerne 2x Queries hat in einem Ding? (Siehe unredcommentsfixer) Phpmyadmin macht sowas nichts aus...?!
zorg.ch
#46452 by @ 07.09.2004 16:43 - nach oben -
Vielleicht nimmt php myadmin das ganze auseinander und macht dann 2 Aufrufe draus.
Wenn du nur einen Aufruf machst, weiss die Funktion ja nicht was sie dir zurückgeben soll.
zorg.ch
#46458 by @ 07.09.2004 17:01 - nach oben -
Äh... doch. Das weiss sie vom Select. Die erste Anweisung hat ja kein Select.
zorg.ch
#46478 by @ 07.09.2004 18:15 - nach oben -
Ja aber beide Statements liefern etwas zurück, das erste würde ja dann verlohren gehen, deshalb wirds nicht erlaubt sein.
zorg.ch
#46545 by @ 08.09.2004 09:13 - nach oben -
Ja, so ist es. (Habs nachgeschaut *g*)
zorg.ch
#46453 by @ 07.09.2004 16:45 - nach oben -
Sortieren von 48k Datensätzen ist ja auch nich grad was einfaches.
Selbst mit Quicksort muss er da ziemlich arbeiten, wenns keine Indices hat (was es bei Joins wahrscheinlich nicht hat) dann dauerts grad nochmal länger.
zorg.ch
#46454 by @ 07.09.2004 16:51 - nach oben -
Bei mir ging jetzt beides ewta gleich schnell (0.0003 und 0.0005 sec) .
Vielleicht weil das ganze schon im Query Cache lag.
zorg.ch
#46462 by @ 07.09.2004 17:08 - nach oben -
Die ohne ORDER BY geht bei mir 0.0466 sek, die andere kommt gar nicht an. Beide haben "Using temporary; Using filesort"...
zorg.ch
#46467 by @ 07.09.2004 17:34 - nach oben -
Hm, ok, ohne group by gingen beide - und zwar schnell. Die Geschw. muss sich wohl einfach so fest verlangsamen wenn man X Tabellen dranhängt.
zorg.ch
#46468 by @ 07.09.2004 17:37 - nach oben -
Hierfür braucht er keine Temp. Table mehr, nur noch einen filesort:
EXPLAIN SELECT *
FROM comments c
FORCE KEY ( DATE_THREAD )
LEFT JOIN comments ct ON ( ct.thread_id = c.thread_id )
WHERE ct.date > c.date
HAVING ct.id IS NULL
ORDER BY c.date DESC
zorg.ch
#46479 by @ 07.09.2004 18:16 - nach oben -
Und was war dabei schneller?
Ich hab das Gefühl dass wir mit allen Parametern spielen müssen um die schnellste Variante laufen zu lassen.
zorg.ch
#46473 by @ 07.09.2004 17:57 - nach oben -
Ich glaube wir brauchen entweder Mysql 4.1 (Subqueries) oder wir müssen das ganze in 2 Schritten machen...
zorg.ch
#46482 by @ 07.09.2004 18:29 - nach oben -
Ich wär für die 2 Schritt Lösung, weil wir die a) jetzt sofort und b) selbst machen können.
Lukas meinte es könnte noch eine Weile gehen bis wir Mysql 4.1 erhalten würden.
zorg.ch
#46489 by @ 07.09.2004 19:31 - nach oben -
mysql 4.1 ueber das lokales 100mbit Ethernet waer eine Moeglichkeit.
zorg.ch
#46491 by @ 07.09.2004 19:40 - nach oben -
Oder noch ne Moeglichkeit:

Man zuegelt Zorg temporaer auf yuffie. Da kann man wesentlich mehr basteln, und es waer ne nette Uebergangsloesung bis ihr euren eigenen Server habt.
zorg.ch
#46497 by @ 07.09.2004 20:05 - nach oben -
Das tönt natürlich auch nicht schlecht.
zorg.ch
#46571 by @ 08.09.2004 11:49 - nach oben -
Das wäre es allerdings.

Was meinen die Herren? Sollten wir ein so zuvorkommendes Angebot nicht nutzen?
zorg.ch
#46573 by @ 08.09.2004 11:51 - nach oben -
Ich bin dafür wenn das Zorg nicht noch langsamer macht...
zorg.ch
#46575 by @ 08.09.2004 12:06, edited @ 08.09.2004 12:07 - nach oben -
Es ist afaik eine Dual-Prozi Maschine, ausserdem läuft afaik nicht wirklich etwas da drauf (ist das so?). Wenn das so ist, und da nachher nur Zorg rumbröselt, kann ich mir vorstellen, dass es schneller läuft, als auf einer gesharten Maschine, wie wir sie jetzt haben.
zorg.ch
#46578 by @ 08.09.2004 12:52 - nach oben -
2x2.4Ghz, 1GB RAM

Momentan laeuft da nur privates Zeugs von mir drauf, d.h. praktisch garnichts.
zorg.ch
#46589 by @ 08.09.2004 13:43 - nach oben -
Am besten machen wir das einfach rasch.

Bis sich jeder zooomer mit dem Gedanken angefreundet und seinen Mostkommentar dazu abgegeben hat, werden wieder Äonen ins Land gezogen sein.
zorg.ch
#46595 by @ 08.09.2004 13:55 - nach oben -
Jo, dann soll sich doch mal einer der Coder ein bisschen Zeit nehmen.
Additional posts
zorg.ch
#46492 by @ 07.09.2004 19:41 - nach oben -
bist du sicher, dass das mit subqueries schneller läuft?
zorg.ch
#46493 by @ 07.09.2004 19:44 - nach oben -
Probieren geht ueber studieren.
zorg.ch
#46494 by @ 07.09.2004 19:45 - nach oben -
das ist auch meine meinung...
zorg.ch
#46495 by @ 07.09.2004 20:03 - nach oben -
correlated subselects solle aber teilweise ziemlich übel abgehen, da mysql sie nicht richtig interpretiert und so. Weisses aber nicht aus erfahrung, da ich erstens kein mysql-geek bind und zweitens mysql 4.0.2 benutze ;)
zorg.ch
#46496 by @ 07.09.2004 20:04 - nach oben -
Mit subqueries geht das Max zeugs suchen viel einfacher und ohne join
select * from comments c where date = (select max(d.date) from comments d group by thread_id where d.thread_id = c.thread_id) group by thread_id
zorg.ch
#46544 by @ 08.09.2004 09:12 - nach oben -
jo.
zorg.ch
#46546 by @ 08.09.2004 09:13 - nach oben -
Ich bin mir ziemlich sicher, ja.
zorg.ch
#46919 by @ 09.09.2004 13:16 - nach oben -
Hab noch was gefunden:

SELECT *
FROM comments_threads ct
LEFT JOIN comments c ON ( c.id = (
SELECT MAX( id )
FROM comments
WHERE thread_id = ct.thread_id ) )
ORDER BY c.date DESC
LIMIT 0 , 23

Benötigt auch einen filesort, aber hat nur N=Anzahl Threads Records, und ist viel schneller.
zorg.ch
#46970 by @ 09.09.2004 20:59 - nach oben -
Vom schönsten, ist drum die Übersicht auf einmal so schnell?
zorg.ch
#46975 by @ 09.09.2004 21:31 - nach oben -
Joh...
zorg.ch
#46977 by @ 09.09.2004 21:33 - nach oben -
schnell ? dem sagst du schnell...es ischt "schneller" aber nicht schnell
zorg.ch
#46978 by @ 09.09.2004 21:35 - nach oben -
Ohne irgendwelche Vorkonsolidierung gehts nicht schneller.
zorg.ch
#46979 by @ 09.09.2004 21:39 - nach oben -
nichts gegen deine arbeit...wollte tschuder nur relativieren.
zorg.ch
#46980 by @ 09.09.2004 21:42 - nach oben -
Du hast recht, es ist nicht viel schneller, nur ein bisschen.
zorg.ch
#46981 by @ 09.09.2004 21:45 - nach oben -
Was müsste man denn für "Vorkonsolidierung" machen ?
zorg.ch
#46983 by @ 09.09.2004 21:48 - nach oben -
Wenn jeder Thread-Record zb zusätzlich die lastcommentid hätte würds viel schneller gehen.
zorg.ch
#46987 by @ 09.09.2004 21:52 - nach oben -
und warum hat er das nicht ?...jeder post müsste dann aber auch wissen in welchem thread er ist oder ?
zorg.ch
#47006 by @ 09.09.2004 22:52 - nach oben -
das wiess jeder post jetzt schon
zorg.ch
#46989 by @ 09.09.2004 22:09 - nach oben -
warum nicht? vorher hatten wir das sogar... ist ein bisschen edler ohne, aber halt eben auch langsamer... wär vielleicht gut das wieder einzubauen.
zorg.ch
#46992 by @ 09.09.2004 22:17 - nach oben -
ich glaub irgendwie das wir endlich mal aufhören müssen die "reinheit" unseres code/struktur vor die geschwindigkeit zu stellen!
zorg.ch
#46994 by @ 09.09.2004 22:20 - nach oben -
Ich bin der Meinung, dass man schnellen Code auch schön schreiben kann.
Vielleicht dauerts etwas länger und nicht jedes Feature von heute auf Morgen verfügbar. Dafür kann man den Code besser warten.
Additional posts
zorg.ch
#47007 by @ 09.09.2004 22:59 - nach oben -
es muss nicht edler sein, ohne. wenns schneller ist, dann ist's edler.

das speichern von zusätzlichen daten ist ein sehr gebräuchliches mittel, um mehr geschwindigkeit rauszuholen. meist gilt, wenn mehr daten gespeichert sind, wird's schneller; und umgekehrt. und da heutzutage speicher günstiger ist als rechenzeit, wird häufig mehr gespeichert. wichtig ist nur, dass die richtigen daten gespeichert werden, damit's auch wirklich schneller wird. (hab heute fast den ganzen tag für die schlussprüfung in 'algorithmen und datenstrukturen' von morgen gebüffelt) also los!
zorg.ch
#47012 by @ 09.09.2004 23:06 - nach oben -
Jo, ich erwarte das ein Pagehit schneller wird als ein 512byte Plaintext file.
zorg.ch
#47022 by @ 10.09.2004 08:07 - nach oben -
Du hast erst jetzt Prüfungen?
Zum glück bin ich mit meinen schon fertig.
Additional posts
zorg.ch
#47027 by @ 10.09.2004 08:33 - nach oben -
hm ja, rechenzeit versus cpu verbrauch. im zorg-kontext kämen da aber schnell redundanz probleme daher, die dann evtl mühsam werden können, meinst du nicht?
Additional posts