große daten durchsuchen
-
Hallo Leute.
MySQL spezifisch!
Wie würdet ihr eine große Menge an Daten vom User durchsuchen lassen. Nehmen wir zB dieses Forum als Vorlage für mein Beispiel:
Es gibt eine Sammlung von Beiträgen die der User durchsuchen will. Nun sind es zB 100MB an rohdaten. Eine MySQL Volltextsuche würde zwar das gewünschte Ergebnis bringen, aber die Tabelle viel zu lange für Insert/Update sperren - vorallem weil man mit kontinuierlichen Suchanfragen ja die DB quasi lahmlegen könnte.
Möglichkeit 1 (die teure): man hat einen dedizierten Server für die Suchanfragen der vom echten Server repliziert.
Super Lösung, weil die Daten nicht 100% aktuell sein müssen. (wer sucht schon nach etwas, das vor 1 minute erst geschrieben wurde?)
Nachteil: man braucht extra Hardware - was nicht immer möglich ist.Möglichkeit 2:
man ladet die durchsuchten Felder in eine eigene Tabelle - und updatet postings und diese tabelle gleichzeitig bzw. speichert die queries für die tabelle um sie zu aktualisieren, wenn keine anfragen mehr kommen (sollte per cronjob kein problem sein - weil die suchtabelle ja nicht aktuell sein muss).
Nachteil: man speichert die Daten doppelt und vergeudet somit doch einiges an SpeicherMöglichkeit 3:
man verwendet keine MyISAM Tabellen sondern InnoDB Tabellen um zeilenweises locking zu erhalten - somit würde das suchen nicht mehr die ganze tabelle blockieren. Nachteil: keine Volltextsuche mehr vorhanden und man zahlt für das zeilenweise locking, obwohl man es nur bei der suche bräuchte.welche lösung würdet ihr nehmen?
-
Hallo,
ist jetzt nur eine Idee. Man könnte die häufig gesuchten querys inklusive Ausgabe
in eine extra Tabelle speichern. Mit diesem Anfragen könnte man dann einmal am Tag
einen Cron starten, um die "cache" Tabelle zu aktuallisieren. Somit müssten
dann die häufig gesuchten Sachen nur aus der kleineren Cache Tabelle geladen werden.
Vielleicht wäre es ja auch ein Ansatz das ganze zusätzlich mit Hashes zu erledigen.Gruss Frank
Edit:
Sehe grade, das das deiner Möglichkeit 2 nahe kommt. Du könntest aber auch
in der 2. Tabelle zu den querys nur die ids der Einträge aus der Haupttabelle
speichern. Dann musst du zumindest keine Volltextsuche mehr starten und hast
keine doppelten Datensätze gespeichert.
-
2oopuls schrieb:
Man könnte die häufig gesuchten querys inklusive Ausgabe
in eine extra Tabelle speichern.Müsste man testen, aber ich wage zu bezweifeln dass User immer nach den selben Daten suchen...
vorallem weil man ja nach wortkombinationen sucht.
Nehmen wir zB wieder das Forum hier: nach "exception" suchen vielleicht viele - aber "exception", "exception catch", "throw catch", "try catch throw",... bezeichnen alle das selbe Thema, bringen aber gänzlich unterschiedliche Ergebnisse. Das macht das cachen recht kompliziert.Es sei denn du hättest eine Idee wie man ohne große CPU Last und händisches editieren solche 'Blöcke' zusammen stellen kann - so dass er bei "exception", "exception catch", "throw catch", "try catch throw",... immer die selben Treffer hat. Sowas wäre nämlich wirklich geil - nur sehe ich leider keinen halbwegs vernünftigen Ansatz
-
Hmm, dann würde ich nicht den ganzen Query sondern nur die einzelnen suchwörter cachen.
Ein Beispiel:content_table -------------- |cid|volltext| --------------
cache_table ---------------- |id|string|cids| ----------------
Die User suchen jetzt nach "exception catch", "throw catch" und "try catch throw".
Das ganze splittest du jetzt und speicherst es einzeln in die cache.cache_table ------------------ |string |cids | ------------------ |exception|1:3:4:| |catch |3:5: | |throw |1:2: | ------------------
Wenn ein User jetzt nach "exception" sucht, musst du an Hand der Cache die cid
1,3,4 aus der content_table laden.Sucht ein User jetzt nach "exception catch", lädst du die Einträge
1,3,4,5Das ganze kann man nun natürlich noch UND, ODER verknüpfen.
Ob dieser Vorschlag aber wirklich effektiver (CPU) ist müsste man testen. Desweiteren
ist die Frage, ob sich ein Cache überhaupt lohnt, wenn die Suchen zu unterschiedlich sind.
In einem Board wie diesem, werden die Suchanfragen im großen und ganzen immer gleich sein
oder gleiche Teile enthalten. Wenn ich aber eine Datenbank habe, die zu allgemeine Daten
enthält dann wirds mit dem Cache schwierig. Als übertriebenes Beispiel, eine Suchmaschine.
Die Warscheinlichkeit das hier gleiche Suchanfragen gestartet werden ist wohl eher gering.Die cache_table könnte man ja auch als Dateisystem entlagern, womit man sich schonmal
Zugriffe auf die Datenbank sparen würde.Das wäre jetzt so auf die schnelle mein Ansatz, ob es Sinn macht, lass ich
mal so im Raum stehen.Gruss
-
Das macht MySQL selbst.
Hält bestimmte Suchabfragen im Chache bereit. Ist aber bei einer Voltextsuche sowieso hinfälliog weil immer andere Result da sind.
Wenn aber z.B. nach PLZ gesucht werden die sich nicht ändern dann liegen die im Cache bereit wenn immer nach allen gesucht wird.Alles andere ist so nicht möglich. Sollte man wirklich solche Tabellen haben dann bleibt einem nur:
Andere Hardware die mit dem Server 1 Repliziert und alle SELECTS beantwortet. Server 1 ist dann nur für INSERT;UPDATES da.
Zweiten MySQL auf dem gleichen Rechner starten und repliziert mit Server 1.
2teres braucht eine DEDI-Server.
1teres Hardware
-
Hm, wenn der content im Web zugängig ist, könnte man
google nicht die Drecksarbeit machen lassen ??
Und das dann per iframe einbindenDevil
-
devil81 schrieb:
Hm, wenn der content im Web zugängig ist, könnte man
google nicht die Drecksarbeit machen lassen ??
Und das dann per iframe einbindenDevil
Die Google-Suche indiziert ihm wahrscheinlich zu selten.
MfG SideWinder
-
2oopuls schrieb:
Hmm, dann würde ich nicht den ganzen Query sondern nur die einzelnen suchwörter cachen.
Die Idee ist zwar nicht schlecht, scheitert aber leider an der Menge der Daten
Unix-Tom schrieb:
Das macht MySQL selbst.
Hält bestimmte Suchabfragen im Chache bereit. Ist aber bei einer Voltextsuche sowieso hinfälliog weil immer andere Result da sind.eben...
Andere Hardware die mit dem Server 1 Repliziert und alle SELECTS beantwortet. Server 1 ist dann nur für INSERT;UPDATES da.
Dafür ist im Code eine Möglichkeit direkt eingebaut.
man ruft ein Query nicht nur mit dem querystring sondern auch mit einem 'realm' auf, so dass man zB
sql_query('select * from foo', 'search_select');
sagt - so dass man einfach für das 'search_select' realm eine andere DB verbindung nehmen kann...
Viel mehr kann ich aus Sicht der Software nicht machen, oder?
Quasi im JDBC (oder war es ne andere Java Library??) Style einen eigenen LoadBalancer einbauen.Zweiten MySQL auf dem gleichen Rechner starten und repliziert mit Server 1.
Was wäre, wenn ich den 2. Server für die Suche mit niedriger Priorität laufen lasse - so dass eine Suche statt 3 sekunden 6 dauert... Die Suche ansich würde es ja nicht stören - denn wenn ich suche, kann ich auch ein bisschen warten. Weiters würde das den ersten Server nicht so stark bremsen.
Ist diese Methode praktikabel?
Ich habe noch nie bei einem größeren Projekt einen MySQL Server administriert, so dass ich da nur theoretische Erfahrung habe
Die Software soll im endeffekt überall laufen (also nicht irgendwelche bestimmten Hardware voraussetzungen mitbringen) - aber extrem skalierbar sein. zB: dank Query 'realm's kann man recht leicht einen 'realm' wie zB die die Suche auf einen anderen Server auslagern ohne dass man groß in die Software eingreifen muss.
zu Google:
- indiziert es zu selten (wie Side schon festgestellt hat)
Es ist kein Problem wenn die Suchanfrage auf 10-20 Minuten alte Daten zugreift, aber ab 1 Tag wird es langsam kritisch... - google müsste die Seite vollständig indizieren, was bei dynamischen Seiten nicht immer leicht zu bewerkstellig ist
- es wirkt einfach unprofessionell.
- indiziert es zu selten (wie Side schon festgestellt hat)
-
Ich würde auch nicht Google dafür benützen, aber Punkt2 deiner Begründung ist nicht richtig, da gibts bei Apache nen Mod dafür der das in http://domain/erzeugenummer.html übersetzt und umgekehrt.
MfG SideWinder
-
Dafür ist im Code eine Möglichkeit direkt eingebaut.
man ruft ein Query nicht nur mit dem querystring sondern auch mit einem 'realm' auf, so dass man zBErklärts du mir das mal genauer. Das kenne ich garnicht. Quelle wo du das her hast.
Ich weiß nur das man über Datenbanken hinaus suchen kann aber nicht über Rechner und das nur durch eine Select.2 MySQL Instanzen ist gtenauso schwierig und leicht wie 2 Rechner mit Replikation.
Wie genau steht in der Doku von MySQL.Klar kannst du verschiedene Prioritäten angeben. Ist aber Linuxspezifisch.
Da LInux aber ein hgervorragendes Threadsystem hat solltest du das nicht brauchen
-
SideWinder schrieb:
Punkt2 deiner Begründung ist nicht richtig, da gibts bei Apache nen Mod dafür der das in http://domain/erzeugenummer.html übersetzt und umgekehrt.
Mein System kann das auch ohne mod_rewrite
Erklärts du mir das mal genauer. Das kenne ich garnicht. Quelle wo du das her hast.
Ich weiß nur das man über Datenbanken hinaus suchen kann aber nicht über Rechner und das nur durch eine Select.Nirgendwo - selber ausgedacht.
Man definiert verschiedene realms. Jetzt übergibt man dem MySQL Wrapper einfach nur den querystring + realm - nun kann ein user registriert haben, dass der realm 'search_select' nach $con2 gesendet wird.
$con2 wurde am anfang halt erstellt und ist mit server2 verbunden. hat der user keinen handler für 'search_select' registriert, wird das query an den standard server gesendet.
Das ermöglicht es eine einfache Datenpartitionierung zu haben - die recht billig ist und quasi keinen overhead hat.
Klar kannst du verschiedene Prioritäten angeben. Ist aber Linuxspezifisch.
Da LInux aber ein hgervorragendes Threadsystem hat solltest du das nicht brauchenne, es geht darum dass Server 1 (der hauptserver) nicht zu stark von Server 2 behindert wird. Denn Server 2 hat mehr zeit als Server 1. Und wenn beide 1 query ausführen, dann sollte Server 2 zB 70% der resourcen und Server 2 nur 30% der resourcen bekommen, weil eine suche ruhig dauern kann...
das 'problem' ist dabei nicht die technische machbarkeit, sondern wie sinnvoll es ist.