Sven Rautenberg: MySQL: Workaround für NEXT und PREVIOUS gesucht

Beitrag lesen

Hallo Sven,

Ähm, hattest du nicht irgendwann mal Performancebedenken angemeldet, weil 1,5 Mio Datensätze zu erwarten wären? Mit _dieser_ SQL-Abfrage killst du die Datenbank ganz sicher, weil die Datenbank komplett gelesen werden muß, um concat auszuführen, und keinerlei Indices genutzt werden können. Ich würde mal sagen: Ganz üble Sache.

Da bin ich mir noch nicht sicher. Es liegt ein Index auf dem Feld Name und einer auf ID. Außerdem einer auf Name+ID. Kommt also darauf an, wie intelligent MySQL ist.

Hast du ein eigenes Feld "Name+ID" in der Datenbank angelegt, um darauf einen Index zu setzen? Warum dann noch concat() nehmen, sortiert doch dann einfach nach diesem Feld. Ist allerdings eine unnötige Redundanz.

»»aber du zeigst dich erstaunlich beratungsresistent gegenüber meinem Vorschlag, _nicht_ auf ID-Basis zu blättern, sondern auf Basis einer außen mitgeführten Variablen.

Was soll ich denn mit der von außen mitgeführten Variablen anfangen? Die gibt mir doch keinerlei Zugriff auf den Datensatz. Nach erfolgter (Einzel)anzeige des Satzwechsels ist diese Variable  hinfällig, weil das Resultset mit dem Ende des Scriptes stirbt. Es lohnt deshalb auch nicht, beliebig große Resultsets zu erzeugen, es sei denn, ich generiere daraus eine Liste, die auf dem Client angezeigt wird. Dann müsste ich aber auf dem Client JavaScript anwenden, um die betroffenen Felder des geänderten Datensatzes auch in der Liste zu aktualisieren. Dort werden natürlich nur die wichtigsten Felder.

Entweder habe ich da was ganz furchtbar falsch verstanden oder Du mich nicht. Ich habe Dir schon zugelesen und auch immer wieder über Deinen Vorschlag nachgedacht. Es ist mir nämlich ziemlich egal, von WEM die beste Lösung stammt, Hauptsache es wird die beste!

Ok, dann mal konkret in PHP, wie ich eine Suchmaschine in der Datenbank realisiert habe (gekürzt - und bitte keine Sicherheitsdiskussion über ungeprüfte Variablen :) ):

$sqlquery="SELECT * FROM tabelle WHERE textcontainer1 LIKE '%$suche%' ORDER BY artikelkey DESC LIMIT $show,".($resultperpage+1)."";

$suche enthält den Suchbegriff

$show enthält den Datensatzzeiger der ansagt, welcher Ausschnitt

der Tabelle geholt werden soll

$resultsperpage enthält die Anzahl der Ergebnisse pro Seite.

Den $sqlquery an die Datenbank senden.

$anz =  mysql_num_rows(...);

Anzahl der Ergebnisse feststellen.

for ($erg=0;$erg<$resultperpage;$erg++)
{

Datensätze ausgeben - man merke, daß in der SQL-Abfrage ein Datensatz

mehr angefordert wurde, als hier ausgegeben wird.

}

Links zum Blättern:

<?
if ($show > 0)

Wenn die Seite nicht am Anfang ist, kann man zurückblättern

{
  ?><a href="<?= $PHP_SELF ?>?suche=<? echo rawurlencode($suche); ?>&show=<? echo $show-$resultperpage ?>" zurück</a><?
}
else
{
  echo " ";
}
if ($anz > $resultperpage)

Wenn mehr Datensätze gefunden wurden, als auf diese Seite passen, kann man weiterblättern.

{
  ?><a href="<?= $PHP_SELF ?>?suche=<? echo rawurlencode($suche); ?>&show=<? echo $show+$resultperpage ?>">Weiter</a><?
}
else
{
  echo " ";
} ?>

Dadurch wird $show im Link jeweils um die Anzahl der Datensätze, die auf der Seite angezeigt werden, erhöht oder erniedrigt. Damit das nicht fehlschlägt, sollte als Grenzprüfung ganz zu Beginn noch rein:

if (($show < 0) OR ($show=="")) {$show=0;}

Weiter zurück als bis zum Anfang kann man nicht, auch wenn der Link das vielleicht irgendwie hinkriegen kann.

Diese Vorgehensweise erlaubt, daß man Indices in der Tabelle nutzen kann (Performance), man kann beliebig (auch User-definiert) sortieren mit ORDER BY - egal wie man sortiert haben möchte, funktioniert das Blättern vollkommen unabhängig davon.

»»Da hab' ich irgendwann keinen Spaß mehr an der Sache. Mach deine Datenbank doch am besten allein weiter, und wunder dich bitte hinterher nicht, wenn es nicht ganz so läuft, wie du oder die Anwender sich das vorstellen.

Nun isser beleidigt *umpf*. Kann ich aber auch nicht ändern. Tut mir nur leid um die Stimmung.

Es hat etwas von Sandsackboxen gehabt bisher.

Die Trennung von Datenhaltung und Datenanzeige hat so ihre Tücken. Bei HTML kann man eben nicht mal so eben per Serverpush und Interrupt den Bildschirm aktualisieren. Ich muss mich also auf eine Ping-Pong-Strategie einlassen, die leitungs- und serverseitig so wenig wie möglich Performace killt.

Über diesen Punkt hast du dich noch garnicht so recht ausgelassen, also schien er bis jetzt nicht sonderlich wichtig. Aber ich denke, serverseitig ist meine Lösung garnicht so problematisch (wenn die DB indexseitig sortieren kann, ist das superschnell, einziges Problem bei mir wäre das WHERE x LIKE '%string%', was lahm ist). Die DB muß jeweils nur einen kleinen Ausschnitt der Datensätze wirklich liefern (LIMIT), und was die Leitung zum Browser angeht: Naja, irgendwie müssen die Datensätze ja über die Leitung. Es hilft nicht viel, die Daten in 20er-Blöcken zu übertragen, wenn dennoch pro Zeitpunkt nur ein Datensatz angezeigt wird. Das spart keine Leitungskapazität, sondern verlagert die Datenübertragung nur.

Wie gut du in den Datensätzen blättern willst/kannst, hängt von dir ab. Es wäre ohne Probleme möglich, 20er-Blöcke in einen Frame zu laden und anhand der ID des Datensatzes dann den einzelnen Datensatz in einen anderen Frame. Oder die betroffenen, kompletten Datensätze schon gleich mitzuübertragen. Ich denke, mit meinem System bist du da ziemlich flexibel, was die Datensatzzahlen angeht. :)

- Sven Rautenberg