Michael Schröpl: (mysql php) Geschwindigkeitsoptimierung bei Suche? oder Anzeige?

Beitrag lesen

Hi Fabian,

Auf der Sucheseite soll man entsprechend aus 1-15 Kategorien auswählen
können wobei man entweder nur nach einem Kriterium oder auch nach allen
15 Kriterien suchen kann.

oha - also doch 1 aus N. Denn ...

Kategorie
Auto Fahrrad Flugzeug Moped ... bis 15
  0    1       1        0

... diese Tabelle suggerierte mir das Gegenteil.

Suche: Wenn z.B. Fahrrad ausgewählt: Gehe in Spalte Fahrrad und gib
alle Spalten mit einer "1" aus.

Ich fürchte, für diesen Fall habe ich mit meinem anderen Beitrag in diesem Thread weit über Dein Ziel hinaus geschossen.

In Deinem Fall steht und fällt die Tuning-Fähigkeit mit der Wahrschein-
lichkeit für eine "1" innerhalb _jeder_ einzelnen Spalte.
Wenn diese im Bereich von 10-15% liegt, ist Index oder full table scan
wahrscheinlich ähnlich schnell; sind es deutlich weniger Einsen, dann
wird ein Index entsprechend viel besser - vorausgesetzt, Du suchst immer
nur nach Einsen und nie nach Nullen. (Wenn Du nach Nullen suchst, dann
hast Du ohnehin verloren - und Deine Benutzer ebenfalls.)

Oder sollte man in der Tabelle lieber nur drei Spalten für die Kategorien
belegen und die Kategorien z.B. zuvor mit einem Index belegen?
Variante B
Kategorie 1         Kategorie  2         Kategorie 3
   Fahrrad            Flugzeug                leer

Wenn es um die grundlegende Architektur Deiner Tabellen geht (also dort
noch nicht alles in Stein gemeißelt ist), dann fehlen mir etliche Infor-
mationen über die Semantik der Daten.
Das, was ich bisher gesehen habe, sieht nun alles andere als normalform-
artig aus (leider) - aber eine konkrete Alternative vorzuschlagen, dafür
müßte ich die _vollständige_ Aufgabenstellung kennen.
Ich halte es aber für durchaus wahrscheinlich, daß diese Architektur der
wichtigste Tuning-Aspekt Deiner gesamten Anwendung wird.

Stell Dir mal vor, Du würdest Deine bisher einzige Tabelle in eine Viel-
zahl von Tabellen zerschlagen, so daß in jeder Tabelle überhaupt nur
noch diejenigen Zeilen drin sind, welche in der entsprechenden Deiner
15 Spalten eine Eins aufweisen - plus weitere Spalten für JOINs zu den
anderen Tabellen. Das würde eine Suche enorm beschleunigen!
Es würde Dich andererseits zwingen, zugehörige Attribute der Treffer
über JOINs aus anderen Tabellen zu holen. Deine gesamte Anwendung würde
anders arbeiten - vor allem UPDATEs auf diese Tabellensysteme würden
völlig anders funktionieren, Du bräuchtest transaktionssichere Tabellen
und tausend andere Dinge mehr.
Falls Such-Geschwindigkeit ein wesentlicher Teil der Anforderung ist,
kann es durchaus bedeuten, daß sich die gesamte Tabellen-Architektur
dieser Anforderung unterordnen muß.

Ich selbst habe gerade in einer Anwendung die Daten einer Tabelle auf
vier identisch formatierte Tabellen verteilt, um Performance beim Suchen
zu gewinnen - quasi als vierstufiges Caching-Systen. Damit habe ich die
heilige Normalformeigschaft der Tabellen zugunsten einer auf die wahr-
scheinliche Verteilung der Suchanfragen optimierten Struktur geopfert.
Meine SQL-Statements sind natürlich wesentlich komplexer geworden, aber
die generiere ich sowieso mit einem Programm, und ob das dann eine
Schleife über mehrere Tabellen macht (und abbricht, wenn es merkt, daß
es das darf) oder nur ein einziges SQL-Statement abfeuert, das macht in
Perl auch nur ein paar Dutzend Zeilen mehr aus. Und ist ist sauschnell
geworden!

Optmiert werden soll die Suchzeit bei sehr vielen gleichzeitigen
Suchanfragen.

Die Gleichzeitigkeit der Anfragen ist relativ egal (wenn ich mal abstra-
hiere, wieviel RAM eine bestimmte Implementierungstechnik erfordert -
aber das herauszufinden, dafür sind Kenntnisse weit unterhalb der SQL-
Ebene erforderlich), weil Du ja ausschließlich Lesezugriffe machst.

Tune eine einzige Abfrage, dann tunest Du den Schnitt aus allen; gib
aber vor allem auf den worst case acht - es darf nicht eine einzige
unegschickte Anfrage so viel Last erzeugen wie tausend geschickte.
(Genau das war mein Problem vor der Verteilung auf mehrere Tabellen ...)

Viele Grüße
      Michael

P.S.:

Wenn Du hochparallel arbeiten willst, dann mach Dir mal Gedanken über
eine entsprechende Hardware-Unterstützung. Du willst beispielsweise
ganz bestimmt nicht, daß Tabelle und Index auf derselben physikalischen
Festplatte liegen und der Festplattenkopf ständig hin- und herpositioniert.
Je mehr parallele Festplattenzugriffe Du ermöglichst (durch striping der
Objekte), desto weniger Verlust an Kopfpositionierungen wirst Du haben.
Tuning findet auf _allen_ Ebenen statt - Du kannst Dir nicht aussuchen,
auf welcher Ebene der größe Faktor an Beschleunigung zu finden ist - das
kann SQL sein, muß aber nicht. Überhaupt ist für Tuning immer ein ganz-
heitlicher Blick auf das System zu empfehlen - denn es ist ein Unter-
schied, ob Du die mittlere Antwortzeit optimieren oder ob Du für einen
möglichst hohen Anteil der Anfragen eine bestimmte Höchst-Antwortzeit
garantieren willst.
Ich selbst habe beispielsweise durch meine Cache-Architektur bewußt die
"schnellsten" Anfragen etwas gebremst (das ist aber egal, die sind immer
noch schnell genug), weil ich gleichzeitig bei den langsamsten (auch wenn
das wenige sind!) einen riesigen Faktor gewonnen habe. In der Summe habe
ich zwar vielleicht trotzdem noch eine höhere mittlere Antwortzeit, aber
wahrscheinlich mehr zufriedene Anwender ...