Hi Andreas,
mach mal eine kurze Kostenrechnung.
Ok, keine Ahnung wieso es nicht ging, hab jetzt
nochmal ordentlich gefoltert und die Datenmenge
von über 50MB auf ca. 12 MB reduziert.
300.000 Datensätze mit Primary-Index, da dauert
die Suche unter 0,01 Sekunden.
So viele Einträge brauchst Du gar nicht.
Scroll mal durch die entsprechenden Häufigkeiten und male Dir in Gedanken die Verteilungsfunktion hin.
Ich rechne damit, daß sehr viele Worte sehr selten vorkommen und ziemlich wenige Worte sehr oft.
Was willst Du eigentlich erreichen?
Du willst wissen, ob sich die Qualität zweier Suchbegriffe um Größenordnungen unterscheidet.
Tut sie das, dann willst Du die Reihenfolge des FULLTEXT-Zugriffs davon abgängig machen; tut sie es nicht, dann kann Dir die Reihenfolge egal sein.
Ein Faktor von 2 lohnt den zusätzlichen Zugriff Deiner Suchbegriffstermqualitätstabelle gar nicht - das muß schon etwas mehr sein.
Deshalb war mein Ansatz an dieses Problem, die Top 2% aller Suchbegriffe in diese Tabelle aufzunehmen und alles andere zu ignorieren.
Wenn einer Deiner beiden Terme in dieser Menge ist und der andere nicht, dann willst Du sortieren; wenn beide nicht in dieser Menge sind, dann ist es Dir egal.
Sind beide in der Menge, dann _kannst_ Du sie sortieren, weil Du nebenbei ihre Qualitätswerte berechnet hast ... das kostet Dich einfach nichts zusätzlich.
Um diese Prüfung zu machen, reicht Dir aber die Darstellung dieser Top2% in einer separaten (!) Tabelle, mit jeweils nur genau einer Zeile pro Term und dem Ergebnis des jeweiligen count(*)-Aggregats aus der eigentlichen Postingtabelle. Das ist Dein "Suchbegriffsqualitätscache" - und der ist mit etwa 6000 Zeilen und PRIMARY KEY irre schnell. Vor allem kannst Du den auch mühelos im RAM halten.
- Wie sollte ich die Tabelle optimalerweise
abfragen? Ich muß z.B. zu 3 Suchbegriffen das
Vorkommen ermitteln, mache ich da leiber 3
Abfragen wie
SELECT count FROM words WHERE word= 'a'
SELECT count FROM words WHERE word= 'b'
SELECT count FROM words WHERE word= 'c'
Grusel. Das ist furchtbar langsam.
Nein, Du brauchst eine separate Tabelle aus nur noch zwei Spalten, nämlich dem Wort und seinen "Kosten". Ein "select count" sucht ja ggf. die gesamte Tabelle ab! Das sind intern tausende von Zugriffen.
Dafür mußt Du diese Tabelle - wie bereits in der letzten Diskussion zum Thema von mir erwähnt - nicht zeitnah aktuell halten. Die Top 2% Stopworte ändern sich nicht innerhalb von Tagen - sie tun es innerhalb von Monaten.
Es reicht also völlig, wenn Du diese zweispaltige Tabelle einmal im Monat neu aufbaust - und zwar im Hintergrund unter einem neuen Namen, während die alte Version noch produktiv eingesetzt wird.
Wenn Dein Neuaufbau fertig ist, dann benennst Du beide Tabelle einfach um - das darf Dir dann eine kurze Produktionsunterbrechung von wenigen Sekunden wert sein.
In der Tabelle stehen mnoch alle Wärter
vielfach drin, halt ime nur mit vielen
Zeichen drucm herum, halt "", (), '' $...
ich habe keine Ahnung wie ich das sinnvol
trennen kann,
Verwende exakt die wordchar()-Funktion von mySQL.
Problematischer gestaltet sich jetzt die weitere
Optimierung. Wenn was gsucht wird, was selten
ist, alles schön, aber sonst?
Auch dazu hatte ich bereits gepostet: LIMIT mit interner Begrenzung und Meldung an den Anwender "Ihre Suche war zu ungenau spezifiziert und wurde deshalb nach <n> Treffern abgebrochen; bitte geben Sie weitere bzw. genauere Suchbegriffe ein".
Bei Google bekommst Du auch erst mal nur 10 Treffer zu sehen - und im Ernst, wen interessiert, wieviele Treffer es insgesamt sind?
Und ich bin noch bei heap geblieben, da ich
nicht weiß, wie ich eien _tenporäre_ MyISAM
Tabelle auf einer RAMdisk speichern kann.
Indem Du eine RAM-Disk installierst und auf den Pfad mountest, wo mySQL seine temporären Tabellen speichert - auch dazu hatte ich bereits gepostet.
Mit normalen kein Problem, bis auf die
Kleinigkeit dass die Tabellen zu groß sind für
meinen RAM... Und den Fulltext-Index könnte ich
ggfs. doch auch einfach über sein sym. link auf
meine RAMdisk im RAM halten, oder?
Wenn das vom Platz her funktioniert - prima.
Da dei meisten Wörte nicht nur in einem Postig
vorkommen, habe ich keine unique Spalte, also
auch keinen Primärschlüssel, d.h. ich müßte
einen normalen Index drüber legen, was schonmal
schlechter ist.
Das glaube ich gar nicht.
Natürlich dauert es länger, alle Treffer eines mehrdeutigen Suchbegriffs auszulesen - das liegt aber nicht (bzw. höchstens marginal, wie Cheatah andeutete) an einem Unterschied zwischen UNIQUE- und NONUNIQUE-Index.
Außerdem müßte ich noch die Posting_ID zu jedem
Datensatz speichern, was bei 12 Mio Datensätzen
das Volumen der Tabelle auf über 1 GB heben
dürfte.
Kann durchaus sein - macht aber gar nichts, weil die Suche immer nur auf einen möglichst keinen Teil dieser Daten zugreifen wird. _Deshalb_ sind die doch ein sortierter Baum ...
Aber ich weiß es nicht, vielleicht ist das auch
der bessere Weg, ich versuche es mal, auf alle
Fälle hätte ich dann mehr Möglichkeiten, nur so
ein Tabelle wird niemals in meinen RAM passen ;-)
Richtig.
Deshalb wirst Du den beobachteten Effekt, daß eine wiederholte Suche schneller wird, weil die von ihr geraden gelesenen Index-Segmente zufällig gerade im Hauptspeicher liegen und nicht neu von der Platte gelesen werden müssen, nicht komplett los werden.
Man darf auch die Belastung der Suche durch den
Durschnittsanwender nicht vernachlässigen.
So kann man sagden das meist nach 2 Wörtern
gesucht wird, von denen eines ein sehr oft
vorkommendes wie "javascript" oder "html" ist.
Das glaube ich auch - und genau deshalb ist die Reihenfolge dieser beiden Worte beim Indexzugriff wahrscheinlich ziemlich wichtig.
Viele Grüße
Michael