Hi Andreas,
Bin jetzt nicht so sicher, aber ich habe das Gefühl,
das wir ein wenig aneinander vorbei geredet haben.
am Anfang Deines letzten Postings - ja.
Die Sache mit dem angeblichen Überleben der temporären
Tabelle hat mich in die Irre geführt - es klang so, als
würdest Du das wirklich wollen.
Ich habe das mit Der HEAP-Tabelle nur gemacht,
um dei Daten irgendwie zum sortieren zwischenzu-
speichern. Und das geht wirklich noch erheblich
besser und schneller als ich gedacht hätte.
Das wundert mich.
Anläßlich unserer Diskussion habe ich in _meiner_
Anwendung vorgestern eine meiner temporären Tabellen
auf HEAP umgestellt, und es war ein Desaster:
Der Aufbau der sortierten Struktur dauerte schon bei
einigen hundert Treffern entsetzlich lange (20 Sekun-
den oder so).
For allem dachte ich mir, spare ich mir so einen
Plattenzugriff, daher HEAP.
Ja, aber. ;-)
Einerseits kannst Du in dieser Hinsicht wahrschein-
lich doch eher an der mySQL-Konfiguration drehen (da
mußt Du halt wirklich mal alle Variablen im Handbuch
nachschlagen - das lohnt sich aber).
Und andererseits kann ein gut konfiguriertes Festplat-
tensystem die Sache auch beschleunigen, vermute ich.
Das ist da immer nur eine Ergebnistabelle mit allen
Feldern außer dem eigentlichen Postings, das hat
der Fulltext ja bereits durchsucht und das kostet
mit riesigem Abstand die meiste Performance.
Völlig richtig: So wenige Spalten mitnehmen wie nötig.
Lieber die SELECT-Felderliste dynamisch berechnen, als
einfach "*" hinschreiben etc.
Also habe ich jetzt nur noch die restlichen Felder
im RAM stehen, maximal 1000, die sortiere ich dann
und lese sie aus. Da es eine Temporäre Tabell ist
wird diese nach bveendigung der Verbindung aus dem
RAM gelöscht, und es ergeben sich auch keine
Überschneidungen.
Da ich das Sortieren in meiner Anwendung mache, habe
ich durch eine temporäre MYISAM-Tabelle keinerlei
Nachteile gegenüber HEAP.
Du erinnerst Dich vielleicht, daß ich Dich gefragt
hatte, ob Du Schreibzugriffe auzf der Festplatte wäh-
rend Deiner Suchmaschinen-Abfragen beobachten kannst?
Das solltest Du unbedingt prüfen.
Bei mir war das nämlich eine schreckliche Performance-
Bremse, daß mySQL die temporären Tabellen auf die
Festplatte geschrieben hat - weil es einen Pfad dafür
vorkonfiguriert hatte, von dem es hoffte, dort eine
RAM-Disk zu finden ... jetzt haben wir dort eine.
http://www.mysql.com/doc/en/Temporary_files.html
Das letzte Problem besteht jetzt eigentlich in dem
Index-Cache, oder wie auch immer das Ding heißt.
Wie gesagt, beim ersten mal über 20 Sekunden, beim
2. mal 10, beim 3. mal 4 und danach immer zw. 0,2
und 0,4.
Welche IO-Zugriffsraten hast Du während dieser Zeit?
(Siehe auch den vorherigen Absatz.)
Schau Dir mal mit "top" die IOWAIT-Zeiten an - wenn
die dramatisch hoch gehen, dann kommt Deine Festplatte
nicht mit.
Und wenn man den mysqld mal neu startet gehts wieder
von vorne los!
Yep. Deine Tabellen _sind_ nun mal groß.
Wäre das, was Du da tust, eine richtig teure kommer-
zielle Anwendung, dann würde ich sagen: Hau 8 GB RAM
in die Kiste rein und konfiguriere mySQL so, daß es
den FULLTEXT-Index komplett im RAM halten kann ...
Wenn ich mal bei webalizer gucke, da machen Such-
Strings die 3 mal und weniger eingegeben wurden
ca. 60-70% der gesamten Such-Anfragen aus(in einem
Monat).
Diese Erfahrung kann ich tendentiell bestätigen.
Das hieße vermutlich am Ende eine Durchschnitts-
Suchzeit von 5 oder mehr Sekunden! Das kann so doch
nicht funktionieren!
Richtig.
Irgendwas an Deiner Konfiguration tut noch nicht.
Ich denke, in Sachen SQL hast Du alles ausgereizt;
jetzt geht es ans mySQL-Tuning und darum, die dann
noch unvermeidlichen Festplattenzugriffe so schnell
wie möglich zu machen.
Was meinst Du wie ich das verändern kann? Die Zeit geht bei
CREATE TEMPORARY TABLE temp_tabelle TYPE=HEAP
Ich zweifele daran, daß HEAP eine gute Idee ist.
MATCH (topic,title,name,body) AGAINST ('Andreas')
Das ist bestimmt _nicht_ gut.
MATCH (topic,title,name,body) AGAINST ('fsockopen()')
Der zweite Suchbegriff ist um Größenordnungen besser!
Ein normales "WHERE" für den "Andreas", selbst eines
mit LIKE über die gesamte Story, hat Chancen, besser
zu sein. Mach mal einen direkten Vergleich ...
LIMIT 0, 1000
Das wirkt zu spät. Du berechnest zunächst einige
tausend Treffer mit "Andreas", joinst ("AND") diese
gegen ein paar Dutzend "fsockopen" (das _ist_ teuer!)
und erst danach begrenzt Du auf 1000 Stück, die Du
aber nach dem JOIN bestimmt schon nicht mehr hast.
verloren, was aber genau so schnell/langsam ist,
wie ohne CREATE
Yep. Mach eine Statistik über alle Worte Deiner Daten-
bank - und setze "Andreas" auf die Schwarze Liste. ;-)
SELECT * FROM temp_tabelle ORDER BY time DESC LIMIT
0, 100
dagegen dauert es wie gesagt imme unter 0,001
Sekunden.
Klar - da ist das Problem auch schon gelöst.
Was könnte man hier machen? Ich denke das ist das
letze Problem,
Aber auch eines der schwierigsten.
Du bräuchtest eine Bewertungsfunktion, um gute WHERE-
Klauseln zu berechnen, _bevor_ Du sie ausführst.
Eine Schwarze Liste wäre _ein_ möglicher Weg dorthin.
Mach mal einen Test (jeweils mit mySQL-Neustart
vorher): Ist die Dauer dieser Query abhängig von der
Reihenfolge (!) der beiden Suchbegriffe?
Wenn ja, dann ist der Query-Optimizer von mySQL nicht
gut, und Du müßtest selbst die bessere der beiden
Reihenfolgen ausrechnen. Das ist zwei SELECT gegen
eine HEAP-Tabelle (Suchbegriff => Häufigkeit) wert.
Mach mal einen zweiten Test: Definiere einen zusätz-
lichen (!) FULLTEXT-Index über den Author und generie-
re die WHERE-Klausel so, daß sie "Andreas" nur in
diesem zweiten FULLTEXT sucht (was man in der alten
Suche über die Eingabe "author:Andreas" ausdrücken
kann).
Ist _das_ schneller? Ich denke, ja - weil dann nur
noch der seltenere Begriff im großen FULLTEXT-Index
gesucht werden muß.
Du wirst immer noch irre viele Treffer dabei finden
und JOINen müssen, aber es sind weniger als bisher.
mit regexp arbeiten, das geht ja in mysql
Versuche es - aber rechne damit, daß dasselbe passiert
wie bei LIKE %...%: Es werden wahrscheinlich keinerlei
Indexzugriffe mehr möglich sein.
EXPLAIN sagt Dir, was Du wissen willst.
Viele Grüße
Michael