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.
"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.
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.
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
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?
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?
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.
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
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...?!
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.
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.
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
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.
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.
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 ;)
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
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.
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.
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!
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?