Design einer Suchfunktion

Radhad

Erfahrenes Mitglied
Design einer datenbankgestützten Suchfunktion

Hallo zusammen,

ich überlege derzeit, wie man eine Suchfunktion am besten umsetzen könnte auf einer eigenen Webseite. Die Suchfunktion müsste sehr viele verschiedene Tabellen in der Datenbank durchsuchen. Ich Liste mal ein paar Tabellen auf:

- Posts
- News
- NewsComments
- WikiArticles
- BlogArticles
- BlogComments
...

Nun gibt es mehrere Möglichkeiten, wie man eine Suche gestalten kann.

1. Man verwendet eine externe Suchmaschien wie Google. Dies ist recht einfach zu implementieren, hat aber den Nachteil, dass man auf den Webcrawler von Google angewiesen ist und dass nur 1000 Suchanfragen pro Tag erlaubt sind.

2. Man entwickelt einen eigenen Webcrawler, welcher die eigene Seite immer aktuell hält. Wäre aber auch nicht so effizient

3. Man durchsucht "live" die oben stethenden Tabellen. Es gibt eine Tabelle "SearchTables" wo die Tabellen, die durchsucht werden sollen, gespeichert sind, mit einer Eigenschaft, zu welchem "System" wie Forum, Wiki, Blog, sie denn gehören. Die Auflistung könnte dann sortiert nach dem Datum der letzten Änderung erfolgen. Allerdings dürfte der Zusammenbau der Hyperlinks schwierig werden...


Wie kann man so etwas denn gut lösen? Wie sind eure Erfahrungen mit einer großen Suchfunktion? Wie stark werden die Ressourcen des Servers in Anspruch genommen? Wie speichert man am besten die Daten? Vielleicht lässt sich ja hier im Forum eine gute, offene Lösung finden :)



Gruß Radhad
 
Zuletzt bearbeitet:
Ich würde auf jeden Fall letztere den ersten beiden vorziehen. Denn eine begrenzte Anzahl von Suchanfragen wie bei der ersten Möglichkeit sowie die schließlich doppelt vorkommenden Daten der zweiten Möglichkeit sind gravierende Nachteile. Da klingt die dritte Möglichkeit schon viel besser und erfolgversprechender.

Die Effizienz einer Datenbanksuche hängt vor allem von dem Schemata der Datenbank und der Tabellen ab. Es ist also schon von Anfang an wichtig darauf zu achten und sie dafür zu optimieren.
 
Ich lege einen großen Wert auf eine normalisierte Datenbank in der 3. NF. Einzig schwierig ist die Planung einer Tabelle für die Menü's. Zuvor habe ich immer Tabellen, die auf sich selbst bezogene ParentID's haben, verwendet. Das Problem dürfte aber sein, dass die Links die richtigen Parameter haben müssen und somit die URL's nicht alle gleich sind.

Der Aufbau der Seite wird in einer Ordnerstruktur sieht wie folgt aus:

htdocs als rootfolder und die Unterordner forum, wiki, blog, ...

Dazu kommt dann wiederum noch mod_rewrite, damit die URL's besser lesbar sind...

Beispiel für News:
http://www.example.com/news/article_1.html

http://www.example.com/index.php?site=news&article=1

Beispiel für Thread:
http://www.example.com/forum/thread_1.html

http://www.example.com/forum/index.php?show=thread&threadid=1

Beispiel für Thread mit Anker
http://www.example.com/forum/thread_1_postid3.html

http://www.example.com/forum/index.php?show=thread&threadid=1#postid3

Ganz festgelegt bin ich da noch nicht, es soll nur mal 2 Möglichkeiten beschreiben. Wie könnte man denn dann die URL's entsprechend aufbauen? Denn das ist ja dann der Knackpunkt an der Sache (sowie der Suchstring in SQL selber, so dass ein schönes Ergebnis ausgegeben wird).
 
Wie werden die URLs denn sonst zusammengebaut? Kann auf diese Algorithmen nicht zurückgegriffen werden?


Übrigens gibt es im Deutschen (und auch im Englischen) kein Plural-S.
 
Dann müsste ich eine Spalte im Ergebnis haben, die mir den Tabellennamen anzeigt. Dann wäre ich in der Lage, den Tabellennamen zu prüfen, um dann in einem Switch-Block den richtigen Algorithmus zu verwenden.

Kann man bei einem SQL Statement den Tabelklennamen als Spalte angeben? Hier mal kurz skizziert:
SQL:
SELECT blogarticleid, blogarticlehead, blogarticletext, GetTablename() FROM blogarticles WHERE blogarticlehead IN (Suchstring) OR blogarticletext In (Suchstring);

Dann wüsste ich, wie ich das ungefähr lösen könnte.

Einen FK zur Tabelle "SearchInTables" (Beispielname) wäre auch eine Möglichkeit, sähe allerdings etwas merkwürdig aus... Aber das wäre eine einfache Methode, den Namen der Tabelle zu erhalten.
 
Hier mal eine rasche Skizze, wie ich das mit dem FK meine, was aber meiner Meinung nach keine wirklich gute Lösung darstellt, aus oben genanntem Grund.
 

Anhänge

  • suchmodell.jpg
    suchmodell.jpg
    36,5 KB · Aufrufe: 34
Da Abfragen tabellen- und datenbankübergreifend sein können, gibt es eine solche Funktion wahrscheinlich nicht. Du könntest aber die Abfragen der einzelnen Tabellen mit UNION vereinigen:
Code:
(
        SELECT "Tabelle-A" AS `Tabelle`, … FROM `Tabelle-A` …
)
UNION
(
        SELECT "Tabelle-B" AS `Tabelle`, … FROM `Tabelle-B` …
)
…
 
An UNION dachte ich auch schon, damit ich es auch entsprechend sortieren kann. Die Frage bleibt aber, wie ich filtern kann, woher die Daten denn kommen :) Also ob sie aus Posts oder aus BlogArticles kommen.
 
Ich lege einen großen Wert auf eine normalisierte Datenbank in der 3. NF.

Das Problem wird dann darstellen, dass du die Suchfunktion nicht sehr effizent lesen kannst, aus Sicht der Datenbankoptimierung ist es legitim zeitweise die Normalformen zu brechen und Daten doppelt zu speichern (zB. Votes müssen nicht immer live berechnet werden und können "gecached" werden). Ein Union wird wahrscheinlich den Overkill darstellen, da dann alle 5 Tables aberufen werden müssen, erkennen wo ein Ergebnis herkommt, könntest du mittles:
SQL:
SELECT blablub,blabliblablup,'wiki' as fundort FROM wiki_table ...

Wie gesagt ist dies aber alles nicht sehr effizent, ich würde dir raten, eine extra Table zu erstellen, die nur die zu durchsuchenden Dinge erhält und dann einen Volltextindex darauf legen, das würde natürlich einiges an Speicherplatz kosten, ist aber überaus performant, alternativ ein Union, wie genannt, mit Volltextindex, was aber bei großen System mit hohen Peaks dein System crashen lassen wird, die Entscheidung liegt bei dir, da wir nicht wissen, wie groß dein System ist.

Mfg Tobias Petry
 
Probier doch mal eine einfache Anfrage mit dem genannten Schema über die Konsole aus, dort wird dann auch die benötigte Dauer der Anfrage ausgegeben.
 
Zurück