Andreas Korthaus: temporäre Tabellen

Hallo!

Ich teste ja zur Zeit mit dem Selfforum-Archiv (http://selfarchiv.knet-systems.de/, aber nicht immer verfügbar).
Das Problem ist, das das ganze bei größeren Sortiervorgängen unglaublich langsam wird. Vor allem ein ORDER BY time 10-20facht die Such-Zeit, und das wird auch nicht gecached.
Daher hatte ich mir überlegt, ich schreibe das Ergebnis, welches ich mit der FULLTEXT-Suche gefunden habe in eine temporäre Tabelle mit begrenzter Datensatz-Anzahl.
Jetzt stellt sich die Frage welches Tabellenformat ich hierfür verwende. Das beste sollen wohl HEAP-Tabellen sein, da die direkt im Arbsitspeicher geladen werden, udn daher extrem schnell sein sollen. 2. Frage ist, welche Daten alle in der temporären Tabelle stehen müssen. Am besten schreibt man doch alle gefunden Daten in die temporäre Tabelle, um dei Datenn direktsortert ausgeben zu können, oder sollte man nur die IDs in die Tabelle schreiben und auf die "feste" Tabelle joinen? Aber dabei ergeben sich Probleme:
1. welchen Namen verwende ich für die temporäere Tabelle? So wie ich das verstanden habe, sind die Temporären Tabellen, so lange existent, für alle Clients "gültig". Das heißt wenn cihd ei Tabelle "temp_table" nenne, kann es bei gleicheitigen Zugriffen auf das Script welches die temp-Tabelle erzeugt zu Konflikten kommen.
2. Mir geht es vor allem auch um ORDER BY, und das kann HEAP nicht, oder? Komme ich dann um MyISAM nicht herum?

Mich stört hier folgender Satz aus der Doku:

Sie können nicht nach dem nächsten Eintrag in der Reihenfolge suchen (also den Index benutzen, um ein ORDER BY zu machen).

http://de.mysql.com/documentation/mysql/bychapter/manual.de_Table_types.html#HEAP

Hier mal eine beispielhafte Anfrage:

SELECT id,topic,title,name,time
FROM selfarchiv
WHERE
MATCH (topic,title,name,body) AGAINST ('Datenbank') AND
MATCH (topic,title,name,body) AGAINST ('MySQL')
LIMIT 0, 100;

Das funktioniert sehr schnell, wenn das ganze erstmal im Cache ist.

SELECT id,topic,title,name,time
FROM selfarchiv
WHERE
MATCH (topic,title,name,body) AGAINST ('Datenbank') AND
MATCH (topic,title,name,body) AGAINST ('MySQL')
ORDER BY time DESC
LIMIT 0, 100;

das dauert immer tierisch lange, egal was ich mache. Daher hatte ich mir das ungefähr so überlegt:

CREATE TEMPORARY temp_tabelle  (
  id smallint(6),
  topic varchar(20),
  title varchar(100),
  name varchar(40),
  time int(10),
  PRIMARY KEY (id)
  TYPE=HEAP;
)

INSERT INTO temp_tabelle (id,topic,title,name,time)
SELECT id,topic,title,name,time
FROM selfarchiv
WHERE
MATCH (topic,title,name,body) AGAINST ('Datenbank') AND
MATCH (topic,title,name,body) AGAINST ('MySQL');

SELECT id,topic,title,name,time
FROM temp_tabelle
ORDER BY time DESC;

So hatte ich mir das in etwas gedacht. Oder wäre es besser die unsortierten Daten direkt auszulesen, ohne Temporäre Tabelle und ORDER BY, das ganze in einen Array schreiben und den sortieren? Was ist von wegen Länge der Temporären Tabelle zu beachten? Sollte ich das mit einem Limit bschränken, oder ist es egal wenn da einige 1000 Tabellen drin stehen, denn nur wenn ich alle Datensätze habe kann ich auch korrekt sortieren, ohne das evtl. relevante Ergebnisse unter den Tisch fallen?

Viele Grüße
Andreas

  1. Hallo!

    So wie ich das verstanden habe, sind die Temporären Tabellen, so lange existent, für alle Clients "gültig". Das heißt wenn cihd ei Tabelle "temp_table" nenne, kann es bei gleicheitigen Zugriffen auf das Script welches die temp-Tabelle erzeugt zu Konflikten kommen.

    Nein. Da der Name einer temporären Tabelle an die Verindung gebunden ist.

    1. Mir geht es vor allem auch um ORDER BY, und das kann HEAP nicht, oder? Komme ich dann um MyISAM nicht herum?

    Eine HEAP Tabelle ist für jeden Client sichtbar, nicht wie eine temporäre Tabelle. IMHO kann eine temporäre Tabelle nicht vom Typ HEAP sein. Aber das ist ja in einem Selbstversuch leicht zu ermitteln.

    HEAP-Tabellen müßen gelöscht werden, oder gehen bei einem Systemstarverloren.

    HEAP-Tabellen kennen den Spaltentyp TEXT nicht. Du kannst als nicht die Nachricht selbst in der Tabelle ablegen. Es macht nur Sinn Subjekt,Name ,Id abzulegen.

    Du mußt auch die Anzahl der Zeile beschränken, wie Du schon geschrieben hast.
    Doku: "Sie sollten immer MAX_ROWS im CREATE-Statement angeben, um sicherzustellen, dass Sie nicht versehentlich den gesamten Arbeitsspeicher benutzen."

    Bei jedem Zugriff auf eine HEAP-Tabelle muß immer überprüft werden, ob es die Tabelle noch gibt. Wenn nicht muß sie neu angelegt werden.

    IMHO wurden HEAP-Tabellen für eine hohe Performance erfunden. Also für Daten die man immer benötigt und Schlüßel für andere Tabellen sind. Indexe fallen mir da ein. Da HEAP-Tabellen nur spalten mit fester Länge verwenden, sollte also selbst bei Texten die Performance stimmen.

    MfG, André Laugks
    L-Andre @ gmx.de

    1. Hi Andre!

      So wie ich das verstanden habe, sind die Temporären Tabellen, so lange existent, für alle Clients "gültig". Das heißt wenn cihd ei Tabelle "temp_table" nenne, kann es bei gleicheitigen Zugriffen auf das Script welches die temp-Tabelle erzeugt zu Konflikten kommen.

      Nein. Da der Name einer temporären Tabelle an die Verindung gebunden ist.

      stimmt.

      1. Mir geht es vor allem auch um ORDER BY, und das kann HEAP nicht, oder? Komme ich dann um MyISAM nicht herum?

      Eine HEAP Tabelle ist für jeden Client sichtbar, nicht wie eine temporäre Tabelle. IMHO kann eine temporäre Tabelle nicht vom Typ HEAP sein. Aber das ist ja in einem Selbstversuch leicht zu ermitteln.

      das ist eine MyISAM Tabelle auch, udn trotzdem muß man meiens Wissens den Typ der temporären Tabelle angeben, also entweder myISAM oder HEAP. Udn ich dachte mir das es gerade hierfür schneller ist wenn man auf Plattenzugriffe verzichten kann.

      HEAP-Tabellen müßen gelöscht werden, oder gehen bei einem Systemstarverloren.

      Ja, das ist ja egal! Es sollen ja nur temp. Tabellen sein. Temporäre Tabellen ist doch kein weiterer Tabellentyp, sondern eine mySQL Funktion die dafür sorgt das die Tabelle nur für die Dauer und überhaupt nur für die eigene Verbindung sichtbar/vorhanden ist.

      HEAP-Tabellen kennen den Spaltentyp TEXT nicht. Du kannst als nicht die Nachricht selbst in der Tabelle ablegen.

      Das mache ich eh nicht, ich braucht den Text ja vorerst nicht zum anzeigen.

      Es macht nur Sinn Subjekt,Name ,Id abzulegen.

      genau, hatte ich auch vor, dazu time, da ich ja danach sortieren will.

      Du mußt auch die Anzahl der Zeile beschränken, wie Du schon geschrieben hast.
      Doku: "Sie sollten immer MAX_ROWS im CREATE-Statement angeben, um sicherzustellen, dass Sie nicht versehentlich den gesamten Arbeitsspeicher benutzen."

      MAX ROW bezieht sich doch bestimmt auf CREATE TABLE, oder?

      Bei jedem Zugriff auf eine HEAP-Tabelle muß immer überprüft werden, ob es die Tabelle noch gibt. Wenn nicht muß sie neu angelegt werden.

      Ich will die Tabelle bei jedem Zugriff neu erstellen! Ich will darein die unsortierten Ergebnsse der Such eschreiben(also in eine leere Tabelle), und die Tabelle dann sorteieren, was hoffentlich erheblich schneller geht, als die Komplette Suche zu sortieren.

      IMHO wurden HEAP-Tabellen für eine hohe Performance erfunden. Also für Daten die man immer benötigt und Schlüßel für andere Tabellen sind. Indexe fallen mir da ein.

      Was fpr Indexe? MySQL speichert die erzeugten Indexe doch selbst?

      Da HEAP-Tabellen nur spalten mit fester Länge verwenden, sollte also selbst bei Texten die Performance stimmen.

      Darauf hoffe ich!

      Ich habe gerde auch nochwas gefunden,w as das ganze nochmal beschleunigen sollte:

      Man kann in das CREATE TABLE Statement ein SELECT schreiben, womit ich 2 SQL-Abfragen  in einer zusammenfasse.

      Grüße
      Andreas

      1. Hallo!
        Nochmal. Hab das ganze jetzt mal so umgesetztm ist verdammt schnell(wenn die Suche im Cache ist), sogar schneller als eine einfache Suche vorher!
        Das Sortieren und Abfragen der temporären Tabelle kostet in der Tat nicht mal 1/1000 Sekunde.
        1 Problem habe ich, wie mache ich das am sinnvollste die Tabelle wieder zu löschen? Exra ein DROP TABLE? Ein mysql_close() bewirkt da nichts, da ich mir mit mysql_peconect() also persistent verbinde. Wenn ich das weglasse, also nur mysql_conect(), dann wird die Tabelle automatisch gelöscht, aber dann muß ich jedesmal eine neue Verbindung aufbauen. Was ist wohl der besere Weg?

        Dann ist da noch das Problem mit dem Ranking. Ich habe die Suche erstmal auf 100 Resultate beschränkt, erhalte dann aber wirklich nur Mist. Ich habe jetzt die Abfrage mal auf 1000 erhöht, das klappt auch prima, nach einigen Versuchen, die ersten Versuche sind erheblich langsamer als bei 100, also 20 Sekunden und mehr, am Ende kommt es trotzdem wieder auf 0,2 Sekunden beim 4. Versuch runter.  Also im Prinzp kein Problem, nur mülle ich mir natürlch mit sowas unnötig schnell den Cache voll, oder? Nur was soll ich machen? In der Suche kann ich nicht sortieren nach Datum, das kostet sooo unglaublich viel Zeit, versteh gar nicht wieso.

        Das Problem ist außerdem, wenn das automatische Ranking mal ausgeschaltet wäre, dann würde mysql vermutlich nach der ID gehen, und da kommt normalerweise die kleinste zuerst, also der älteste Beitrag zuerst, also würden alle aktuelleren Beiträge automatisch bei Überschreitung von LIMIT hinten rausfallen.

        Mal meine Abfragen:

        CREATE TEMPORARY TABLE temp_tabelle TYPE=HEAP
        SELECT id,topic,title,name,time
        FROM selfarchiv
        WHERE
        MATCH (topic,title,name,body) AGAINST ('Datenbank') AND
        MATCH (topic,title,name,body) AGAINST ('MySQL')
        LIMIT 0, 100;

        SELECT * FROM temp_tabelle ORDER BY time

        Viele Grüße
        Andreas

        1. Hi

          1 Problem habe ich, wie mache ich das am sinnvollste die Tabelle wieder zu löschen? Exra ein DROP TABLE? Ein mysql_close() bewirkt da nichts, da ich mir mit mysql_peconect() also persistent verbinde. Wenn ich das weglasse, also nur mysql_conect(), dann wird die Tabelle automatisch gelöscht, aber dann muß ich jedesmal eine neue Verbindung aufbauen. Was ist wohl der besere Weg?

          Ich bin jetzt nicht _der_ Datenbank Speziallist, aber warum die Tabelle jedesmal löschen? Leer sie doch einfach mittels DELETE FROM xyz. Mysql leert, wenn ich es richtig verstanden habe,  bei einem Statement wie dem obigen gleich die ganze Tabelle auf einmal, und nicht einzeln. Auf diese Weise müsstest du die tabelle auch nicht jedesmal wieder neu anlegen.

          Ich hoffe das ich das problem richtig verstanden habe.

          mfg

          Andres Freund

          PS: Wie lange arbeitest du jetzt eigentlich schon an der Selfsuch, ich habe die letzten Threads dazu mitgelesen und hab das Gefühl das du verdammt viel über SQL gelernt hast in der doch eigentlich kurzen Zeit. Respekt.

          1. Hallo!

            Ich bin jetzt nicht _der_ Datenbank Speziallist, aber warum die Tabelle jedesmal löschen? Leer sie doch einfach mittels DELETE FROM xyz. Mysql leert, wenn ich es richtig verstanden habe,  bei einem Statement wie dem obigen gleich die ganze Tabelle auf einmal, und nicht einzeln. Auf diese Weise müsstest du die tabelle auch nicht jedesmal wieder neu anlegen.

            Das aanlegen kostet glaub ich so gut wie nichts, und genau deshalb verwende ich eien Temporäre Tabelle, mit Beendigung der Verbindung, also am Ende des PHP-Scriptes, wird die Tabelle automatisch vom mysqld gelöscht. Wenn ich eine Tabelle nur leere, udn ime rin die gleiche Tabelle schreibe, dann habe ich das Problem, wenn 2 Leute gleichzeitig suchen, kann es sein das die sich bei der Sache ins Gehege kommen, womöglich bekommt der eien die Ergebnisse des anderen, oder die Ergebnisse des anderen werden gelöscht bevor sie ausgegeben wurden... und außerdem ist das löschen von Datensätzen erheblich langsamer als das löschen einer Tabelle, und vermutlich auch das Anlegen. Man könnte das evtl mit einer individuellen ID für jeden User in dieser Tabele umgehen, aber das wäre nochmal mehr Rechen-Aufwand, und dazu wird die HEAP-Tabelle im RAM unnötigerweise größer, und je größer desto langsamer wird das, auch wenn man es hier vermutlich nicht merken würde. Aber so ganz sicher bin ich mir heir auch noch nicht, vor allem bin ich mir noch nicht sicher ob ich überhaupt HEAP-Tabellen verwenden soll, denn da kann ich keien Index anlegen, den ich dann zum sortieren verwenden kann. Aber auf der anderen Seite dauert das Sortieren von 1000 Datesätzen ohne Index unter 1/1000 Sekunde, also was will man mehr? Außerdem glaube ich, das die HEAP-Tabelle an sich einige Vorteile des Index aufwiegt, vor allem brauche ich jede Tabelle nur ein mal, was bei einem Index natürlich Quatsch ist. Ich denke so wie ich es mache ist es gar nicht so schlecht, wie gesagt ist das ganze erstaunlich schnell. Die Engstelle bleibt jetzt eigentlich nur die Volltext-Suche, denn wennan hier einen Suchstring erstmalig eingibt, dauert die Suche tierisch lang, 10-20 Sekunden. Erst ab der 4. Wiederholung desselben Strings kommen dabei Zeiten um 0,1 und 0,3 Sekunden raus.

            PS: Wie lange arbeitest du jetzt eigentlich schon an der Selfsuch, ich habe die letzten Threads dazu mitgelesen und hab das Gefühl das du verdammt viel über SQL gelernt hast in der doch eigentlich kurzen Zeit.

            Ja, das stimmt, vor allem dank der Postings von Michael Schroepl. Außerdem habe ich einige Kapitel in der Doku jetzt ein paar mal gelesen ;-) Wobei ich noch lange nicht alles verstanden habe, aber es wird langsam. Das wichtigste ist wirklich die Datenstruktur und die Abbfragen, da ist mit großem Abstand das meiste Potential an Verbesserung zu holen, und das ist als Anfänger nicht ganz so einfach finde ich, vor allem da ich Dinge wie Temporäre Tabellen, oder andere Tabellentypen vorher nie in Erwägung gezogen habe.

            Nächte Woche will ich nochmal einen Versuch mit MySQL 4 wagen, zur Not halt unter Windows, um einfach mal zu sehen, was da noch für Potoentiel ist, z.B. wenn ich nicht mehrere Match against mit AND verknüpfe, sondern direkt die + aus dem Suchstring verwende, weiß noch nicht wie sich das auswirkt, außerdem kann ich einfach erfahren, wieviele Ergebnisse die Abfrage ohne LIMIT gebracht hätte, also durchaus interessante Sachen. Mal schaun wie das so wird. Aber diese Suche ist natürlich eine sehr spezielle Anwendung, für viele andere Bereiche muß ich nochmal genauso viel lernen, es gibt nicht umsonst DB-Spezialisten, die das Berfufsmäßig machen, denn das ist wirklich nicht so trivial wie man am Anfang denkt.

            Respekt.

            Danke ;-)

            Grüße
            Andreas

            1. Hi Andreas,

              Das aanlegen kostet glaub ich so gut wie nichts,
              und genau deshalb verwende ich eien Temporäre
              Tabelle, mit Beendigung der Verbindung, also am
              Ende des PHP-Scriptes,

              wenn Du pro Such-Aufruf eine Verbindung aufbaust,
              dann ist das so. Hat Dein PHP aber eine stehende
              Verbindung, dann sind Deine Tabellen weit weniger
              "temporär", als Dir lieb ist.

              Auch dafür gibt es aber eine Lösung: Verwende tem-poräre Tabellen (wegen der Performance), aber mit
              disjunkten Tabellennamen!
              Generiere den Tabellennamen aus etwas, das definitiv
              unique ist - nämlich der Prozeß-ID Deines PHP-Skripts.

              Am Ende des Skripts vernichte die Tabelle mit DROP.
              So hast Du immer nur eine Handvoll Tabellen, alle aber
              temporär, und Dein PHP-daemon (ist das ein Apache-
              Modul?) darf sehr wohl eine stehende Verbindung zu
              mySQL offen halten ...

              Aber diese Suche ist natürlich eine sehr spezielle
              Anwendung, für viele andere Bereiche muß ich noch-
              mal genauso viel lernen, es gibt nicht umsonst DB-
              Spezialisten, die das Berfufsmäßig machen, denn das
              ist wirklich nicht so trivial wie man am Anfang
              denkt.

              Alleine das ist doch schon ein schöner Lernerfolg. ;-)

              Aber so speziell ist diese Anwendung gar nicht.
              Das Wissen, das Du gerade erwirbst, wird Dir für sehr
              viele Datenbankanwendungen helfen - Du reizt mySQL
              immerhin schon ziemlich heftig aus.

              Und Du lernst Grundlegendes über das Wesen von Indizes,
              und den trade-off zwischen CPU und RAM, über sinnvolle
              Projektplanung (zuerst die Aufgabenstellung, dann die
              Datenstrukturen, danach die Algorithmen, zuletzt das
              Fein-Tuning), über die Mehrfachverwendung von Zwischen-
              ergebnissen ...

              Möchtest Du nicht gleich ein Informatik-Studium dran-
              hängen? ;-)

              Viele Grüße
                    Michael

              1. Hallo!

                Möchtest Du nicht gleich ein Informatik-Studium dran-
                hängen? ;-)

                Du wirst lachen, ich bin dieses Semester für Informatik eingeschrieben, neben BWL, aber das ist mir einfach zu krass, das muß jetzt nicht mehr sein. Mit BWL bin ich in knapp 2 Jahren fertig, bei Informatik müßte ich mich alleine 2 Jahre nur mit Mathematik rumschlagen bei allem inzwichen angeworbenen Verstendnis hierfür, dazu habe ich keine Lust mehr. Ich war immer gut in Mathe, hatte da nier Probleme und mußte nie lernen, aber Statik bei BWL war schon nicht ganz ohne, und die Mathematik bei Infoirmatik ist nochmal eine steigerung dazu, udn ich muß sagen es reicht langsam ;-) Nicht das ich zweifele das zu schafffen, aber das würde mir nur was bringen wnen ich in die richtige Informatik Branche wollte, das komplett fertig stdiere, was jka noch ein paar Jaher merh dauern würde, und hierfür sehe ich den Nutzen nicht. Und das ist nicht alles was mich da nicht interessiert, das wäre nur ein kleiner Teil.
                Bei BWL mache ich jetzt als BWL Schwerpunkt entweder E-Business oder Wirtschaftsindirmatik, und als techn. Schwerpunkt Informatik(3 Vorlesungen aus dem Informatik Hauptstudium, Datenbanken, Datenkommunikations, udn noch sowas). Vielleicht mache ich nach meienm Diplom noch einen Bachelor, wenn mir ein paar Sachen anerkannt werden und das ganze nicht viel mehr als 1 oder 1,5 Jahre dauert, mal schaun.
                Außerdem kostet ien 2.-Studium in NRW nächstes Semester 650 EUR extra!

                Grüße
                Andreas

                1. Hi Andreas,

                  Du wirst lachen, ich bin dieses Semester für
                  Informatik eingeschrieben, neben BWL, aber das
                  ist mir einfach zu krass, das muß jetzt nicht
                  mehr sein. Mit BWL bin ich in knapp 2 Jahren fertig,
                  bei Informatik müßte ich mich alleine 2 Jahre nur
                  mit Mathematik rumschlagen bei allem inzwichen
                  angeworbenen Verstendnis hierfür, dazu habe ich
                  keine Lust mehr. Ich war immer gut in Mathe, hatte
                  da nier Probleme und mußte nie lernen, aber Statik
                  bei BWL war schon nicht ganz ohne, und die
                  Mathematik bei Infoirmatik ist nochmal eine
                  steigerung dazu, udn ich muß sagen es reicht langsam
                  ;-) Nicht das ich zweifele das zu schafffen, aber
                  das würde mir nur was bringen wnen ich in die
                  richtige Informatik Branche wollte, das komplett
                  fertig stdiere, was jka noch ein paar Jaher merh
                  dauern würde, und hierfür sehe ich den Nutzen nicht.

                  Meine Postings in unseren Threads versuchen, Dir zu
                  vermitteln, wie ein "richtiger" Informatiker denkt.

                  Und das ist nicht alles was mich da nicht
                  interessiert, das wäre nur ein kleiner Teil.

                  Das Grundstudium Informatik enthält relativ viel
                  Mathematik, die man später kaum noch braucht (wieso
                  ich so viel Analysis lernen mußte, habe ich auch nie
                  verstanden - Algebra dagegen ist notwendig für Theo-
                  retische Informatik).
                  Das Hauptstudium ist fast vollständig sinnvoller Stoff.

                  Bei BWL mache ich jetzt als BWL Schwerpunkt
                  entweder E-Business oder Wirtschaftsindirmatik,
                  und als techn. Schwerpunkt Informatik (3 Vor-
                  lesungen aus dem Informatik Hauptstudium,
                  Datenbanken, Datenkommunikations, udn noch sowas).

                  Ein bißchen Theoretische Informatik würde Dir helfen.
                  Für Datenbanken sind insbesondere "Suchen und Sortieren"
                  (das war bei mir Grundstudium Informatik III) und
                  etwas "Komplexitätstheorie" sinnvoll.

                  Viele Grüße
                        Michael

          2. Hi auch,

            1 Problem habe ich, wie mache ich das am
            sinnvollste die Tabelle wieder zu löschen?
            Exra ein DROP TABLE?

            Ja, das dürfte am schnellsten sein.

            Was muß die Datenbank dabei tun?
            a) ein paar Puffer in einer Belegungsliste freigeben
               und
            b) die CREATE TABLE-Struktur aus ihrem Inhaltsver-
               zeichnis aller Tabellen streichen
            Das geht beides sehr schnell.

            Ich bin jetzt nicht _der_ Datenbank Speziallist,
            aber warum die Tabelle jedesmal löschen?
            Leer sie doch einfach mittels DELETE FROM xyz.

            Das ist im allgemeinen Fall _ganz_ schlecht.

            Ein DELETE greift auf die einzelnen Datensätze zu
            und entfernt einen nach dem anderen - es könnte ja
            eine WHERE-Klausel bewirken, daß _nicht_ alle Zeilen
            entfernt werden sollen. Das ist schrecklich langsam.
            (Oder es könnten parallel andere Prozesse darauf zu-
            greifen - dieses Argument scheidet bei temporären
            Tabellen allerdings aus.)

            Deshalb gibt es in einigen SQL-Dialekten spezielle
            Befehle wie TRUNCATE:
            http://www.mysql.com/doc/en/TRUNCATE.html
            (mit Erklärung über Performance-Aspekte)
            "Hau weg" ist viel einfacher als DELETE - und viel
            schneller.

            ich habe die letzten Threads dazu mitgelesen und
            hab das Gefühl das du verdammt viel über SQL
            gelernt hast in der doch eigentlich kurzen Zeit.

            Dieser Beobachtung schließe ich mich uneingeschränkt an.

            Viele Grüße
                  Michael

            1. Hi

              Ich bin jetzt nicht _der_ Datenbank Speziallist,
              aber warum die Tabelle jedesmal löschen?
              Leer sie doch einfach mittels DELETE FROM xyz.

              Das ist im allgemeinen Fall _ganz_ schlecht.

              Ein DELETE greift auf die einzelnen Datensätze zu
              und entfernt einen nach dem anderen - es könnte ja
              eine WHERE-Klausel bewirken, daß _nicht_ alle Zeilen
              entfernt werden sollen. Das ist schrecklich langsam.
              (Oder es könnten parallel andere Prozesse darauf zu-
              greifen - dieses Argument scheidet bei temporären
              Tabellen allerdings aus.)

              Das das wenn es genau so geschieht sehr langsam ist, ist mir klar ;-). Aber ich hab irgendwo mal gelesen, ich glaube es war in dem Buch von Paul Dubois "Mysql und Perl", dass wenn man bei Mysql ein ein DELETE Statement ohne WHERE Klausel startet, werden die Zeilen um Last zu vermeiden (wie heißen sie nochmal in Wirklichkeit?) nicht einzeln gelöscht, sonder die Tabelle gelöscht und sofort neu angelegt. Was natürlich ein properietäres Feature ist. Eigentlich wollte ich das auch in meinem letzten Posting noch schreiben, aber habe es dann doch irgendwie vergessen.
              Naja, ich  suche die betreffende Textstelle mal.

              mfg

              Andres Freund

              PS: So ein Informatik Studium wäre wirklich was interressantes.

              1. Hallo!

                Naja, ich  suche die betreffende Textstelle mal.

                In der Doku steht folgendes:
                "Wenn Sie DELETE ohne WHERE-Klausel angeben, werden alle Zeilen gelöscht. Wenn Sie das im AUTOCOMMIT-Modus machen, funktioniert es wie TRUNCATE. See section 7.4.7 TRUNCATE-Syntax. In MySQL 3.23 gibt DELETE ohne eine WHERE-Klausel als Anzahl von betroffenen Datensätzen 0 zurück."
                http://de.mysql.com/documentation/mysql/bychapter/manual.de_Reference.html#DELETE

                "Wenn Sie alle Zeilen in der Tabelle löschen wollen, sollten Sie TRUNCATE TABLE tabelle benutzen. See section 7.4.7 TRUNCATE-Syntax."
                http://de.mysql.com/documentation/mysql/bychapter/manual.de_MySQL_Optimisation.html#Delete_speed

                Was der "AUTOCOMMIT-Modus" ist kann ich Dir leider nicht sagen, vermutlich steht das auch in der Doku, bin jetzt aber mal faul ;-)

                PS: So ein Informatik Studium wäre wirklich was interressantes.

                das Studium nicht so glaube ich ;-)

                Grüße
                Andreas

                1. Hi

                  Was der "AUTOCOMMIT-Modus" ist kann ich Dir leider nicht sagen, vermutlich steht das auch in der Doku, bin jetzt aber mal faul ;-)

                  Das weiß ich sogar, wenn du einen Tabellentyp benutzt , der Transaktionen unterstützt, das währen bei mysql soviel ich weiß InnoDB und BDB, dann kannst du mit Autocommit=1 Transaktionen bestätigen, oder mit Autocommit=0 eine neue Transaktion starten. Wenn du Autocommit dauerhaft gleich 1 setzt, wird jeder Eintrag einzeln vorgenommen.
                  Falls du nicht weißt was Transaktionen sind, eine grobe Erklärung:
                  Wenn du einen eintrag in eine DB machst, wird die während einer Eingabe Inkonsistent, dh. wenn die DB crasht, kann es sein dass die eingabe nicht vorgenommen wird. Oder wenn du mehrere Eingaben gleichzeitig oder eine die mehrere Felder gleichzeitig ändert wird z.b feld 100 durch Statement 2 (die jedes Feld verändert) verändert wäherend Statement 1 aufgrund einer komplizierten WHERE Klausel erst bei Feld 10 ist, und die WHERE Klausel bei Feld 100 aufgrund der Veränderung von Abfrage 2 nicht mehr zutrifft. Das gleiche trifft natürlich auch zu, wenn mehrere Clients/Prozesse gleichzeitig auf die Db zugreifen.
                  Deswegen werden viele Statements zu einer Transaktion zusammengefasst, die dann auf einmal stattfindet, wodurch die DB nicht inkonsitent wird. Ausserdem können, wenn während eines Skriptes ein Fehler auftritt, die Änderungen abgebrochen werden, so dass die DB nicht zt. alte und zt. neue Daten hat.
                  Ich hoffe ich habe das einigermaßen verständlich und richtig ausgedrückt.

                  PS: So ein Informatik Studium wäre wirklich was interressantes.
                  das Studium nicht so glaube ich ;-)

                  Doch, ich kenn jemand der am Stidieren ist, und es sehr interresant findet.

                  Noch eine Frage: Ich bin ebenfalls gerade am Schreiben einer Suchmaschiene für eine Internetseite und wollte daher fragen, ob du den Teil deines Skriptes in dem User-Eingaben in SQL geparst wird sehen, da ich mir da noch nicht so sicher bin, wie ich das machen soll.

                  Mfg
                  Andres Freund

                  1. Hallo!

                    Danke für die Erklärungen zu Transaktionen, ich wußte das nur so halb.

                    Doch, ich kenn jemand der am Stidieren ist, und es sehr interresant findet.

                    Kommt auch drauf an wo und was genau man studiert, hioer in Aachen, TH, soll das mit mathe sehr extrem sein. An der FH dagegen schon ganz anders, erheblich praxisnäher.

                    Noch eine Frage: Ich bin ebenfalls gerade am Schreiben einer Suchmaschiene für eine Internetseite und wollte daher fragen, ob du den Teil deines Skriptes in dem User-Eingaben in SQL geparst wird sehen, da ich mir da noch nicht so sicher bin, wie ich das machen soll.

                    Obwohl ich den Satz jetzt nicht wirklich verstehe, hier mal mein PARSE-Teil, aber ich warne, das ist noch eine "Großbaustelle", ich ändere noch immer viel zu viel, als das es ein vernünftiger Code wäre

                    function query($sql){
                     global $link;
                     $result = mysql_query($sql,$link)
                      or die ("Folgende SQL-Abfrage ist gescheitert: ".$sql." <br>\n MySQL-Fehlermeldung: ".mysql_error()." (".mysql_errno().")");
                     return $result;
                    }

                    if ($_GET['submit']=="Suche starten"){

                    $limit = 1000;

                    $such_array = explode (" ",$_GET['suchausdruck']);
                    foreach ($such_array as $teilstring) {
                        if(substr($teilstring,0,1)=="+") {
                            $and_array[] = substr($teilstring,1);
                        }
                       else if(substr($teilstring,0,1)=="-") {
                            $not_array[] = substr($teilstring,1);
                        }
                        else {
                            $rest_array[] = $teilstring;
                        }
                    }

                    if($and_array){
                        foreach($and_array as $teilstring) {
                            if ($bedingung_vorhanden == 1) {
                                $query_where_bedingung .= " AND";
                            }
                            $query_where_bedingung .= "
                    MATCH (topic,title,name,body) AGAINST ('".mysql_escape_string($teilstring)."')";
                            $bedingung_vorhanden = 1;
                        }
                    }

                    if($not_array){
                        foreach($not_array as $teilstring) {
                            if ($bedingung_vorhanden == 1) {
                                $query_where_bedingung .= " AND";
                            }
                            $query_where_bedingung .= "
                    !MATCH (topic,title,name,body) AGAINST ('".mysql_escape_string($teilstring)."')";
                            $bedingung_vorhanden = 1;
                        }
                    }
                    if($rest_array){

                    if($not_array || $and_array || $_GET['and'] != 1){
                            if ($bedingung_vorhanden == 1) {
                                $query_where_bedingung .= " AND";
                            }
                            $query_where_bedingung .= "
                    MATCH (topic,title,name,body) AGAINST ('".mysql_escape_string(implode(" ",$rest_array))."')";
                        }
                        else{
                            foreach($rest_array as $teilstring) {
                                if ($bedingung_vorhanden == 1) {
                                    $query_where_bedingung .= " AND";
                                }
                             $query_where_bedingung .= "
                    MATCH (topic,title,name,body) AGAINST ('".mysql_escape_string($teilstring)."')";
                             $bedingung_vorhanden = 1;
                            }
                        }
                    }

                    $query_string = "SELECT id,topic,title,name,time
                    FROM selfarchiv
                    WHERE";
                    $query_string .= $query_where_bedingung;

                    if($_GET['Verfasser']) {
                        $query_string .= "
                    AND INSTR(name,'".mysql_escape_string($_GET['Verfasser'])."')>0";
                    }
                    if($_GET['Kategorie']) {
                        $query_string .= "
                    AND topic = '".mysql_escape_string($_GET['Kategorie'])."'";
                    }
                    $query_string .= "
                    LIMIT 0, $limit";

                    $full_query = "CREATE TEMPORARY TABLE temp_tabelle TYPE=HEAP
                    ".$query_string;

                    $filter_query = "SELECT * FROM temp_tabelle ORDER BY time DESC LIMIT 0, 100";

                    $temp_result = query($full_query);
                    $result = query($filter_query);
                    }

                    Wie gesagt, keine Gewähr, ich habe das ganze Konzept zum testen mehrmals grundlegend umgestellt, und noch nicht alles angepasst...

                    Ist übrigens PHP.

                    Grüße
                    Andreas

                    1. Hi

                      Danke für die Erklärungen zu Transaktionen, ich wußte das nur so halb.

                      Bitte...

                      Doch, ich kenn jemand der am Stidieren ist, und es sehr interresant findet.
                      Kommt auch drauf an wo und was genau man studiert, hioer in Aachen, TH, soll das mit mathe sehr extrem sein. An der FH dagegen schon ganz anders, erheblich praxisnäher.

                      Naja, ich mag Mathe, bin da allerdings von der Schule aus noch nicht mit extremeren ;.) Sachen zusammengetroffen, da ich leider erst in der 11Klasse bin.

                      Noch eine Frage: Ich bin ebenfalls gerade am Schreiben einer Suchmaschiene für eine Internetseite und wollte daher fragen, ob du den Teil deines Skriptes in dem User-Eingaben in SQL geparst wird sehen, da ich mir da noch nicht so sicher bin, wie ich das machen soll.

                      Obwohl ich den Satz jetzt nicht wirklich verstehe, hier mal mein PARSE-Teil, aber ich warne, das ist noch eine "Großbaustelle", ich ändere noch immer viel zu viel, als das es ein vernünftiger Code wäre

                      Ich frag mich auch gerade, was führ ein Teufel mich da geritten hat;-). ABer die Reaktion war trotzdem richtig;-), ich meinte, ob ich den Quelltext mal sehen kann, was du ja nun getan hast.
                      Danke!

                      Wie gesagt, keine Gewähr, ich habe das ganze Konzept zum testen mehrmals grundlegend umgestellt, und noch nicht alles angepasst...

                      Ich will ja auch nur ein paar Ideen, damit ich nen bisschen genauere vorstellungen davon bekomme, wie ich das alles machen soll/weitermachen soll.

                      Ist übrigens PHP.

                      Oh, nein. Warum bloß PHP? Da muss ich mich ja mal wieder da nen bisschen reinknieen damit ich was verstehe. Ich arbeite normalerweise mit Perl  und verstehe nicht wirklich was von PHP. ;-(

                      Grüße
                      Andreas

                      Ebenfalls Grüße
                      Andres Freund

                      1. Hi Andres,

                        Kommt auch drauf an wo und was genau man
                        studiert, hioer in Aachen, TH, soll das
                        mit mathe sehr extrem sein. An der FH dagegen
                        schon ganz anders, erheblich praxisnäher.
                        Naja, ich mag Mathe, bin da allerdings von der
                        Schule aus noch nicht mit extremeren ;.) Sachen
                        zusammengetroffen, da ich leider erst in der
                        11Klasse bin.

                        da geht es bei Dir gerade mit Analysis los - irgend-
                        wann in der Oberstufe sollte noch Lineare Algebra und
                        ein bißchen Wahrscheinlichkeitsrechnung kommen.

                        Analysis gibt es auf der Uni dann in geballter Form
                        (da hab ich drei Kreuze gemacht, als ich die Vor-
                        diplomprüfung hinter mir hatte); auch bei Algebra
                        wird es sehr viel detaillierter (vor allem abstrakter

                        • mit Zahlen hat das alles nichts mehr zu tun).

                        Das Abschreckende an den Mathe-Vorlesungen war für
                        mich, daß alles und jedes bewiesen wurde.
                        Das ist für diejenigen, die wirklich Mathe studieren,
                        sinnvoll - aber letzten Endes merkt man sich meistens
                        nur, _daß_ etwas gilt. Beweisen könnte ich die meisten
                        Aussagen heute auch nicht mehr.

                        An der FH ist alles "etwas dünner" - man lernt mehr
                        Programmieren und Projektarbeit, aber weniger Theorie
                        (was ich schade finde, denn mit soliden Theoriekennt-
                        nissen kann man sich später _alles_ andere schneller
                        beibringen).

                        Obwohl ich den Satz jetzt nicht wirklich
                        verstehe, hier mal mein PARSE-Teil, aber ich
                        warne, das ist noch eine "Großbaustelle", ich
                        ändere noch immer viel zu viel, als das es ein
                        vernünftiger Code wäre

                        Sehr viel übersichtlicher ist es bei mir auch nicht.
                        Ich habe mir allerdings pro Term der WHERE-Liste eine
                        function geschrieben und konkateniere deren Ergebnisse.

                        Ist übrigens PHP.
                        Oh, nein. Warum bloß PHP? Da muss ich mich ja mal
                        wieder da nen bisschen reinknieen damit ich was
                        verstehe. Ich arbeite normalerweise mit Perl und
                        verstehe nicht wirklich was von PHP. ;-(

                        Das ist in diesem Falle egal. Mehr als ein Haufen
                        Fallunterscheidungen, String-Concats und das Verwalten
                        eines Flags, ob man den nächsten TERM schon mit AND
                        dran kleben muß oder noch mit WHERE, ist es nicht.

                        Viele Grüße
                              Michael

                        1. Hi

                          da geht es bei Dir gerade mit Analysis los - irgend-
                          wann in der Oberstufe sollte noch Lineare Algebra und
                          ein bißchen Wahrscheinlichkeitsrechnung kommen.

                          Ne, das haben wir zumindest z.T auch schon gemacht.

                          Ist übrigens PHP.
                          Oh, nein. Warum bloß PHP? Da muss ich mich ja mal
                          wieder da nen bisschen reinknieen damit ich was
                          verstehe. Ich arbeite normalerweise mit Perl und
                          verstehe nicht wirklich was von PHP. ;-(

                          Das ist in diesem Falle egal. Mehr als ein Haufen
                          Fallunterscheidungen, String-Concats und das Verwalten
                          eines Flags, ob man den nächsten TERM schon mit AND
                          dran kleben muß oder noch mit WHERE, ist es nicht.

                          Das ist schon klar, aber ich mag PHP aus einem mir unbekannten Grund nicht. Aber eigentlich ist das allermeiste sowieso verständlich, wenn man Perl kann und sowieso, wenn man einige üblicher Sprache kennt.

                          mfg Andres Freund

                          1. Hi

                            da geht es bei Dir gerade mit Analysis los - irgend-
                            wann in der Oberstufe sollte noch Lineare Algebra und
                            ein bißchen Wahrscheinlichkeitsrechnung kommen.

                            Ne, das haben wir zumindest z.T auch schon gemacht.

                            Ich meinte die Wahrscheinlichkeitsrechnung, aber habe das vergessen dazuzuschreiben. Liegt vielleicht daran das ich ein Naturwissenschftliches Profil habe.

                            mfg Andres Freund

      2. Hallo!

        das ist eine MyISAM Tabelle auch, udn trotzdem muß man meiens Wissens den Typ der temporären Tabelle angeben, also entweder myISAM oder HEAP. Udn ich dachte mir das es gerade hierfür schneller ist wenn man auf Plattenzugriffe verzichten kann.

        Nein Standardmäßig wird MYISAM genommen. Ich werde daß auch mal ausproboeren, ob eine temporäre Tabelle mit dem Type HEAP für alle sichbar ist. Oder hast Du das schon gemacht?

        MAX ROW bezieht sich doch bestimmt auf CREATE TABLE, oder?

        Ja.

        CREATE TABLE tabelle ( Angaben ) MAX_ROWS = 200;

        // oder/usw.

        CREATE TABLE tabelle ( Angaben ) TYPE = MYISAM MAX_ROWS = 200;

        Was fpr Indexe? MySQL speichert die erzeugten Indexe doch selbst?

        Ich meinte damit z.B. eine lange Liste von Zahlen/IDs, für die man einen schnelleren Zugriff benötigt.

        MfG, André Laugks
        L-Andre @ gmx.de

  2. Hi Andreas,

    Das Problem ist, das das ganze bei größeren
    Sortiervorgängen unglaublich langsam wird.

    dann vermeide sie. Sortiere erst, nachdem Deine
    Treffermenge einige hundert Zeilen nicht übersteigt.
    Mehr willst Du ohnehin nicht ausliefern.

    Daher hatte ich mir überlegt, ich schreibe das
    Ergebnis, welches ich mit der FULLTEXT-Suche
    gefunden habe in eine temporäre Tabelle mit
    begrenzter Datensatz-Anzahl.

    Welche Cache-Hit-Rate erwartest Du?
    Ich würde etwas im einstelligen Prozentbereich
    erwarten, und dafür lohnt sich ein Cache nicht.

    Jetzt stellt sich die Frage welches Tabellenformat
    ich hierfür verwende. Das beste sollen wohl HEAP-
    Tabellen sein, da die direkt im Arbsitspeicher
    geladen werden, udn daher extrem schnell sein
    sollen.

    Im Prinzip hast Du Recht: Wenn Du einen Cache halten
    willst, dann wäre in bestimmten Fällen ein Hash, wie
    der Tabellentreiber HEAP ihn realisiert, eine gute
    Idee. Aber hauptsächlich dann, wenn Du später wieder
    auf diesen Hash über eine Indexstruktur zugreifen
    willst - ist das bei Dir der Fall?

    Und für diesen Indexzugriff zahlst Du einen Preis:
    Der Index will erst einmal aufgebaut werden. Bei HEAP
    geschieht das offenbar implizit - dadurch wird _dies_
    aber um kein bißchen schneller.
    Der Aufwand zum Sortieren, den Du kennst und fürchtest,
    ist beim Aufbau des HEAP natürlich ebenfalls notwendig,
    denn das Ergebnis dieser Sortierung ist das Adressie-
    rungssystem für die Einträge des HEAP.

    Dieses System wäre also sinnvoll, wenn Du
    a) sehr oft auf das Ergebnis zugreifen und
    b) dabei immer kleine Teilmengen heraussuchen willst,
       die Du über kleine Mengen von Spaltenwerten angibst.
    Dieses Szenario liegt bei Deiner Suche m. E. nicht vor.

    1. Frage ist, welche Daten alle in der temporären
      Tabelle stehen müssen. Am besten schreibt man doch
      alle gefunden Daten in die temporäre Tabelle, um
      dei Datenn direktsortert ausgeben zu können, oder
      sollte man nur die IDs in die Tabelle schreiben und
      auf die "feste" Tabelle joinen?

    Hast Du überhaupt die Wahl - wird immer exakt derselbe
    JOIN durchgeführt werden? (In meinem Szenario ist das
    nicht der Fall ...)

    Wenn Du die Tabelle als Cache haben willst, dann
    willst Du sehr oft darauf zugreifen.
    Willst Du den anschließenden (und wahrscheinlich
    ebenfalls teuren) JOIN ebenfalls sehr oft durchführen?

    Ein Cache versucht, CPU-Last durch den Einsatz von
    Speicher einzusparen.
    Das ist nicht der Moment, um am Speicher zu sparen. ;-)

    1. welchen Namen verwende ich für die temporäere
      Tabelle? So wie ich das verstanden habe, sind die
      Temporären Tabellen, so lange existent, für alle
      Clients "gültig".

    Nein - nur für Deinen Task.
    Deshalb stellt sich Deine Frage gar nicht.

    Das heißt wenn cihd ei Tabelle "temp_table" nenne,
    kann es bei gleicheitigen Zugriffen auf das Script
    welches die temp-Tabelle erzeugt zu Konflikten
    kommen.

    Richtig. Genau das wird passieren, wenn Du nicht-
    temporäre Tabellen verwenden willst, um das Ergebnis
    für weitere Zugriffe zu speichern.
    Du müßtest Dir die Namen der Tabellen unique generieren
    und eine Tabelle mit der Liste aller Tabellen speichern
    ... oder alternativ den Namen der temporären Tabelle
    als zusätzliche Spalte in eine Supertabelle aufnehmen,
    aus der Du mit diesem Namen alle Werte der Teil-Tabelle
    herausfiltern kannst ...
    Dynamisch viele Tabellen können schrecklich werden.

    Andererseits hat die Verteilung Deiner Daten auf meh-
    rere Tabellen durchaus ihren Reiz.
    Wenn Du das aber mal konsequent weiter denkst, könntest
    Du auf die Idee kommen, bereits bei der Speicherung
    der Postings mehrere Tabellen zu verwenden - so, wie
    die bisherige Self-Suche mehrere Indexdateien nutzt.
    Wenn Du dann chronologisch rückwärts die Treffer bis
    zu einem bestimmten Limit aufsammelst, mußt Du wahr-
    scheinlich nur bei sehr guten Suchbegriffen wirklich
    alle Tabellen durchsuchen - bei schlechten reicht die
    allererste ... Du hast also je nach Suchbegriffen ent-
    weder viele schnelle oder nur eine langsame Query,
    letztere aber auf einer Teilmenge aller Daten ...

    1. Mir geht es vor allem auch um ORDER BY, und das
      kann HEAP nicht, oder?

    Tabellentreiber sollten für die konkrete Syntax der
    DML-Statements eigentlich transparent sein. Wie der
    Tabellentreiber ein ORDER BY realisiert, das laß mal
    seine Sache sein. Und wenn Du genau nach demjenigen
    Kriterium sortierst, welches der Schlüssel seines
    Hash-Baums ist, dann kann das SELECT vielleicht ein-
    fach den bereits sortiert vorliegenden Indexbaum
    ablaufen ...

    Das kann aber immer noch sehr langsam sein!
    Indexzugriffe macht man, um kleine Teilmengen aus
    einer großen Gesamtmenge zu extrahieren - nicht, um
    eine große Menge damit zu sortieren.
    Faustregel: Ein Indexzugriff kostet Faktor 7 (!) mehr
    als ein full table scan. Wenn Dein Index also 15% der
    vorhandenen Zeilen zurückliefert, hast Du gerade den
    break-even.

    Sie können nicht nach dem nächsten Eintrag in der

    Reihenfolge suchen (also den Index benutzen, um ein
    ORDER BY zu machen).

    Ah - dann geht das, was ich im vorherigen Absatz be-
    schrieben habe, genau bei HEAP nicht performant.
    (Natürlich geht ORDER BY, aber Du verlierst dabei die
    positiven Eigenschaften des HEAP.)

    SELECT id,topic,title,name,time
    FROM selfarchiv
    WHERE
    MATCH (topic,title,name,body) AGAINST ('Datenbank') AND
    MATCH (topic,title,name,body) AGAINST ('MySQL')
    LIMIT 0, 100;
    Das funktioniert sehr schnell, wenn das ganze
    erstmal im Cache ist.

    Allerdings sind sowohl "MySQL" als auch "Datenbank"
    keine "guten" Suchbegriffe - vor allem der zweite ist
    viel zu häufig.
    In diesem extremen Fall würde ich "Datenbank" auf die
    Schwarze Liste setzen, den MATCH nur über mySQL machen
    und "Datenbank" via normalen WHERE (LIKE) prüfen.
    Wenn die Häufigkeit beider Suchbegriffe sich um mehr
    als eine Zehnerpotenz unterscheidet, kann diese Methode
    besser sein.
    Der Trick besteht natürlich darin, aus Deinen Daten
    eine wirklich gute Schwarze Liste zu berechnen ...
    daran habe ich eine ganze Weile gesessen.

    SELECT id,topic,title,name,time
    FROM selfarchiv
    WHERE
    MATCH (topic,title,name,body) AGAINST ('Datenbank') AND
    MATCH (topic,title,name,body) AGAINST ('MySQL')
    ORDER BY time DESC
    LIMIT 0, 100;

    das dauert immer tierisch lange, egal was ich mache.

    Ja - Du sortierst viele tausend Treffer und wirfst
    danach fast alle wieder weg.

    Daher hatte ich mir das ungefähr so überlegt:
    CREATE TEMPORARY temp_tabelle  (
    INSERT INTO temp_tabelle (id,topic,title,name,time)

    Das kannst Du sogar zu _einem_ Befehl zusammensetzen.

    SELECT id,topic,title,name,time
    FROM temp_tabelle
    ORDER BY time DESC;

    Genau so mache ich das in meiner Anwendung.
    (Ich habe allerdings noch mehr Filterschritte - einer
    davon ist ein JOIN gegen eine Entitlement-Tabelle.)

    So hatte ich mir das in etwas gedacht.

    Mach es einfach!

    Oder wäre es besser die unsortierten Daten direkt
    auszulesen, ohne Temporäre Tabelle und ORDER BY,
    das ganze in einen Array schreiben und den
    sortieren?

    Das kommt auf Deine Sortierfunktion an. Es ist auf
    jeden Fall eine Möglichkeit, die Du prüfen solltest.

    Mit einer guten Sortier-Funktion, die nicht die Zeilen
    verschiebt, sondern nur Verweise darauf, und die
    logarithmisch schnell arbeitet, solltest Du einem
    ORDER BY in nichts nachstehen.

    Ich habe in meinem Fall sogar einen JOIN in Perl
    realisiert, weil es performanter ging, eine Spalte
    meiner Treffer gegen einen Hash zu filtern - es war
    halt ein JOIN, bei dem ich aus der zweiten Tabelle
    keine Felder übernehmen mußte, aber einige hundert
    Werte matchen mußte, zu viele für ein "IN" in einer
    WHERE-Klausel.

    Was ist von wegen Länge der Temporären Tabelle zu
    beachten? Sollte ich das mit einem Limit bschränken,
    oder ist es egal wenn da einige 1000 Tabellen drin
    stehen

    Da stehen immer nur ganz wenige Tabellen - nach dem
    Ende Deiner Anwendung räumt mySQL sie wieder weg.

    denn nur wenn ich alle Datensätze habe kann ich auch
    korrekt sortieren, ohne das evtl. relevante
    Ergebnisse unter den Tisch fallen?

    Tja, _das_ ist der Knackpunkt an Deiner Anwendung:

    Willst Du Performance oder Ergebnisqualität als oberste
    Priorität? Beides geht nicht ... und ich finde, daß
    die Qualität nicht darunter leidet, wenn Du für eine
    schlechte Eingabe des Benutzers ein schlechteres Er-
    gebnis und eine Aufforderung zur Verbesserung der
    Eingabe zurück lieferst, dies aber sehr schnell tust

    • so schnell, daß sich der Anwender tatsächlich in-
      krementell seine Suche mit try & error zusammenbauen
      kann, selbst wenn das mehrere Aufrufe der Suchmaschine
      kostet.

    Viele Grüße
          Michael

    1. Hi Michael!

      Bin jetzt nicht so sicher, aber ich habe das Gefühl, das wir ein wenig aneinander vorbei geredet haben. Ich habe das mit Der HEAP-Tabelle nur gemacht, um dei Daten irgendwie zum sortieren zwischenzuspeichern. Und das geht wirklich noch erheblich besser und schneller als ich gedacht hätte.
      For allem dachte ich mir, spare ich mir so einen Plattenzugriff, daher HEAP. Das ist da immer nur eine Ergebnistabelle mit allen Feldern außer dem eigentlichen Postings, das hat der Fulltext ja bereits durchsucht und das kostet mit riesigem Abstand die meiste Performance. Also habe ich jetzt nur noch die restlichen Felder im RAM stehen, maximal 1000, die sortiere ich dann und lese sie aus. Da es eine Temporäre Tabell ist wird diese nach bveendigung der Verbindung aus dem RAM gelöscht, und es ergeben sich auch keine Überschneidungen.

      Das geht superschnell! nie über 1/1000 Sekunde. Und ich gebe Dir vollkommen Recht, wenn jemand schlechte Begriffe eingibt, dann müssen nicht im Gegenzug alle anderen auf gute Performacne verzichten, so würde auf die falschen Leute zu viel Rücksicht genommen finde ich.

      Das letzte Problem besteht jetzt eigentlich in dem Index-Cache, oder wie auch immer das Ding heißt. Wie gesagt, beim ersten mal über 20 Sekunden, beim 2. mal 10, beim 3. mal 4 und danach immer zw. 0,2 und 0,4. Aber die Suchbegriffe sind doch derart verschieden, dass am Ende die meisten Leute 4 Sekunden und mehr warten müssen, und der ganze Server entsprechen beansprucht würde. Und wenn man den mysqld mal neu startet gehts wieder von vorne los! Wenn ich mal bei webalizer gucke, da machen Such-Strings die 3 mal und weniger eingegeben wurden ca. 60-70% der gesamten Such-Anfragen aus(in einem Monat). Das hieße vermutlich am Ende eine Durchschnitts-Suchzeit von 5 oder mehr Sekunden! Das kann so doch nicht funktionieren!

      Was meinst Du wie ich das verändern kann? Die Zeit geht bei

      CREATE TEMPORARY TABLE temp_tabelle TYPE=HEAP
      SELECT id,topic,title,name,time
      FROM selfarchiv
      WHERE
      MATCH (topic,title,name,body) AGAINST ('Andreas') AND
      MATCH (topic,title,name,body) AGAINST ('fsockopen()')
      LIMIT 0, 1000

      verloren, was aber genau so schnell/langsam ist, wie ohne CREATE

      bei

      SELECT * FROM temp_tabelle ORDER BY time DESC LIMIT 0, 100

      dagegen dauert es wie gesagt imme unter 0,001 Sekunden.

      Was könnte man hier machen? Ich denke das ist das letze Problem, selbst das instr() kostet fast nichst, vielleicht kann ich entweder in der ersten Suche, oder in der 2. noch mit regexp arbeiten, das geht ja in mysql(http://de.mysql.com/documentation/mysql/bychapter/manual.de_Regexp.html#Regexp
      )

      Grüße
      Andreas

      1. Hi Andreas,

        Bin jetzt nicht so sicher, aber ich habe das Gefühl,
        das wir ein wenig aneinander vorbei geredet haben.

        am Anfang Deines letzten Postings - ja.

        Die Sache mit dem angeblichen Überleben der temporären
        Tabelle hat mich in die Irre geführt - es klang so, als
        würdest Du das wirklich wollen.

        Ich habe das mit Der HEAP-Tabelle nur gemacht,
        um dei Daten irgendwie zum sortieren zwischenzu-
        speichern. Und das geht wirklich noch erheblich
        besser und schneller als ich gedacht hätte.

        Das wundert mich.

        Anläßlich unserer Diskussion habe ich in _meiner_
        Anwendung vorgestern eine meiner temporären Tabellen
        auf HEAP umgestellt, und es war ein Desaster:
        Der Aufbau der sortierten Struktur dauerte schon bei
        einigen hundert Treffern entsetzlich lange (20 Sekun-
        den oder so).

        For allem dachte ich mir, spare ich mir so einen
        Plattenzugriff, daher HEAP.

        Ja, aber. ;-)

        Einerseits kannst Du in dieser Hinsicht wahrschein-
        lich doch eher an der mySQL-Konfiguration drehen (da
        mußt Du halt wirklich mal alle Variablen im Handbuch
        nachschlagen - das lohnt sich aber).

        Und andererseits kann ein gut konfiguriertes Festplat-
        tensystem die Sache auch beschleunigen, vermute ich.

        Das ist da immer nur eine Ergebnistabelle mit allen
        Feldern außer dem eigentlichen Postings, das hat
        der Fulltext ja bereits durchsucht und das kostet
        mit riesigem Abstand die meiste Performance.

        Völlig richtig: So wenige Spalten mitnehmen wie nötig.
        Lieber die SELECT-Felderliste dynamisch berechnen, als
        einfach "*" hinschreiben etc.

        Also habe ich jetzt nur noch die restlichen Felder
        im RAM stehen, maximal 1000, die sortiere ich dann
        und lese sie aus. Da es eine Temporäre Tabell ist
        wird diese nach bveendigung der Verbindung aus dem
        RAM gelöscht, und es ergeben sich auch keine
        Überschneidungen.

        Da ich das Sortieren in meiner Anwendung mache, habe
        ich durch eine temporäre MYISAM-Tabelle keinerlei
        Nachteile gegenüber HEAP.

        Du erinnerst Dich vielleicht, daß ich Dich gefragt
        hatte, ob Du Schreibzugriffe auzf der Festplatte wäh-
        rend Deiner Suchmaschinen-Abfragen beobachten kannst?
        Das solltest Du unbedingt prüfen.
        Bei mir war das nämlich eine schreckliche Performance-
        Bremse, daß mySQL die temporären Tabellen auf die
        Festplatte geschrieben hat - weil es einen Pfad dafür
        vorkonfiguriert hatte, von dem es hoffte, dort eine
        RAM-Disk zu finden ... jetzt haben wir dort eine.
        http://www.mysql.com/doc/en/Temporary_files.html

        Das letzte Problem besteht jetzt eigentlich in dem
        Index-Cache, oder wie auch immer das Ding heißt.
        Wie gesagt, beim ersten mal über 20 Sekunden, beim
        2. mal 10, beim 3. mal 4 und danach immer zw. 0,2
        und 0,4.

        Welche IO-Zugriffsraten hast Du während dieser Zeit?
        (Siehe auch den vorherigen Absatz.)

        Schau Dir mal mit "top" die IOWAIT-Zeiten an - wenn
        die dramatisch hoch gehen, dann kommt Deine Festplatte
        nicht mit.

        Und wenn man den mysqld mal neu startet gehts wieder
        von vorne los!

        Yep. Deine Tabellen _sind_ nun mal groß.

        Wäre das, was Du da tust, eine richtig teure kommer-
        zielle Anwendung, dann würde ich sagen: Hau 8 GB RAM
        in die Kiste rein und konfiguriere mySQL so, daß es
        den FULLTEXT-Index komplett im RAM halten kann ...

        Wenn ich mal bei webalizer gucke, da machen Such-
        Strings die 3 mal und weniger eingegeben wurden
        ca. 60-70% der gesamten Such-Anfragen aus(in einem
        Monat).

        Diese Erfahrung kann ich tendentiell bestätigen.

        Das hieße vermutlich am Ende eine Durchschnitts-
        Suchzeit von 5 oder mehr Sekunden! Das kann so doch
        nicht funktionieren!

        Richtig.
        Irgendwas an Deiner Konfiguration tut noch nicht.

        Ich denke, in Sachen SQL hast Du alles ausgereizt;
        jetzt geht es ans mySQL-Tuning und darum, die dann
        noch unvermeidlichen Festplattenzugriffe so schnell
        wie möglich zu machen.

        Was meinst Du wie ich das verändern kann? Die Zeit geht bei

        CREATE TEMPORARY TABLE temp_tabelle TYPE=HEAP

        Ich zweifele daran, daß HEAP eine gute Idee ist.

        MATCH (topic,title,name,body) AGAINST ('Andreas')

        Das ist bestimmt _nicht_ gut.

        MATCH (topic,title,name,body) AGAINST ('fsockopen()')

        Der zweite Suchbegriff ist um Größenordnungen besser!

        Ein normales "WHERE" für den "Andreas", selbst eines
        mit LIKE über die gesamte Story, hat Chancen, besser
        zu sein. Mach mal einen direkten Vergleich ...

        LIMIT 0, 1000

        Das wirkt zu spät. Du berechnest zunächst einige
        tausend Treffer mit "Andreas", joinst ("AND") diese
        gegen ein paar Dutzend "fsockopen" (das _ist_ teuer!)
        und erst danach begrenzt Du auf 1000 Stück, die Du
        aber nach dem JOIN bestimmt schon nicht mehr hast.

        verloren, was aber genau so schnell/langsam ist,
        wie ohne CREATE

        Yep. Mach eine Statistik über alle Worte Deiner Daten-
        bank - und setze "Andreas" auf die Schwarze Liste. ;-)

        SELECT * FROM temp_tabelle ORDER BY time DESC LIMIT
        0, 100
        dagegen dauert es wie gesagt imme unter 0,001
        Sekunden.

        Klar - da ist das Problem auch schon gelöst.

        Was könnte man hier machen? Ich denke das ist das
        letze Problem,

        Aber auch eines der schwierigsten.
        Du bräuchtest eine Bewertungsfunktion, um gute WHERE-
        Klauseln zu berechnen, _bevor_ Du sie ausführst.
        Eine Schwarze Liste wäre _ein_ möglicher Weg dorthin.

        Mach mal einen Test (jeweils mit mySQL-Neustart
        vorher): Ist die Dauer dieser Query abhängig von der
        Reihenfolge (!) der beiden Suchbegriffe?
        Wenn ja, dann ist der Query-Optimizer von mySQL nicht
        gut, und Du müßtest selbst die bessere der beiden
        Reihenfolgen ausrechnen. Das ist zwei SELECT gegen
        eine HEAP-Tabelle (Suchbegriff => Häufigkeit) wert.

        Mach mal einen zweiten Test: Definiere einen zusätz-
        lichen (!) FULLTEXT-Index über den Author und generie-
        re die WHERE-Klausel so, daß sie "Andreas" nur in
        diesem zweiten FULLTEXT sucht (was man in der alten
        Suche über die Eingabe "author:Andreas" ausdrücken
        kann).
        Ist _das_ schneller? Ich denke, ja - weil dann nur
        noch der seltenere Begriff im großen FULLTEXT-Index
        gesucht werden muß.
        Du wirst immer noch irre viele Treffer dabei finden
        und JOINen müssen, aber es sind weniger als bisher.

        mit regexp arbeiten, das geht ja in mysql

        Versuche es - aber rechne damit, daß dasselbe passiert
        wie bei LIKE %...%: Es werden wahrscheinlich keinerlei
        Indexzugriffe mehr möglich sein.

        EXPLAIN sagt Dir, was Du wissen willst.

        Viele Grüße
              Michael

        1. Hallo Michael!

          Ich habe das mit Der HEAP-Tabelle nur gemacht, um dei Daten irgendwie zum sortieren zwischenzu- speichern. Und das geht wirklich noch erheblich besser und schneller als ich gedacht hätte.

          Das wundert mich.

          Wieso? das Wesen einer HEAP-Tabelel ist es doch die Daten im RAM, zu speichern, das ist doch perfekt, und in der Doku steht doch auch das es ganeu dazu gedacht ist, also nicht ganz, aber so ähnlich ;-)

          Anläßlich unserer Diskussion habe ich in meiner Anwendung vorgestern eine meiner temporären Tabellen auf HEAP umgestellt, und es war ein Desaster: Der Aufbau der sortierten Struktur dauerte schon bei einigen hundert Treffern entsetzlich lange (20 Sekun- den oder so).

          Dir ist klar das ich die Temporäre Tabelle mit den den Ergebnissen der Fulltext-Suche meine, in der bereits keine Postings mehr stehen? Das ist doch nichts an Speicherplatz, udn wenn dafür keien Plattenzugriffe notwendig sind(was nicht der Fall ist), dann ist es doch perfekt!

          For allem dachte ich mir, spare ich mir so einen Plattenzugriff, daher HEAP.

          Ja, aber. ;-)

          Einerseits kannst Du in dieser Hinsicht wahrschein- lich doch eher an der mySQL-Konfiguration drehen (da mußt Du halt wirklich mal alle Variablen im Handbuch nachschlagen - das lohnt sich aber).

          Hab ich ja, egal was ich da drehem das sind ja alles nur obergrenzen die mir nicht be der ersten Suche helfen, sondern nur nachfolgende Suchen beschleunigen, da einfach mehr im Cahce gehalten werden  kann. ich habe wirklich alle Paramterr verdoppelt, teilweise ver-4-facht, brint alles nicht! Kein Stück!

          Und andererseits kann ein gut konfiguriertes Festplat- tensystem die Sache auch beschleunigen, vermute ich.

          Ja, sicher, aber das habe ich hier nicht! Wie schon beschrieben. Ich kann das alles später mal unter Windows laufen lassen, die Platte ist rel. neu und über 133 ATA angebunden, mal gucken wie sich das auswirkt.

          Das ist da immer nur eine Ergebnistabelle mit allen Feldern außer dem eigentlichen Postings, das hat der Fulltext ja bereits durchsucht und das kostet mit riesigem Abstand die meiste Performance.

          Völlig richtig: So wenige Spalten mitnehmen wie nötig. Lieber die SELECT-Felderliste dynamisch berechnen, als einfach "*" hinschreiben etc.

          Nltig ist im Prinzip nur ID und time, sollte ich die anderen Felder wie "autor" und "titel", dic ich ja später brauche aus der großen Tabelle joinen?

          Da ich das Sortieren in meiner Anwendung mache, habe ich durch eine temporäre MYISAM-Tabelle keinerlei Nachteile gegenüber HEAP.

          Aber ich dachte, HEAP wird im RAM abgelegt, und MyISAM auf der Festplatte! selbst bei einer schnellen Platte sollte das schlechter sein. Ich habe die Statemnents nicht evrändert, udn mal HEAP gegen MyISAM ausgetauscht, dann wird es 50% langsamer(das abfragen der Tabelle), das Create kann ich schlecht messen. Die Tabelle wird ja auch nur einmal gebraucht, also wäre es totale Zeitverschwendung eine Index anzulegen, und sonst bietet mir MyISAM hier keine Vorteile, im Gegenteil wie gesagt.

          Du erinnerst Dich vielleicht, daß ich Dich gefragt hatte, ob Du Schreibzugriffe auzf der Festplatte wäh- rend Deiner Suchmaschinen-Abfragen beobachten kannst? Das solltest Du unbedingt prüfen.

          Ja, aber das habe ich nicht geschafft zu prüfen.

          Bei mir war das nämlich eine schreckliche Performance- Bremse, daß mySQL die temporären Tabellen auf die Festplatte geschrieben hat - weil es einen Pfad dafür vorkonfiguriert hatte, von dem es hoffte, dort eine RAM-Disk zu finden ... jetzt haben wir dort eine.

          Daher dachte ich an HEAP!

          http://www.mysql.com/doc/en/Temporary_files.html

          Das letzte Problem besteht jetzt eigentlich in dem Index-Cache, oder wie auch immer das Ding heißt. Wie gesagt, beim ersten mal über 20 Sekunden, beim 2. mal 10, beim 3. mal 4 und danach immer zw. 0,2 und 0,4.

          Welche IO-Zugriffsraten hast Du während dieser Zeit? (Siehe auch den vorherigen Absatz.)

          Das versteh ich wie gesagt noch nicht richtig. Bei der Eingabe von "top" erhalte ich z.B.:

          2:25am  up 29 min,  1 user,  load average: 0,10, 0,24, 0,22 89 processes: 86 sleeping, 2 running, 1 zombie, 0 stopped CPU states: 19,9% user,  1,7% system,  0,0% nice, 78,2% idle Mem:   255412K av,  251120K used,    4292K free,       0K shrd,    1772K buff Swap:  522104K av,       0K used,  522104K free                  160248K cached

          PID USER     PRI  NI  SIZE  RSS SHARE STAT %CPU %MEM   TIME COMMAND  1030 root       5 -10 62476  12M  5584 S <  15,5  5,0   1:00 X  1239 root      15   0  9128 9124  6968 R     5,1  3,5   0:01 gnome-terminal  1264 root      15   0   988  988   780 R     0,3  0,3   0:01 top  1127 root      15   0  6032 6028  5084 S     0,1  2,3   0:01 magicdev  1131 root      15   0 10996  10M  8504 S     0,1  4,3   0:01 gnome-panel     1 root      15   0   480  480   428 S     0,0  0,1   0:04 init     2 root      15   0     0    0     0 SW    0,0  0,0   0:00 keventd     3 root      15   0     0    0     0 SW    0,0  0,0   0:00 kapmd     4 root      34  19     0    0     0 SWN   0,0  0,0   0:00 ksoftirqd_CPU0 [...]

          Da she ich nicht von IO, und auch in der Hilfe steht nichts dazu.

          Schau Dir mal mit "top" die IOWAIT-Zeiten an - wenn die dramatisch hoch gehen, dann kommt Deine Festplatte nicht mit.

          s.o.

          Wäre das, was Du da tust, eine richtig teure kommer- zielle Anwendung, dann würde ich sagen: Hau 8 GB RAM in die Kiste rein und konfiguriere mySQL so, daß es den FULLTEXT-Index komplett im RAM halten kann ...

          Wenn ich denn mal wüßte welche Variable ich hierfür verstellen müßte, da gibt es so viele...

          Das hieße vermutlich am Ende eine Durchschnitts- Suchzeit von 5 oder mehr Sekunden! Das kann so doch nicht funktionieren!

          Richtig. Irgendwas an Deiner Konfiguration tut noch nicht.

          Ich denke, in Sachen SQL hast Du alles ausgereizt; jetzt geht es ans mySQL-Tuning und darum, die dann noch unvermeidlichen Festplattenzugriffe so schnell wie möglich zu machen.

          Ja, aber was können die  MySQL Parameter da  machen? Ich kann lediglich bestimmen wieviel im RAM steht, aber sonst?

          Was meinst Du wie ich das verändern kann? Die Zeit geht bei

          CREATE TEMPORARY TABLE temp_tabelle TYPE=HEAP

          Ich zweifele daran, daß HEAP eine gute Idee ist.

          wieso?

          MATCH (topic,title,name,body) AGAINST ('Andreas')

          Das ist bestimmt nicht gut.

          Das war auch nur ein Beispiel, ein Suchstring a la "+Andreas + Datenbank"

          MATCH (topic,title,name,body) AGAINST ('fsockopen()')

          Der zweite Suchbegriff ist um Größenordnungen besser!

          Ja, aber was der User eingibt kann ich ja schlecht wissen, vielleicht kann ich es umsortieren, sollte nicht allzulange dauern. Was mich aber am meisten stört, fsockopen würde ich nicht suchen können, da teilstring. Das ist das Größte Problem den ich muß ja Fulltext verwenden. Das wäre mir noch wichtiger als Phrasen.

          Ein normales "WHERE" für den "Andreas", selbst eines mit LIKE über die gesamte Story, hat Chancen, besser zu sein. Mach mal einen direkten Vergleich ...

          Weiß ich das voreher? Und ein LIKE über die Posting-Spalte dürfte sehr lange dauern!

          LIMIT 0, 1000

          Das wirkt zu spät.

          lustig! Wie soll ich das vorher begrenzen?

          Du berechnest zunächst einige tausend Treffer mit "Andreas", joinst ("AND") diese gegen ein paar Dutzend "fsockopen" (das ist teuer!) und erst danach begrenzt Du auf 1000 Stück, die Du aber nach dem JOIN bestimmt schon nicht mehr hast.

          Klar, aber das Scipt kann nunmal nicht so schlau sein wie Du ;-)

          Yep. Mach eine Statistik über alle Worte Deiner Daten- bank - und setze "Andreas" auf die Schwarze Liste. ;-)

          Das dumnme an der schwarzen liste, ich gebe "Andreas" ja nicht nru zum Spaß ein! Das soll ja auch Auswirkungen auf das Ergebnis haben!

          SELECT * FROM temp_tabelle ORDER BY time DESC LIMIT 0, 100 dagegen dauert es wie gesagt imme unter 0,001 Sekunden.

          Klar - da ist das Problem auch schon gelöst.

          Wo soll ich es sonst lösen?

          Was könnte man hier machen? Ich denke das ist das letze Problem,

          Aber auch eines der schwierigsten. Du bräuchtest eine Bewertungsfunktion, um gute WHERE- Klauseln zu berechnen, bevor Du sie ausführst. Eine Schwarze Liste wäre ein möglicher Weg dorthin.

          Mach mal einen Test (jeweils mit mySQL-Neustart vorher):

          Neustart von MYSQL reicht nicht, ich muß renooten und das ist mervig ;-)

          Ist die Dauer dieser Query abhängig von der Reihenfolge (!) der beiden Suchbegriffe?

          Ich meine nein, aber habe jetzt keinen Beweise da ich nicht neu booten will ;-)

          Mach mal einen zweiten Test: Definiere einen zusätz- lichen (!) FULLTEXT-Index über den Author und generie- re die WHERE-Klausel so, daß sie "Andreas" nur in diesem zweiten FULLTEXT sucht (was man in der alten Suche über die Eingabe "author:Andreas" ausdrücken kann). Ist das schneller? Ich denke, ja - weil dann nur noch der seltenere Begriff im großen FULLTEXT-Index gesucht werden muß.

          mache ich später, meinst Du das wäre besser als meine instr() Varianteß Wie gesagt kostet die so gut wie nicht!

          Du wirst immer noch irre viele Treffer dabei finden und JOINen müssen, aber es sind weniger als bisher.

          mit regexp arbeiten, das geht ja in mysql

          Versuche es - aber rechne damit, daß dasselbe passiert wie bei LIKE %...%: Es werden wahrscheinlich keinerlei Indexzugriffe mehr möglich sein.

          Ist ja auch egal, ich meine das jetzt für die temporäre Tabelle, daher wollte ich die etwas größer machen(max 1000), damit ich evtl hier so filtern kann, was sehr schnell ist, aber evtl einige Ergebnisse ausschließt.

          Grüße Abdreas

          1. Hi Andreas,

            speichern. Und das geht wirklich noch erheblich besser und schneller als ich gedacht hätte. Das wundert mich. Wieso? das Wesen einer HEAP-Tabelel ist es doch die Daten im RAM, zu speichern, das ist doch perfekt,

            es geht nicht darum, wo die Daten gespeicher werden, sondern wie. Das hast Du doch am Sortieren gemerkt: Sortieren im RAM ist furchtbar teuer, wenn die Datenmenge groß genug ist, weil das ein n*log(n)-Algorithmus ist.

            und in der Doku steht doch auch das es ganeu dazu gedacht ist, also nicht ganz, aber so ähnlich ;-)

            Eben. Das ist der Grund für mein "ja, aber".

            Dir ist klar das ich die Temporäre Tabelle mit den den Ergebnissen der Fulltext-Suche meine, in der bereits keine Postings mehr stehen? Das ist doch nichts an Speicherplatz, udn wenn dafür keien Plattenzugriffe notwendig sind(was nicht der Fall ist), dann ist es doch perfekt!

            Siehe oben: Auch sehr viele sehr kleine Daten brauchen zum Sortieren sehr viele sinnlose Vergleiche.

            Und so, wie ich den HEAP verstanden zu haben glaube, ist der Sinn der Sache, daß dabei implizit ein Index aufgebaut wird - genau das, was wir vermeiden wollen, weil dafür eine Sortierung notwendig ist. MYISAM im RAM muß für Deinen Zwecke besser sein als HEAP.

            Hab ich ja, egal was ich da drehem das sind ja alles nur obergrenzen die mir nicht be der ersten Suche helfen, sondern nur nachfolgende Suchen beschleu- nigen, da einfach mehr im Cache gehalten werden kann. ich habe wirklich alle Paramterr verdoppelt, teilweise ver-4-facht, brint alles nicht! Kein Stück!

            Du sollst auch nicht alle Parameter verdoppeln - das kostet RAM und macht die Sache langsamer. Du sollst den richtigen Parameter finden und ihn verzehnfachen.

            Völlig richtig: So wenige Spalten mitnehmen wie nötig. Lieber die SELECT-Felderliste dynamisch berechnen, als einfach "*" hinschreiben etc. Nltig ist im Prinzip nur ID und time, sollte ich die anderen Felder wie "autor" und "titel", dic ich ja später brauche aus der großen Tabelle joinen?

            Alles, was Du später brauchst, ist "nötig".

            Bedenke, daß der JOIN auch wieder implizit eine Sor- tierung braucht - wenn Du es schaffst, diesen JOIN nach der Limitierung zu machen, dann ist er nicht so teuer, ansonsten würde ich ihn zu vermeiden suchen.

            Da ich das Sortieren in meiner Anwendung mache, habe ich durch eine temporäre MYISAM-Tabelle keinerlei Nachteile gegenüber HEAP. Aber ich dachte, HEAP wird im RAM abgelegt, und MyISAM auf der Festplatte!

            Deshalb hatte ich in Dir in einem meiner vorherigen Postings den Link auf die mySQL-Doku gezeigt, wo steht, wo diese Daten auf der Festplatte gespeichert werden. Wenn Du diesen Pfad auf eine RAM-Disk legst, hast Du Deine MYISAM-Tabellen im RAM ... und brauchst kein HEAP mehr.

            selbst bei einer schnellen Platte sollte das schlechter sein. Ich habe die Statemnents nicht evrändert, udn mal HEAP gegen MyISAM ausgetauscht, dann wird es 50% langsamer(das abfragen der Tabelle), das Create kann ich schlecht messen.

            Du kannst alles messen. Liste Dir die einzelnen SQL-Statements auf (zerlege das, was Du bei CREATE TABLE AS SELECT ... in einem Schritt machst, wieder in zwei Schritte) und tippe sie über die mySQL- Kommandozeile nacheinander ein. Du bekommt dort eine Zeitmessung für jeden einzelnen Schritt.

            Die Tabelle wird ja auch nur einmal gebraucht, also wäre es totale Zeitverschwendung eine Index anzulegen, und sonst bietet mir MyISAM hier keine Vorteile, im Gegenteil wie gesagt.

            Gerade weil Du keinen Index brauchst, solltest Du MYISAM nehmen - und nicht HEAP.

            Das solltest Du unbedingt prüfen. Ja, aber das habe ich nicht geschafft zu prüfen.

            "top" hast Du aber? Normalerweise solltest Du eine IOWAIT-Anzeige im einstelligen Prozentbereich haben. Wenn die während einer Abfrage deutlich zweistellig wird, dann bremst Deine Platte das Systen.

            RAM-Disk zu finden ... jetzt haben wir dort eine. Daher dachte ich an HEAP! http://www.mysql.com/doc/en/Temporary_files.html

            "Ja, aber". Du schüttest das Kind mit dem Bade aus. MYISAM auf RAM-Disk ist RAM ohne HEAP-Struktur.

            Das versteh ich wie gesagt noch nicht richtig. Bei der Eingabe von "top" erhalte ich z.B.:

            CPU states: 19,9% user,  1,7% system,  0,0% nice, 78,2% idle

            Was ist denn das schon wieder für ein komisches "top"? Wo ist da die IOWAIT-Spalte? Genau die brauchst Du ...

            Da she ich nicht von IO, und auch in der Hilfe steht nichts dazu.

            Gnlpfts. Mein "top" zeigt mir mehr an. (http://www.sunmanagers.org/pipermail/sunmanagers/2001-November/008101.html)

            den FULLTEXT-Index komplett im RAM halten kann ... Wenn ich denn mal wüßte welche Variable ich hierfür verstellen müßte, da gibt es so viele...

            Ich habe gerade mal das mySQL-Handbuch überflogen ...

            Ich fürchte, Du wirst das gesamte Kapitel 5 einmal linear durchlesen müssen - nicht, um es komplett zu verstehen, sondern um zu lernen, welche Themen dort behandelt werden. Das ist ein Ideengeber ohne Ende.

            Konkreter Versuch - setz mal diesen Wert hier so hoch, wie nur irgend möglich bei Dir:

            "key_buffer_size" Index blocks are buffered and are shared by all threads. key_buffer_size is the size of the buffer used for index blocks. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford; 64M on a 256M machine that mainly runs MySQL is quite common. If you, however, make this too big (for instance more than 50% of your total memory) your system may start to page and become extremely slow. Remember that because MySQL does not cache data reads, you will have to leave some room for the OS filesystem cache. You can check the performance of the key buffer by doing show status and examine the variables Key_read_requests, Key_reads, Key_write_requests, and Key_writes. The Key_reads/Key_read_request ratio should normally be < 0.01. The Key_write/Key_write_requests is usually near 1 if you are using mostly updates/deletes but may be much smaller if you tend to do updates that affect many at the same time or if you are using DELAY_KEY_WRITE. See section 4.5.6 SHOW Syntax. To get even more speed when writing many rows at the same time, use LOCK TABLES. See section 6.7.2 LOCK TABLES/UNLOCK TABLES Syntax.

            Ja, aber was können die  MySQL Parameter da  machen? Ich kann lediglich bestimmen wieviel im RAM steht, aber sonst?

            Vieles. Beispiel (jetzt nicht für SELECT, aber für INSERT):

            "ft_max_word_len_for_sort" The maximum length of the word in a FULLTEXT index to be used in fast index recreation method in REPAIR, CREATE INDEX, or ALTER TABLE. Longer words are inserted the slow way. The rule of the thumb is as follows: with ft_max_word_len_for_sort increasing, MySQL will create bigger temporary files (thus slowing the process down, due to disk I/O), and will put fewer keys in one sort block (again, decreasing the efficiency). When ft_max_word_len_for_sort is too small, instead, MySQL will insert a lot of words into index the slow way, but short words will be inserted very quickly.

            Das ist also ein Wert, mit dem Du den FULLTEXT-Indexer auf Deine "Sprache" feintunen kannst.

            Ich zweifele daran, daß HEAP eine gute Idee ist. wieso?

            Weil Du die Fähigkeit eines HEAP, als Baum gespeichert zu werden, bezahlen mußt, aber nicht ausnutzt.

            MATCH (topic,title,name,body) AGAINST ('Andreas') Das ist bestimmt nicht gut. Das war auch nur ein Beispiel, ein Suchstring a la "+Andreas + Datenbank"

            Mein Einwand ist aber prinzipieller Natur: Deine konkreten WHERE-Klauseln könnten besser sein.

            MATCH (topic,title,name,body) AGAINST ('fsockopen()') Der zweite Suchbegriff ist um Größenordnungen besser! Ja, aber was der User eingibt kann ich ja schlecht wissen, vielleicht kann ich es umsortieren, sollte nicht allzulange dauern.

            Genau das meinte ich. Eine Funktion, die Dir zu jedem Suchbegriff dessen Häufigkeit berechnet, ist nicht schwer zu bauen; basierend auf dieser kannst Du dann "nutzlose" Terme herausnehmen, statt damit den Index- zugriff durchzuführen und in Treffern zu ertrinken.

            Was mich aber am meisten stört, fsockopen würde ich nicht suchen können, da teilstring.

            Das habe ich nicht verstanden.

            Ein normales "WHERE" für den "Andreas", selbst eines mit LIKE über die gesamte Story, hat Chancen, besser zu sein. Mach mal einen direkten Vergleich ... Weiß ich das voreher?

            Ja, das weißt Du vorher, wenn Du eine Tabelle mit den beiden Spalten "begriff" und "haeufigkeit" hast, über "begriff" ein PRIMARY KEY liegt und Du für jeden Begriff einen SELECT dort investierst.

            Die Tabelle muß gar nicht inkrementell gepflegt sein

            • die relative Häufigkeit der Suchbegriffe ändert sich nur langsam. Es reicht, wenn Du die einmal im Monat aufbaust. Und diese Tabelle sollte ein HEAP sein!

            Und ein LIKE über die Posting-Spalte dürfte sehr lange dauern!

            Nicht, wenn Du nur ganz wenige Postings zu prüfen hast. Der Unterschied zwischen den Suchbegriffen muß mindestens eine Zehnerpotenz ausmachen, schätze ich.

            LIMIT 0, 1000 Das wirkt zu spät. lustig! Wie soll ich das vorher begrenzen?

            Indem Du die einzelnen Schritte voneinander trennst.

            Klar, aber das Scipt kann nunmal nicht so schlau sein wie Du ;-)

            Doch. Das muß es sogar. Das ist der Trick an der Sache.

            Yep. Mach eine Statistik über alle Worte Deiner Datenbank - und setze "Andreas" auf die Schwarze Liste. ;-) Das dumnme an der schwarzen liste, ich gebe "Andreas" ja nicht nru zum Spaß ein! Das soll ja auch Auswirkungen auf das Ergebnis haben!

            Hat es auch - Du sollst ja "Andreas" nicht ignorieren, sondern diesen Begriff nur nicht mit MATCH abfragen, sondern ganz normal mit LIKE. Und am besten auch nicht im Posting-Body, sondern nur im Author - es liegt an Deinem Eingabeformular, dem Anwender zu erleichtern, Dir diese eingeschränkte Bedeutung zu sagen. Je mehr Informationen der Anwender in diesem Formular eingibt, desto bessere SELECT- Statements kannst Du daraus generieren.

            Mach mal einen Test (jeweils mit mySQL-Neustart vorher): Neustart von MYSQL reicht nicht, ich muß renooten und das ist mervig ;-)

            Das macht nichts. Es geht um das prinzipielle Verständnis. (Alternativ kannst Du auch das ganze mySQL-Handbuch lesen ...)

            Ist die Dauer dieser Query abhängig von der Reihenfolge (!) der beiden Suchbegriffe? Ich meine nein, aber habe jetzt keinen Beweise da ich nicht neu booten will ;-)

            Investiere einen Bootvorgang dafür. Das lohnt sich.

            mache ich später, meinst Du das wäre besser als meine instr() Varianteß Wie gesagt kostet die so gut wie nicht!

            Diese Aussage glaube ich nicht, solange sie unabhängig von der Treffermenge ist.

            Bei vielen Treffern kostet jede Operation etwas. Entscheidend ist, ob die Kostenfunktion linear oder überlinear mit der Anzahl der Treffer wächst - und in dieser Hinsicht ist Sortieren fast immer der worst case.

            Viele Grüße       Michael

            1. Hallo Michael!

              es geht nicht darum, _wo_ die Daten gespeicher werden,
              sondern _wie_.

              Naja, aber auch das _wo_ ist nicht ganz so unwichtig, denn Plattenzugriffen dauren doch erheblich länger als direkte RAM-Zugriffe! Aber das sind wieder 2 Dinge, Du redest glaibe ich vom schreiben der Tabelle, was vermiutlich langsamer ist als bei MyISAM, und ich rede vom auslesen, was kaum merklich schneller ist. Was jetzt am Ende das schnellste ist muß ich genau messen, aber jetzt verstehe ich. Ich hatte immer nur das Auslesen zum Vergleichen herangezogen.

              Siehe oben: Auch sehr viele sehr kleine Daten brauchen
              zum Sortieren sehr viele sinnlose Vergleiche.

              Bei MyISAM etwas nicht? Vermutlich ist das bei myISAM auch langsamer, so spricht nur das schnellere Schreiben für MyISAM.

              Und so, wie ich den HEAP verstanden zu haben glaube,
              ist der Sinn der Sache, daß dabei implizit ein Index
              aufgebaut wird - genau das, was wir vermeiden wollen,
              weil dafür eine Sortierung notwendig ist.

              Du wirst es wissen. Ich habe das so verstanden, dass das ein Hash ist(für mein Verständnis eine Art Array), der als Index benutzt werden kann/sollte. Man kan ja auch hier extra einen Index erzeugen, halt nicht besonderes wie Fulltext, und man kann auch nicht nach dem erzeugten Index sortieren. Aber warum sollte man- wenn HEAP selbst ein Index ist - einen Index über einen Index erstellen können?

              MYISAM im
              RAM muß für Deinen Zwecke besser sein als HEAP.

              Wie bekommt man myISAM in den RAM? Du sagts immer was von RAM-Disc, aber was ist das? Sowas habe ich nicht! Geht das auch anders?

              Du sollst auch nicht alle Parameter verdoppeln - das
              kostet RAM und macht die Sache langsamer.

              Ich habe ja auch nicht alles verdoppelt, nur das was mir vernünftig erschien, aber der RAM-Verbrauch steigt ja erst mit zunehmender Anzahl an SELECTS, sonst nicht! (da hatte ich noich kein HEAP)
              Das einzige an Tuning was ich hier für sinnvoll halte, ist den Anfragen-Cache(welche Variable auch immer das sein mag) so groß wie möglich zu halten, so dass die Anfragen nicht immer neu auf die Platte zugreifen müseen. Den Fulltext-Index selbst weiß ich auich nicht wei ich den in den RAm bekomme, der hat ja immerhin 60 MB, aber zu besten Testzeiten hat MySQL etwas über 30 MB Ram belegt.

              Du sollst
              den richtigen Parameter finden und ihn verzehnfachen.

              Aber wo steht welche Parameter was genau tut? Da steht eine Liste mit Beispielwerten, aber dei bringt mit nichts. Dann sind noch ein üar Beispiele für spezzielle Anforderungen aufgeführt, die ich aber nicht nachvollziehen kann, da am Ende für sehr viele Anfragen der Cache auf ein paar KB reduziert wird!

              Aber ich dachte, HEAP wird im RAM abgelegt, und
              MyISAM auf der Festplatte!

              Deshalb hatte ich in Dir in einem meiner vorherigen
              Postings den Link auf die mySQL-Doku gezeigt, wo
              steht, _wo_ diese Daten auf der Festplatte gespeichert
              werden. Wenn Du diesen Pfad auf eine RAM-Disk legst,
              hast Du Deine MYISAM-Tabellen im RAM ... und brauchst
              kein HEAP mehr.

              Und wie geht das? Kann ich einen Teil des RAMs "mounten" oder wie soll ich mir das Vorstellen, oder ist eine RAM-Disk ein Hardware-Teil?

              "top" hast Du aber?

              ja.

              Normalerweise solltest Du eine
              IOWAIT-Anzeige im einstelligen Prozentbereich haben.
              Wenn die während einer Abfrage deutlich zweistellig
              wird, dann bremst Deine Platte das Systen.

              Ich habe mal in der RH-Mailing-Liste angefragt, wie ich an den Wert komme.

              Gnlpfts. Mein "top" zeigt mir mehr an.
              (http://www.sunmanagers.org/pipermail/sunmanagers/2001-November/008101.html)

              schön ;-)

              Ich fürchte, Du wirst das gesamte Kapitel 5 einmal
              linear durchlesen müssen - nicht, um es komplett zu
              verstehen, sondern um zu lernen, welche Themen dort
              behandelt werden. Das ist ein Ideengeber ohne Ende.

              Ja, ich habe es jetzt 2 oder 3 mal komplett gelesen, wie gesagt vieles nicht verstanden, aber seh rinteresant. Aber das Kapitel mit den Server-Parametern finde ich etwas kurz, oder gibt es dazu irgendwie ein eigenes Kapitel, was die einzelnen Paramter genau machen?

              Konkreter Versuch - setz mal diesen Wert hier so hoch,
              wie nur irgend möglich bei Dir:

              "key_buffer_size"

              Habe ich auf 64 MB gesetzt, kein Unterschied. Aber kannst Du mir mal sagen wo Du die Erklärung her hast? Sowas suche ich schon die ganze Zeit und finde es nicht!

              Was mich aber am meisten stört, fsockopen würde ich
              nicht suchen können, da teilstring.

              Das habe ich nicht verstanden.

              Wenn im Posting spwa ssteht..

              <?
              fsockopen("bla.bla.de");...

              dann fidne ich dieses Posting weder Durch die Eingabe von "fsockopen()", noch durch "fsockopen", das ist sehr schlecht! Ich müßte auch teuilstrings finden könnewn, aber das kann zumindet 3.23 noch nicht, udn ohen Fuulltext hat das wohl kaum sinn, es sei denn ich durchsuche per %LIKE% nochmal die temporäre Tabelle, wobei ich in diesem Fall aber die Kompletten Postings reinschreiben müßte, was womöglich schnell an Grenzen stößt!

              LIMIT 0, 1000
              Das wirkt zu spät.
              lustig! Wie soll ich das vorher begrenzen?

              Indem Du die einzelnen Schritte voneinander trennst.

              Aber wie? Erstmal brauche ich doch eine Grundauswahl. Das Limit ist nur eien Sicherheit gegen ganz grobe Such-Begriffe.

              Klar, aber das Scipt kann nunmal nicht so schlau
              sein wie Du ;-)

              Doch. Das muß es sogar. Das ist der Trick an der Sache.

              Yep. Mach eine Statistik über alle Worte Deiner
              Datenbank - und setze "Andreas" auf die Schwarze
              Liste. ;-)
              Das dumnme an der schwarzen liste, ich gebe
              "Andreas" ja nicht nru zum Spaß ein! Das soll ja
              auch Auswirkungen auf das Ergebnis haben!

              Hat es auch - Du sollst ja "Andreas" nicht ignorieren,
              sondern diesen Begriff nur nicht mit MATCH abfragen,
              sondern ganz normal mit LIKE.
              Und am besten auch nicht im Posting-Body, sondern nur
              im Author - es liegt an Deinem Eingabeformular, dem
              Anwender zu erleichtern, Dir diese eingeschränkte
              Bedeutung zu sagen. Je mehr Informationen der Anwender
              in diesem Formular eingibt, desto bessere SELECT-
              Statements kannst Du daraus generieren.

              Ja, das mit den Namen hatte ich ja so gemacht. Sollt eich das denn dann erst hinterher machen, oder die Kategorie und den Namen direkt zum Filtern im ersten SELECT verwenden? Also Parallel zu den Match()Against(), oder am Ende in der Temporären Tabelle? Nach meinen MEssungen kostet eien zusätzliche WHERE Bedingung durchaus Zeit, aber dafür sortiere ich in der Temporären tabelle weniger, wobei das Abfragen der kleinen temp. Tabelle wirklich mit weniger als 1/1000 nicht ins Geewicht fällt, daher sollte ich wohl am Anfang nur mit Match erstmal den Fulltext-Indes allgemein abfragen, und in einem 2. Schritt den Rest.

              mache ich später, meinst Du das wäre besser als
              meine instr() Varianteß Wie gesagt kostet die so
              gut wie nicht!

              Diese Aussage glaube ich nicht, solange sie unabhängig
              von der Treffermenge ist.

              Bedenke das es sich nur um die Autoren-Spalte handelt, die ist ja recht kurz! Und es kostet durchaus was, halt ca. 1/10 Sekunde, je nachdem(über die Autor-Spalte der kompletten Ursprungstabelle). Vermutlich ist das nachträglich schneller.

              Bei vielen Treffern kostet _jede_ Operation etwas.
              Entscheidend ist, ob die Kostenfunktion linear oder
              überlinear mit der Anzahl der Treffer wächst - und in
              dieser Hinsicht ist Sortieren fast immer der worst case.

              Daher mache ich das so spät wie möglich!

              Grüße und vielen Dank nochmal,

              Andreas

              1. Hi Andreas,

                Aber das sind wieder 2 Dinge, Du redest glaibe ich
                vom schreiben der Tabelle, was vermiutlich langsamer
                ist als bei MyISAM, und ich rede vom auslesen, was
                kaum merklich schneller ist.

                Genau: Das Schreiben ist erheblich langsamer, wenn
                dabei eine sortierte Struktur aufgebaut werden muß.
                Das lohnt sich nicht, wenn nur _einmal_ auf diese
                Tabelle zugegriffen werden soll - wie auch ein CREATE
                INDEX für eine temporäre Tabelle sich meistens nicht
                lohnt.

                Siehe oben: Auch sehr viele sehr kleine Daten
                brauchen zum Sortieren sehr viele sinnlose
                Vergleiche.
                Bei MyISAM etwas nicht? Vermutlich ist das bei
                myISAM auch langsamer, so spricht nur das
                schnellere Schreiben für MyISAM.

                Dieses Argument bezog sich nicht auf den Tabellentyp,
                sondern auf die SELECT-Query und die Reihenfolge der
                Filteroperationen.

                Du wirst es wissen. Ich habe das so verstanden, dass
                das ein Hash ist(für mein Verständnis eine Art
                Array),

                Eben nicht. Ein Hash ist ein sortierter Baum, kein
                linearer Array (daß PHP beides als syntaktische Syno-
                nyme verwendet, verstellt Dir den Blick für die Imple-
                mentierung - in Perl sind es erkennbar unterschiedliche
                Konstrukte). Denn nur durch diese Sortierung ist es
                anschließend möglich, sehr schnell auf die einzelnen
                Elemente zuzugreifen - bei einem Array müßtest Du für
                das Heraussuchen eines bestimmten Elements ja einen
                full table scan machen.

                Ein CREATE TABLE vom Typ HEAP muß implizit ein CREATE
                INDEX bedingen, damit der HEAP wie ein Hash funktionie-
                ren kann. Und _das_ sind die Kosten, die Du vermeiden
                mußt, wenn Du nur ein einziges Mal auf dieses Tabelle
                zugreifen willst.

                Aber warum sollte man- wenn HEAP selbst ein Index
                ist - einen Index über einen Index erstellen können?

                Man kann für jede Tabelle beliebig viele Indexe er-
                stellen - und in vielen Fällen macht das auch Sinn.

                Es kann sinnvoll sein, für _jedes_ einzelne SELECT-
                Statement (gemeint sind Code-Varianten, nicht Aufrufe)
                einen eigenen Zugriffspfad zu bauen, wenn sich die
                SELECT-Statements hinreichend stark von einander
                unterscheiden.

                Ein Beispiel dazu hatte ich ja schon angeführt: Ein
                separater FULLTEXT-Index über die Author-Spalte, der
                sehr viel schneller durchsuchbar wäre als der FULLTEXT
                über die Postings selbst.
                Dieser Index wäre ein optimaler Zugriffspfad für ein
                Statement der Art
                    SELECT * FROM postings WHERE author = MATCH (...)
                _ohne_ weitere WHERE-Klauseln.
                Sobald auch nur _eine_ weitere WHERE-Klausel hinzu
                kommt, die einen 'besseren' Index braucht (z. B. "AND
                posting_body = MATCH (...)"), ist der neue Index wert-
                los, weil pro SQL-Statement nur _ein_ Index verwendet
                werden kann - und zwar der beste. Das kann aber bei
                verschiedenen SELECT-Statements jeweils ein anderer
                sein.
                Deshalb können sogar mehrere FULLTEXT-Indexe auf
                derselben Tabelle Sinn machen - je nachdem, welche
                SELECT-Statements Du abfeuerst.

                Ich verwende den Namen "Zugriffspfad" absichtlich,
                weil er die Denkweise beschreibt:
                 1. Definition der Spalten (Semantik der Daten)
                 2. Definition der Queries (Semantik der Auswertung)
                 3. Definition der Indexe  (Tuning der Queries)
                Zu jeder möglichen Variante Deines SELECT-Codes -
                ausgenommen solche Queries, die sich nur durch Host-
                Variablenwerte (oder solche, die eigentlich Host-Va-
                riablen sein sollten, was mySQL aber wohl nicht kann)
                unterscheiden, wird intern ein unterschiedlicher 3GL-
                Code generiert werden, den Du wieder mit EXPLAIN prü-
                fen und bei Nicht-Gefallen durch weitere Indexe auf
                einen schnelleren Zugriffspfad umleiten solltest.

                Es kann übrigens _noch_ krasser sein: Wenn der Query-
                Optimizer intern kostenbasiert arbeitet und nicht
                regelbasiert, dann kann er sogar für dasselbe SELECT-
                Statement zu verschiedenen Zeiten unterschiedlichen
                internen Code generieren, also unterschiedliche Zu-
                griffspfade verwenden.
                Stell Dir vor, FULLTEXT würde intern eine Schwarze
                Liste der Worte führen und selbst _erkennen_, daß
                "HTML" zu viele Treffer verursacht! Dann würde ein
                MATCH gegen HTML einen _anderen_ Code generieren als
                ein MATCH gegen "fsockopen" ... bei Oracle kann man in
                der Konfiguration wählen, welche Strategie der Query-
                Optimizer verwenden soll, und über spezielle SQL-
                Erweiterungen dies sogar innerhalb jedes einzelnen
                SQL-Statements verlangen ...
                Ja, SQL _ist_ eine Wissen-schaft für sich. Eigentlich
                will man mit einer 4GL den Programmierern verbergen,
                wie ein Statement intern realisiert wird; um so schwie-
                riger ist es dann leider, dies doch heraus zu bekommen,
                um den schnellsten Zugriffspfad zu verwenden (oder um
                zu entdecken, daß gar kein wirklich schneller Pfad
                existiert, weil kein passender Index definiert wurde).
                EXPLAIN ist von unschätzbarer Bedeutung, um Queries
                wirklich schnell zu bekommen.

                Tuning einer SQL-Anwendung ist ein bißchen ähnlich wie
                das Schaffen mehrerer alternativer Navigationen auf
                einer Webseite: Der eine Anwender erwartet eine Link-
                Leite überall links, der andere möchte eine Sitemap
                benutzen, der dritte glaubt an die Macht der Such-
                maschinen ... so, wie sich diese Besucher unterschei-
                den, unterscheiden sich auch Deine SELECT Statements
                in ihrem Charakter.

                Du sagts immer was von RAM-Disc, aber was ist das?

                In UNIX gibt es keinen prinzipiellen Unterschied zwi-
                schen Geräten und Dateien - alles liegt irgendwo im
                Verzeichnisbaum. (Die Geräte liegen unter /dev.)

                Eine RAM-Disk ist ein Gerätetreiber, der einen Puffer
                im RAM in den Verzeichnisbaum einblendet. Du kannst
                mit dem entsprechenden Verzeichnisbaum-Teil arbeiten
                wie mit einer Festplatte, Dateien per "fopen()" öffnen
                usw. - all diese Systemaufrufe werden aber von diesem
                Treiber abgefangen und in seine eigenen Funktionen um-
                gesetzt - wie dieser Treiber beispielsweise Seiten ein-
                und auslagert, ist seine Sache, und wie die Größe sei-
                nes RAM-Bereichs konfiguriert wird, das ist Sache der
                Installation dieses Treibers.

                Eine RAM-Disk ist aber nichts, was es nur unter UNIX
                gäbe. Auch in Windows gibt es irgendwo im System-Kern
                eine Adresse des Treibers für die Zugriffe auf ein
                Festplattenlaufwerk. Wenn man dort an der richtigen
                Stelle die Adresse durch diejenige eines residenten
                eigenen Treibers ersetzt, kann man die Festplatte auch
                "simulieren" - ohne daß eine Anwendung das merkt.

                Sowas habe ich nicht! Geht das auch anders?

                Du hast bestimmt einen RAM-Disk-Treiber in Deiner
                UNIX-Kiste - im Zweifelsfalle kannst Du Dir einen aus
                dem WWW fischen.
                (Lesetip: http://www.linuxfocus.org/English/November1999/article124.html)

                Und nein, es geht nicht anders, weil Du wahrscheinlich
                nicht mySQL sagen kannst, es soll nur ganz bestimmte
                Arten von Tabellen komplett im RAM halten und andere
                nicht. Aber Du kannst sehr wohl bestimmte Verzeichnisse
                (oder gar nur bestimmte Dateien!) Deines Pfad-Baums in
                die RAM-Disk legen (via symbolic links - das wird im
                mySQL-Handbuch explizit ermutigt) - mySQL wird gar
                nicht merken, daß es mit einer RAM-Disk zu tun hat,
                aber die Zugriffe werden entsprechend schneller.

                Das einzige an Tuning was ich hier für sinnvoll
                halte, ist den Anfragen-Cache(welche Variable auch
                immer das sein mag) so groß wie möglich zu halten,
                so dass die Anfragen nicht immer neu auf die Platte
                zugreifen müseen.

                Der Query-Cache bewirkt nicht, daß die Anfragen nicht
                neu ausgeführt werden - er bewirkt nur, daß sie nicht
                neu in mySQL-internen Code _übersetzt_ werden müssen.

                Wenn Du verhindern willst, daß auf die Platte zuge-
                griffen wird, dann mußt Du das in den RAM legen, worauf
                zugegriffen wird - und das ist der FULLTEXT-Indexbaum.

                Den Fulltext-Index selbst weiß ich auich nicht wei
                ich den in den RAm bekomme, der hat ja immerhin 60
                MB, aber zu besten Testzeiten hat MySQL etwas über
                30 MB Ram belegt.

                Suche nach dem Konfigurationsparameter für den Puffer,
                der die Indexbäume aufnimmt. Dort müßten auch die
                Sektoren des FULLTEXT-Index drin liegen.

                Wahrscheinlich wird mySQL nie komplette Indexe im RAM
                halten - aber je größer dieser Teil-Puffer ist, um so
                besser ist die Cache-Hit-Rate und um so weniger
                Festplattenzugriffe wirst Du brauchen.

                Aber wo steht welche Parameter was genau tut?

                Im mySQL-Benutzerhandbuch.

                In meinem vorherigen Posting habe ich Abschnitte daraus
                zitiert - Google wird Dir den URL dazu zeigen.

                ... mein Posting wird zu lang, ich schneide hier mal ...

                Viele Grüße
                      Michael

                1. Hi Michael!

                  Leider kann ich jetzt nicht hierauf antworten, da ich Mittwoch eine wichtige Prüfung habe und noch einiges lernen mußt. Ich vermute dass sich der Thread nicht bis Mittwoch Nachmittag halten wird, daher werde ich ggfs. einen neuen eröffnen. Ich habe die Postings beide mit großerm Interesse gelesen, und ich habe wieder ein Stückchen mehr verstanden, ich danke Dir sehr für diese unbezahlbaren "Nachhilfestunden"! Ich habe dank Dir die letzten Tage wirklich sehr viel gelernt.
                  Aber gerade dieser Thread führt mir nochmal sehr deutlich vor Augen, dass es eine Schande ist ein derartiges Wissen mit der Zeit im Archiv versauern zu lassen!
                  Es bestärkt mich darin, nach einer performanten Suche erstens einen sinnvollen "Relevanz Algorythmus" zu entwickeln, und 2., mit dessen Hilfe auch eine sinnvolle Navigation durch das Archiv zu entwickeln, mit weiteren Unterkategorien, so wie ich es mal mit FAQ anregen wollte.
                  Wenn man die Suche noch mit dem Login-Mechanismus des Forums kombiniert, ergeben sich ja noch einige wirklich interessante Möglichkeiten. Ich wäre auch immer noch dafür, im Forum eine erweiterete "Fürs-Archiv vorschlagen"-Möglichkeit zu schaffen, denn kombiniert mit der Information über den "REMOTE USER"(statistisch berechnete Erfahrung...), würde die Qualität eines Rankings sehr gewinnen!

                  Ach ja: http://www.surriel.com/procps/NEWS

                  ich habe:   [root@localhost root]# top -V
                              top (procps version 2.0.7)

                  Ich weiß auch nicht, scheint aber aktuell zu sein, vielleicht sollte ich mir die aktuelle Version holen, aber k.A. wie das geht... mal schaun!

                  Viele Grüße
                  Andreas

              2. Hi Andreas,

                ... weiter im Text:

                Und wie geht das? Kann ich einen Teil des RAMs
                "mounten" oder wie soll ich mir das Vorstellen,

                Ja, so ungefähr. Wie genau eine RAM-Disk installiert
                wird, das wirst Du in ihrer Beschreibung lesen. Es
                wird aber immer so ähnlich funktionieren wie "mount",
                auch wenn es nicht dieses Kommando selbst verwendet.

                Auch "mount" blendet ja ein über einen Treiber be-
                triebenes Gerät in den Verzeichnisbaum ein - wobei
                Du als Anwendungsprogramm nicht zwischen einem Fest-
                platten- und einem NFS-mount unterscheiden kannst.

                Ja, ich habe es jetzt 2 oder 3 mal komplett gelesen,
                wie gesagt vieles nicht verstanden, aber sehr
                interesant. Aber das Kapitel mit den Server-
                Parametern finde ich etwas kurz, oder gibt es dazu
                irgendwie ein eigenes Kapitel, was die einzelnen
                Paramter genau machen?

                Ich fand die Beschreibung mit den Parametern auch kurz.

                Aber kannst Du mir mal sagen wo Du die Erklärung
                her hast? Sowas suche ich schon die ganze Zeit
                und finde es nicht!

                http://www.mysql.com/doc/en/SHOW_VARIABLES.html
                Da kann man sogar selbst Kommentare abgeben - habe ich
                teilweise auch gemacht.

                Was mich aber am meisten stört, fsockopen
                würde ich nicht suchen können, da teilstring.
                Das habe ich nicht verstanden.
                Wenn im Posting spwa ssteht..
                <?
                fsockopen("bla.bla.de");...
                dann fidne ich dieses Posting weder Durch die
                Eingabe von "fsockopen()"
                noch durch "fsockopen"

                In _beiden_ Fällen solltest Du es finden.

                Der Punkt ist: mySQL-FULLTEXT hat eine eigene Vorstel-
                lung davon, was ein "Wort" ist. Im mySQL-Quelltext gibt
                es eine Beschreibung, welche Zeichen legale "wordchars"
                sind - und "(" ist keiner!

                Deshalb wird in Deinem Beispiel durchaus "fsockopen"
                als Wort im FULLTEXT-Index gespeichert werden - und
                sogar bei Deiner Eingabe von "fsockopen()" sollte es
                gefunden werden, weil der FULLTEXT-Treiber auch bei
                der Ausführung von MATCH erst mal Deinen Suchbegriff
                analysiert (deshalb funktioniert ja eine Eingabe von
                mehreren Begriffen mit Leerzeichen getrennt).

                Diese wordchars kannst Du selbst auch ändern - genau
                wie die Mindestlänge eines FULLTEXT-Eintrags. Das ist
                ein C-Makro in einer der Dateien des MYISAM-Tabellen-
                treibers - das findest Du im mySQL-Quelltextverzeich-
                nis "src/myisam".
                Der voreingestellte Wert ist allerdings m. E. sinnvoll

                • ich selbst habe dort nichts ändern müssen.

                das ist sehr schlecht! Ich müßte auch teuilstrings
                finden könnewn, aber das kann zumindet 3.23 noch
                nicht

                Versuche, das "wordchars"-Konzept zu verstehen. Es
                ist im ersten Moment verwirrend - aber es lohnt sich.

                und ohne Fulltext hat das wohl kaum sinn, es sei
                denn ich durchsuche per %LIKE% nochmal die temporäre
                Tabelle, wobei ich in diesem Fall aber die
                Kompletten Postings reinschreiben müßte, was
                womöglich schnell an Grenzen stößt!

                So macht es in der Tat keinen Sinn.
                Da müßtest Du schon eher die FULLTEXT-Funktionalität
                selbst nochmal implementieren, also einen Wort-Zerleger
                schreiben und eine Tabelle bauen, die nur aus zwei
                Spalten besteht, dem Wort und der Posting-ID, und über
                dem Wort einen non-unique Index definieren ...
                (Ich habe das für eine andere Anwendung mal so reali-
                siert, mit einer Tabelle mit 20 Millionen Einträgen -
                damit habe ich eine Suche, die eigentlich LIKE %...%
                ist, über Indexverwendung irre schnell bekommen: Jeder
                Postfix ist bei mir ein Tabelleneintrag ... denn LIKE
                ...% arbeitet _mit_ Index ...)

                Zurück zu FULLTEXT: Definiere, was Du als Bestandteil
                eines Wortes, also eines Suchbegriffs zu akzeptieren
                bereit bist, und passe ggf. die wordchar-Definition an.

                Um dann allerdings "fsockopen()" zu finden und an
                Stellen, wo "fsockopen" ohne "()" steht, _keinen_
                Treffer zu erzielen, müßtest Du
                1. in Deinem PHP-Skript begreifen, daß "fsockopen()"
                   kein "word" ist und
                2. deshalb _nach_ dem erfolgreichen FULLTEXT-Zugriff
                   in einem weiteren Filterschritt ein
                        "LIKE %fsockopen()%"
                   dahinter schalten.
                Letzteres ist der schon mehrfach angesprochene Phra-
                senfilter: Suche zunächst nach allen Worten über den
                FULLTEXT-Index und prüfe anschließend die (hoffentlich
                schon sehr wenigen) Treffer daraufhin, ob es wirklich
                "echte" Treffer waren. Das LIKE ist teuer - deshalb
                muß vorher die Trefferzahl schon sehr klein sein ...
                ein Phrasenfilter nach "HTML " kann nicht schnell
                werden.

                LIMIT 0, 1000
                Das wirkt zu spät.
                lustig! Wie soll ich das vorher begrenzen?
                Indem Du die einzelnen Schritte voneinander
                trennst.
                Aber wie? Erstmal brauche ich doch eine Grund-
                auswahl. Das Limit ist nur eien Sicherheit gegen
                ganz grobe Such-Begriffe.

                Aber "Andreas" ist in diesem Fall _zu_ grob.

                Wenn Du zuerst nur nach "fsockopen" suchst, bekommst
                Du eine bereits kleine Treffermenge; an dieser Stelle
                kannst Du allerdings ein "pathologisches" Trefferlimit
                von vielleicht 3000 setzen, damit Du nicht in Treffern
                ertrinkst. (Dessen Erreichen reduziert wieder die
                Qualität der Treffer, aber das merkst Du und kannst
                es in der HTML-Ausgabe anzeigen.)

                Danach kommt dann erst der Vergleich mit "Andreas",
                der _nicht_ über den FULLTEXT-Index geht - erneut mit
                einem LIMIT versehen, diesmal mit demjenigen, das für
                die spätere Ausgabe gelten soll.
                In diesem Falle hast Du die Query in zwei SELECTs
                zerlegt und das Ergebnis in einer temporären Tabelle
                gepuffert, um zwischen den beiden Bedingungen ein
                LIMIT feuern zu lassen.
                Im vorliegenden Fall war das wahrscheinlich nicht
                mehr notwendig - da hätte es gereicht, nut "fsockopen"
                über den FULLTEXT zu suchen, weil der Vergleich mit
                "Andreas" aufgrund des verwendeten Zugriffspfades
                nachgeschaltet ist, also nur auf die Treffer des
                FULLTEXT-MATCH angewendet wird.
                Auch die unterschiedliche Auswertung der beiden WHERE-
                Terme ist aber schon eine solche Serialisierung - wenn
                Du beide Terme über MATCH suchst, dann sind sie
                gleichrangig, und mySQL muß für die geballte Ladung
                Treffer den FULLTEXT-Index bemühen - und JOINen, also
                sortieren.

                Bedeutung zu sagen. Je mehr Informationen der Anwender
                in diesem Formular eingibt, desto bessere SELECT-
                Statements kannst Du daraus generieren.
                Ja, das mit den Namen hatte ich ja so gemacht.
                Sollt eich das denn dann erst hinterher machen,
                oder die Kategorie und den Namen direkt zum Filtern
                im ersten SELECT verwenden?

                Das Problem ist, daß ich die Funktionalität der ge-
                samten Suche nicht überblicke. Wird es jemals eine
                Möglichkeit geben, alle Postings eines Autoren ohne
                Angabe eines Inhaltsmusters anzufordern? Dies würde
                eine andere Indexarchitektur erfordern.

                Ich ignoriere diese Möglichkeit mal und beschränke
                mich auf das, was bisher geht:

                Also Parallel zu den Match()Against(),

                Ja.

                Nach meinen MEssungen kostet eien zusätzliche WHERE
                Bedingung durchaus Zeit, aber dafür sortiere ich in
                der Temporären tabelle weniger, wobei das Abfragen
                der kleinen temp. Tabelle wirklich mit weniger als
                1/1000 nicht ins Geewicht fällt, daher sollte ich
                wohl am Anfang nur mit Match erstmal den Fulltext-
                Indes allgemein abfragen, und in einem 2. Schritt
                den Rest.

                Das WHERE muß irgendwann einmal gemacht werden, und
                Du wirst nie einen Indexzugriff dabei durchführen
                können - egal, ob Du es schon direkt nach dem MATCH
                oder in einer späteren Filterstufe erledigst.
                Daraus folgt: Mach es so früh wie möglich.

                In der temporären Tabelle sortiert Du Zeilen, nicht
                Spalten. Wie breit diese Zeilen sind, das ist für
                die Sortierung irrelevant (weil mySQL sicherlich nur
                Pointer auf diese Zeilen neu verketten wird).
                Die Breite der Sortierspalte selbst ist allerdings
                wichtig (weil der Vergleich langer Werte teurer ist
                als der Vergleich kurzer Werte - deshalb gefällt mir
                die Datums-Codierung als UNIX time stamp so gut).

                Bedenke das es sich nur um die Autoren-Spalte
                handelt, die ist ja recht kurz!

                Ja - aber wenn Du mehrere hunderttausend INSTR-Opera-
                tionen durchführen mußt, weil der vorherige FULLTEXT-
                Zugriff nichts oder nur ganz wenig gefiltert hat
                ("HTML" ;-), dann ist das trotzdem teuer. (Wahrschein-
                lich wird es identisch zu LIKE %...% realisiert ...)

                Viele Grüße
                      Michael