Hi!
ein Primary-Index ist ein Index mit Unique-Constraint. Das mag die Datenstruktur optimieren, weil der Fall "gleicher Wert" in keinem Knoten des binären Baums vorkommen kann; es mag aber auch beim Befüllen langsamer sein, weil die Bedingung (unique) erst abgeprüft werden muss. Nun ja, das Aktualisieren eines Index sollte für _Such_anfragen nicht relevant sein.
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. Jetzt bleiben 2 Fragen:
1. 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'
oder
SELECT count FROM words WHERE word= 'a'OR word= 'b' OR word= 'c' ORDER BY count
Welches ist hier besser?
2. Wie sieht hier die optimale-Index-Struktur aus? reicht der Primary? Bei obigen Anfragen, würde noch ein Index über die Spalte 'count' was bringen, oder besser über 'word,count'? und beim unteren beide?
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,
Das sagte ich bereits :-) Bei Befüllen der Daten ist das Leerzeichen als Trenner eine schlechte Wahl. Du musst _vorher_ die richtigen Werte ermitteln. Nachher ist es potentiell zu spät.
Ich habe jetzt ne ganze Menge gelöscht, und die meisten Sonderzeichen entfernt und hinterher wieder zusammengefaßt. Ist schon besser aber imemr noch viel Quatsch, aber den weiß ich jetzt auch nich mehr heraus zu bekommen. 3 Stellige Wörter habe ich vorerst drinnen gelassen, aber das Problem ist, dass mysqls Fulltext-Index standardmäßig eh nur Wörter länger als 3 Zeichen sucht. Nur gehen da wichtige Inforationen wie php,asp,xml... verloren.
Außerdem habe ich dei Tabelle über ein "CREATE TABLE... SELECT word, SUM(count) FROM tabelle GRPUP BY word" erstellt,
Auch das kann ein Problem sein. Ist das für MySQL anschließend eine physikalische Tabelle, oder wird es vielleicht ähnlich eines Views gehandhabt?
Ja, eine ganz normale Tabelle wird erzeugt. Kein Problem. Das klappt jetzt alles.
Ach ja, ich mache die mehreren matches daher, weil ich die Wörter so mit AND verknüpfen kann, was sonst nur OR ist.
Problematischer gestaltet sich jetzt die weitere Optimierung. Wenn was gsucht wird, was selten ist, alles schön, aber sonst?
Folgende SQL-Querys werden an die DB geschickt:
// Ermittelung der Reihenfolge
SELECT word FROM words WHERE word = 'javascript' OR word = 'preloader' ORDER BY count
Erstelle temporäre Tabelle zum sortieren
CREATE TEMPORARY TABLE temp_tabelle TYPE=HEAP
SELECT id,category,title,author,time,thread,month,year
FROM archiv
WHERE
MATCH (category,title,author,body) AGAINST ('preloader') AND
MATCH (category,title,author,body) AGAINST ('javascript')
LIMIT 0, 1000
// temp. Tabelle abfragen
SELECT * FROM temp_tabelle ORDER BY time DESC LIMIT 0, 100
Und ich bin noch bei heap geblieben, da ich nicht weiß, wie ich eien _tenporäre_ MyISAM Tabelle auf einer RAMdisk speichern kann. 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?
Naja aber so wie es ist ist es nicht befriedigend. Seltene Begriffe sind sehr schnell, und allgemeine sind zwar schneller geworden, dauern im Schnitt beim ersten mal aber immer noch gut 5 Sekunden, teilweise imer noch erheblich länger, aber das ist sehr selten. Dafür habe ich jetzt nicht mehr so stark den Caching-Effekt, liegt wohl daran dass ich den Cache nicht extra wieder vergrößert habe, aber ich weiß auch gar nicht so genau welche Variable das hier ist, obwohl ich alle Variablen kenne, laut doku, verstehe ich es noch nicht ganz.
OK, eine gute Idee war es, die Daten direkt beim schreiben zu optimieren. Aber damit komme ich auch nicht so weit, vermutlich ließe sich der Datenbestand um 20% reduzieren, aber der große Wurf wäre das auch nicht. Und mit einem eigenen Index, ich habe eine Tabelle mit einem Datensatz pro Wort(aggregiert) pro Posting. Das sind schonmal 12 Mio Datensätze. 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. 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. 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 ;-)
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. http://webalizer.teamone.de/selfforum/search_200209.htm
Aber wenn man derartige Wörter jetzt ignoriert, dann kann es sein das das Ergebnis absolut falsch ist, obwohl bei Berücksichtigung ein gutes Ergebnis möglich wäre. Es ist halt ein Komprimiss, zum einen dürfen die "DAU" anfragen nicht zu viel performance fressen, auf der anderen Seite soll die Suche gute Ergebnisse liefern, ein gewisser Zeilkonflikt.
Viele Grüße
Andreas