Stephan K.: Normalisierung vs. Performance

Hallo allerseits,

bei uns der Arbeit soll ein neues Datenbanksystem entwickelt werden.
(Redaktionssystem einer Website für Börseninformationen)

Benutzt wird auf alle Fälle MySQL. (armer dotcom, keine kohle für oracle ...)

Dabei stellen sich mir einige Fragen bzgl. Datenbank-Design:

Macht es Sinn, eine Datenbank bis in die letzten Details zu normalisieren?
Dadurch steigt doch gleichzeitig die Anzahl der beteiligten Tabellen beim SELECT,
was für die Performance wohl eher schlecht ist.

Einsatz von char- oder varchar-Feldern:
Benutze man nur char-Felder, erreicht man eine feste Satzlänge.
Kann das Vorteile beim Durchsuchen bringen?

Was kann z.B. bei INTEGER-Felder die genaue Abschätzung der möglichen Werte bringen (--> Grösse der Spalte)?
Bei über 100 int-Feldern kann das ziemlich nervig sein, aber wenn es der Performance dient ...

Was kann man generell für böse Fouls begehen?

Ich hoffe nicht unbedingt auf Antworten (wäre natürlich super),
eher bin auf der Suche nach guten Informationsquellen.
Aber nicht in der Form "Wie erstelle ich ein ERM" oder "Datenbank-Normalisierung" !!
Die Theorie hab ich (hoffentlich) schon verstanden, aber die Praxis und Erfahrung
für so ein Projekt kann gerne noch verbessert werden !

Vielen Dank für alle Hinweise

Stephan, <nerv>der heute den ganzen Tag einer Blaskapelle in Büronähe lauschen durfte</nerv>

  1. eher bin auf der Suche nach guten Informationsquellen.

    Unter http://www.php-kongress.de/2000/zusammenfassung.php#pres findest du einen Beitrag zum Thema 'Schnelle Suchmaschine mit PHP & MySQL' wo zB. erklärt wird, wie man durch eine temporäre Tabelle einen Join über 3 Tabellen umgeht und warum/ab wann dies sinnvoll ist.

    Ist vielleicht nicht genau, was du gesucht hast, aber tiefergehnde Quellen kenn ich leider auch nicht. Wenn es welche gibt: immer her damit :o)

    Andererseits verstehe ich nicht, warum du denkst, Oracle sei schneller als MySQL. Im Grunde ist MySQL eine abgespeckte relationale Datenbank die speziell für große Datenbanken und schnelle Suchen entwickelt wurde. Der Nachteil von MySQL liegt eher im Funktionsumfang: kein Rollback, keine foreign Keys usw.

  2. Hallo Stephan,

    Dabei stellen sich mir einige Fragen bzgl. Datenbank-Design:

    ich versuchs mal kurz zu fassen, was leider nicht leicht ist. Denn was du fragst, ist eigentlich der Stoff ganztaegiger Schulungen und in den Details von DBMS zu DBMS verschieden. Zu den Interna von MySQL kann ich nicht viel sagen, da ich selbst noch nicht damit gearbeitet habe. Allen relationalen Datenbanksystemen sind jedoch einige Dinge gemeinsam. Und darauf versuche ich mal einzugehen:

    Macht es Sinn, eine Datenbank bis in die letzten Details zu normalisieren?

    Es kommt darauf an ;-)

    Dadurch steigt doch gleichzeitig die Anzahl der beteiligten Tabellen beim SELECT,
    was für die Performance wohl eher schlecht ist.

    Richtig. Kleine Tabellen, die ohnehin nicht mehr als ein oder zwei DB-Pages umfassen, zu normalisieren oder auch indizieren, macht keinen Sinn, da das DBMS in jedem Fall mindestens eine Page laden muß.
    Eine Page ist in der Regel ein Block in der vom Filesystem vorgegebenen Groesse. Es gibt zwar auch Mechanismen, mit Subpages zu arbeiten, aber grundsaetzlich gilt: Datenbanken sind letztlich auch Dateien auf der Festplatte und werden Daten aus der Datenbank geladen, so muss immer wenigstens ein Block von der Festplatte in den Arbeitsspeicher geladen werden. Auf grossen Festplatten kann ein solcher Block locker mal 32 Kb umfassen.
    Ist eine Tabelle so klein, dass sie vollkommen in eine Page passt, dann wird also beim Zugriff auf die Tabelle durch einlesen einer Page die gesamte Tabelle in den Speicher geladen. Wuerde man eine solche Tabelle indizieren, dann muesste fuer den Index eine weiteres Page angelegt werden. Da DBMS i.A. Daten und Indices getrennt halten (ich kenne keine Ausnahme), wuerde eine solch kleine Tabelle mit dem Index nichts gewinnen. Alle Eintraege im Index zeigen wieder auf die gleiche Datenpage. Deshalb ignoriert ein gutes DBMS bei kleinen Tabellen den Index vollkommen, wenn die Daten nicht wenigstens mehrere Pages umfassen. Wozu auch extra im Index nachsehen, wenn am Ende doch stets die gleich Datenpage geladen wuerde.
    Nehmen wir nun an, diese schon recht kleine Tabelle ist nicht normalisiert und wir wuerden sie normalisieren, dann entstehen aus dieser einen Tabelle mehrere noch kleinere. Es ist nicht garantiert, dass diese in der gleichen Page liegen. Abgesehen vom Verwaltungsaufwand des Joinens waere das DBMS auf einmal gezwungen, auch noch mehrere Pages von Platte einzulesen.

    Darum gilt im Allgemeinen: Je kleiner die Tabelle, desto weniger Sinn macht eine Normalisierung.

    Der Umkehrschluss gilt jedoch nicht automatisch, dass grosse Tabellen auf jeden Fall normalisiert werden sollten.

    Vor jedem groesseren Datenbankdesign sollte man sich ueberlegen, welche Daten in welchen Prozessen verarbeitet werden. Wird Wert auf eine leichte Pflege gelegt oder Wert auf Performance? Wie lauten die wichtigsten SQL-Statements? Wie sehen die Arbeitsablaeufe aus? Haeufige Abfrage und wenig "Bewegung" in den Daten selbst? Oder permanante Datenaenderungen? usw.
    All diese Fragen spielen eine Rolle beim Datenbankdesign. Erst wenn der Anforderungskatalog mit Prioritaetenliste steht und eine vollstaendige (!) Beschreibung der Daten vorhanden ist, sollte das eigentliche DB-Design beginnen.
    In der Praxis sieht es oft anders aus, was dann schnell zu Beschwerden ueber lahme DB-Server fuehrt und tatsaechlich fast immer am unpassenden Design liegt.

    Einsatz von char- oder varchar-Feldern:
    Benutze man nur char-Felder, erreicht man eine feste Satzlänge.
    Kann das Vorteile beim Durchsuchen bringen?

    Ja, kann es eindeutig.
    Varchar bedeutet, dass im Datendatz nur soviel Platz reserviert wird, wie auch tatsaechlich Daten gespeichert werden. Dies kann in jedem Satz anders aussehen. Woher aber weiss das DBMS, wieviele Bytes eine Spalte gerade in diesem Satz enthaelt? Diese Laengeninformation muss also zusaetzlich gespeichert werden und wird in der Regel direkt im Row mitgespeichert.

    Ein typischer Row besteht immer aus einem Header und den aneinandergereihten Spalten. Bei Spalten mit fester Laenge muss wieder unterschieden werden, ob eine Spalte nullable ist oder mit der Option NOT NULL definiert wurde. Darf eine Spalte fester Laenge nicht NULL sein, ist alles klar, es muss nur der Inhalt der Spalte gespeichert werden. Ist eine Spalte nullable, muss zusaetzlich zu den Daten die Information abgelegt werden, ob die Spalte in diesem Row NULL ist. D.h. nullable Spalten enthalten zusetzlich zu dem fuer die Daten reservierten Platz noch ein oft 1 Byte grosses Feld, das Auskunft ueber die NULL-Eigenschaft gibt. Ist eine Spalte fester Laenge NULL, liegt der fest fuer die Daten reservierte Platz ungenutzt brach.
    Bei Spalten variabler Laenge ist dies nicht der Fall. Ist eine Varcharspalte nullable, muss auch hier wieder die NULL-Eigenschaft separat zu den Daten abgelegt werden. Im Falle von NULL wird jedoch kein weiterer Platz benoetigt. Ist die Spalte in diesem Row aber nicht NULL, muss noch festgehalten werden, wie lang die Daten denn nun wirklich sind. Es wird also noch eine Laengeninformation benoetigt (und meist unabhaengig von der NULL-Eigenschaft in jedem Fall abgelegt).
    Richtig interessant wird all dies aber erst, wenn man sich nun die Reihenfolge der Spalten ansieht. Dazu ein kleines Beispel:

    Tabelle A bestehe aus den Spalten
    Col1   Integer
    Col2   Varchar(50)
    Col3   Char(7)     NOT NULL

    Dies ist eine typische Tabelle, wie sie gerne angelegt wird, und bereits einen Kardinalsfehler enthaelt. Ein Row dieser Tabelle wuerde etwa folgendermassen aussehen:

    |Header|nullinfo1,daten1|nullinfo2,laenge2,daten2|daten3|

    Am Anfang jedes Rows befindet sich ein Header. Die ist eine DB-interne Information und hier nicht weiter interessant. Wenn nun Col1 ermittelt werden soll, wird zunaechst die nullinfo1 ausglesen. Ist die Splate NULL, wird NULL als Wert ausgegeben. Ist nullinfo1 nicht NULL, wird daten1 ausgelesen. Bei Col2 verhaelt es sich genauso, nur dass hier beim Zugriff auf daten2 (falls noetig) noch laenge2 beruecksichtigt wird. Ganz anders aber sieht es beim Zugriff auf Col3 aus. Woher weiss das DBMS an welcher Position im Row Col3 beginnt? Col3 hat keine feste Startposition im Row, da zuvor ein Feld variabler Laenge gespeichert ist. D.h., um Col3 ermitteln zu koennen, muss zunaechst die Laenge von Col2 bestimmt werden, um herauszufinden, wo die Daten von Col3 ueberhaupt beginnen. Oder anders gesagt, die Postion aller nach der ersten variablen Spalte liegenden weiteren Tabellenspalten muss zunaecht berechnet werden. Je weiter hinten im Row sich die gewuenschte Spalte befindet und je mehr Varcharspalten davor liegen, desto mehr Aufwand entsteht.

    Daher gilt: Spalten fester Länge an den Anfang, Varchar-Spalten ans Ende der Tabelle.
    Haeufiger benoetigte Spalten nach vorne, selten benoetigte Spalten ans Ende.

    Was kann z.B. bei INTEGER-Felder die genaue Abschätzung der möglichen Werte bringen (--> Grösse der Spalte)?
    Bei über 100 int-Feldern kann das ziemlich nervig sein, aber wenn es der Performance dient ...

    Je genauer die noetige Laenge der Felder abgeschaetzt wird, desto weniger Platz wird unnoetig verschwendet und desto mehr Rows einer Tabelle passen in eine Page. Bei der Abfrage jeweils nur eines einzigen Satzes aus einer Tabelle ist dies irrelavent. Werden aber grosse Bereich der Tabele abgefragt, dann sind kuerzere Saetze in sofern interessant, dass das DBMS weniger Pages einlesen muss.

    Was kann man generell für böse Fouls begehen?

    Uff, da gibt es viele Moeglichkeiten. Vielleicht ein paar klassische Beispiele:

    Eine Tabelle enthaelt 12 Monatswerte je Satz. Aenderungen erfolgen einmal pro Monat, wenn der aktuelle Monat upgedatet wird. Abgefragt wird die Datenbank haeufig, jedoch immer nur einzelne Monate. Die Performance der Datenbank laesst sich durch simples Kippen und umsortieren drastisch erhoehen. Kippen meint: je Satz werden nicht alle 12 Monate gespeichert, sondern nur die Monatsnummer und der jeweilige Wert. Dadurch werden zunaechst zusaetzliche Informationen eingefuegt, die die Tabelle scheinbar aufblaehen,. Tatsaechlich werden wesentlich kuerzere Saetze erreicht, wodurch wieder mit einer Page mehr Saetze auf einmal eingelesen werden koennen. Mit Umsortieren ist gemeint, dass die Speicherung der Daten innerhalb der Tabelle nach Monaten sortiert erfolgen soll. (Am Besten in der Doku nachsehen, wie sich die Sortierung beeinflussen laesst. Dies muss nicht immer der Primaerindex sein.) Somit liegen jeweils die Daten eines Monats beieinander und nicht, wie zuvor ueber die gesammte Datenbank verstreut. Zuvor war praktisch ein Tablescann erforderlich um die Daten eines Monats komplett zu ermitteln, nun reicht das Einlesen eines bestimmten Pagebereiches aus. Beherrscht nun das DBMS auch noch Clustering, kann der Platzbedarf pro Monat wieder reduziert werden auf etwas das gleich Mass wie zuvor.

    Eher ein Fehler der aus mangelnder Erfahrung oder Nachlassigkeit entsteht ist die falsche Wahl der Speicheroptionen. Insbesondere wenn laufend Aenderungen an den Daten erfolgen und Saetze hinzugefuegt werden, verdienen die Parameter zur Einstellung der Freibereiche Beachtung. Diese Freibereiche werden ja nach DMBS am Ende jeder Page gelassen oder in Form von eingeschobenen Leerpages in der Tabelle. Sie dienen dazu, neue Saetze aufzunehmen und passend in die vorgegebene Sortierung der Tabelle einordnen zu koennen. Enthaelt eine Page beispielsweise alle Saetze zu "A" und soll ein weiterer Satz zu "A" hinzugefuegt werden, dann waere es sinnvoll, wenn er auch in diese Page eingefuegt werden koennte. Beim Auslesen waeren somit wieder alle Rows zu "A" beisammen. Ist dieser Freibereich zu klein gewaehlt, fuegt das DBMS die neuen Saetze am Ende der Tabelle ein, was zu haufigem Hin-und-Herspringen fuehren kann bei der Abfrage, und Performance kostet. Wird der Wert zu groß gewaehlt, blaeht sich die Tabelle unnoetig auf, was auch wieder Performance kostet.
    Welches DBMS hier welche Einstellungen ermoeglicht, muß jeweils der Doku entnommen werden.
    Eine regelmaeßige Reorganisation wird dadurch uebrigens nicht ueberfluessig. ;-)

    Ein weiterer beliebter Fehler oft aus Faulheit ist die Anwendungsentwicklung, ohne die SQL-Statements per Explain zu überprüfen. Explain zeigt die Art des Zugriffes auf die Daten an. Indexbasiert, Indescann, Tablescann, ... Es hat schon manch ein Programmierer ruhigen Gewissens den Arbeitsplatz verlassen , im Glauben, seine Querys wuerden den Index nutzen, und tatsaechlich den Server in die Knie gezwungen, weil ein Tablescann erfolgte.

    Puh, das sind nur drei beispiele. Daneben gibt es noch tausend Dinge, die Performance kosten koennen. Datenbanktuning gehoert in den Bereich DB-Administration und der ist nicht ohne Grund ein eigener Beruf. Ein Blick in die Doku und besonders in den Abschnitt Tuning ist imho immer noch die beste Informationsquelle.

    HTH

    Viele Gruesse
     Kess

    1. Hallo Kess,

      uff ... machst du uns einen Feature-Artikel aus diesem Posting?
      (wenn du mal wieder viel Zeit hast ... :-)

      viele Gruesse
        Stefan Muenz

    2. Hallo Kess,

      erstmal vielen, vielen Dank für diese ausführliche Antwort.
      Eine Frage vorweg:
      Wie kommt man zu solchem (Detail)Wissen?
      Studium, Berufserfahrung, Privatvergnügen?
      Kann man ja richtig neidisch werden ;-)

      Macht es Sinn, eine Datenbank bis in die letzten Details zu normalisieren?
      Es kommt darauf an ;-)

      Ich habs befürchtet, allgemeingültige Aussagen wird man in diesem Bereich wohl nicht erhalten können :-(

      Darum gilt im Allgemeinen: Je kleiner die Tabelle, desto weniger Sinn macht eine Normalisierung.

      Kleines Beispiel aus dem Projekt:

      Ich habe eine Tabelle AKTIEN, in der zu beliebigen Wertpapieren ca. 10 Daten gespeichert werden.
      Unter anderem kann sich eine Aktie in verschiedenen Indices (DAX, NEMAX, ...) befinden, wobei die Anzahl der möglichen Indices auf 10 beschränkt ist.
      Also ein typischer Fall einer N:M-Beziehung, die nach der Theorie 3 Tabellen erfordert:

      1. AKTIE (id, ...)
      2. INDEX (id, name)
      3. AKTIE_INDEX (aktien_id, index_id)

      Wie kann ich jetzt sowas performanter auf zwei Tabellen beschränken?
      Die INDEX-Tabelle wegschmeissen und den INDEX-Namen bei AKTIE-INDEX speichern?
      Oder, ganz anders, die INDEX-IDs in der AKTIEN-Tabelle in einem Feld mit Trennzeichen speichern und dafür AKTIEN_INDEX einstampfen? (wahrscheinlich dämlich?!)

      Vor jedem groesseren Datenbankdesign sollte man sich ueberlegen, welche Daten in welchen Prozessen verarbeitet werden. Wird Wert auf eine leichte Pflege gelegt oder Wert auf Performance? Wie lauten die wichtigsten SQL-Statements? Wie sehen die Arbeitsablaeufe aus? Haeufige Abfrage und wenig "Bewegung" in den Daten selbst? Oder permanante Datenaenderungen? usw.
      All diese Fragen spielen eine Rolle beim Datenbankdesign. Erst wenn der Anforderungskatalog mit Prioritaetenliste steht und eine vollstaendige (!) Beschreibung der Daten vorhanden ist, sollte das eigentliche DB-Design beginnen.
      In der Praxis sieht es oft anders aus, was dann schnell zu Beschwerden ueber lahme DB-Server fuehrt und tatsaechlich fast immer am unpassenden Design liegt.

      Welche Auswirkungen auf das Design hätten denn folgende Vorgaben:
      Prio 1: Performance
      Prio 2: Pflege
      Viele (!!) Abfragen und eine konstante Zuwachs- bzw. Änderungsrate, dabei fast immer komplexe SELECT-Statements über mehrere Tabellen.

      Daher gilt: Spalten fester Länge an den Anfang, Varchar-Spalten ans Ende der Tabelle.
      Haeufiger benoetigte Spalten nach vorne, selten benoetigte Spalten ans Ende.

      Super-Hinweis, wäre mir selber nie in den Sinn gekommen, das die Feldreihenfolge so grossen Einfluss haben kann.
      Damit lässt sich bestimmt einiges optimieren.

      Je genauer die noetige Laenge der Felder abgeschaetzt wird, desto weniger Platz wird unnoetig verschwendet und desto mehr Rows einer Tabelle passen in eine Page. Bei der Abfrage jeweils nur eines einzigen Satzes aus einer Tabelle ist dies irrelavent. Werden aber grosse Bereich der Tabele abgefragt, dann sind kuerzere Saetze in sofern interessant, dass das DBMS weniger Pages einlesen muss.

      OK, dann werd ich unsere Redakteure mal ein wenig mit solchen Abschätzungen belästigen ;-)

      Puh, das sind nur drei beispiele. Daneben gibt es noch tausend Dinge, die Performance kosten koennen. Datenbanktuning gehoert in den Bereich DB-Administration und der ist nicht ohne Grund ein eigener Beruf. Ein Blick in die Doku und besonders in den Abschnitt Tuning ist imho immer noch die beste Informationsquelle.

      Ich seh schon, da wollen noch einige Dokus gewälzt werden!
      Trotzdem nochmals herzlichen Dank für deine Anregungen.

      Viele Grüsse
      Stephan

      1. Hallo Stephan,

        Wie kommt man zu solchem (Detail)Wissen?
        Studium, Berufserfahrung, Privatvergnügen?
        Kann man ja richtig neidisch werden ;-)

        lass deinen Neid daheim, ein erfahrener Datenbankadministrator (nein, ich bin keiner) hat ganz andere Tricks drauf. Mir reicht es fuer den Hausgebrauch bzw. die Arbeit. Und genau dort bei der Arbeit habe ich mich in diese Dinge eingelesen und entsprechende Schulungen besucht. Es steckt also kein geheimer Vodoozauber dahinter. ;-)

        Ich habs befürchtet, allgemeingültige Aussagen wird man in diesem Bereich wohl nicht erhalten können :-(

        Nunja, es gibt auch keine allgemeingueltige Antwort auf die Frage nach dem richtigen Glauben. Dies muss jeder fuer sich entscheiden. Und jedes DB-Projekt besitzt eben auch andere Anforderungen. :-)

        Ich habe eine Tabelle AKTIEN, in der zu beliebigen Wertpapieren ca. 10 Daten gespeichert werden.
        Unter anderem kann sich eine Aktie in verschiedenen Indices (DAX, NEMAX, ...) befinden, wobei die Anzahl der möglichen Indices auf 10 beschränkt ist.
        Also ein typischer Fall einer N:M-Beziehung, die nach der Theorie 3 Tabellen erfordert:

        1. AKTIE (id, ...)
        2. INDEX (id, name)
        3. AKTIE_INDEX (aktien_id, index_id)

        Wie kann ich jetzt sowas performanter auf zwei Tabellen beschränken?
        Die INDEX-Tabelle wegschmeissen und den INDEX-Namen bei AKTIE-INDEX speichern?
        Oder, ganz anders, die INDEX-IDs in der AKTIEN-Tabelle in einem Feld mit Trennzeichen speichern und dafür AKTIEN_INDEX einstampfen? (wahrscheinlich dämlich?!)

        Nein, gar nicht daemlich. Erfolg der Zugriff beispielsweise immer ueber den Aktienindexnamen, dann wuerde in obigem Beispiel in jedem Fall ein Join noetig, um die ID des Aktienindexes zu ermitteln. Die kann man sich sparen, wenn man den Namen mit in der Tabelle AKTIE_INDEX fuehrt. Beispielsweise in Form von "index_name.aktien_id", wobei der Punkt das Trennzeichen waere. Dies macht Sinn, wenn haeufig ueber den Indexnamen nach mehreren Aktien gefragt wird. Werden umgekehrt zu einer Aktie, auf die mit Namen zugegriffen wird, die verschiedenen Indexwerte verlangt, dann macht eine Spalte "aktien_name.index_id" mehr Sinn. Natuerlich kann man auch gleich "index_name.aktien_name" bzw. "aktien_name.index_name" speichern. Dass dies nicht mehr normalisiert ist, ist klar :-)

        Sinn macht es, alle drei Tabellen in der normalisierten Form zu erhalten und eine zusaetzliche vierte auf die Performance hin optimierte Tabelle zu erzeugen, mit der bei Abfragen gearbeitet wird ...

        Welche Auswirkungen auf das Design hätten denn folgende Vorgaben:
        Prio 1: Performance
        Prio 2: Pflege
        Viele (!!) Abfragen und eine konstante Zuwachs- bzw. Änderungsrate, dabei fast immer komplexe SELECT-Statements über mehrere Tabellen.

        Wann erfolgt die Pflege der Daten? Fortlaufend in Echtzeit? Oder beispielsweise stets am Ende eines Boersentages?
        Kompliziert wird es naemlich nur, wenn die die Hauptzeiten der Datenaenderung und der Abfrage ueberschneiden. Muessen aktualisierte Daten beispielsweise nur taeglich zur Verfuegung stehen, wuerdeich sie in die normalisierten Tabellen einzuflegen und aus diesen allabendlich außerhalb der Hauptzugriffszeit die performanceoptimierten Tabellen generieren.
        Muessen die Aenderungen wirklich in Echtzeit verfuegbar sein, wird es schwieriger. Dinge wie Aktienname aendern sich weniger haeufig. Hier kann man getrost auf Performance achten und den erhoehten Wartungsaufwand als Sonderfall behandeln, der dann eben Zeit kostet.
        Meine ganz persoenliche Meinung: Immer auf Abfrage-Performance optimieren. Anwender sind nie geduldig :-) Den Pflegeaufwand kann man durch geschickte Codierung verbessern. Jedes Update ist zunaechst auch nur ein Select. Die zu aendernden Daten muessen eingelesen werden, bevor sie zurueckgeschrieben werden koennen. Wenn man reihenweise Updates in der Reihenfolge ausfuehren laesst, in der die Daten in der Datenbank abgelegt sind, erspart man dem DBMS haeufige Pagewechsel. Sollen beispielsweise die Kurse akutalisiert werden und sind die Kurstabellen nach Aktienname sortiert, dann ist es hilfreich, die Update-Statements nacheinander in dieser Reihenfolge (nach Aktienname) ausfuehren zu lassen. Viele DBMS halten eingelesene Index- und Datenpages naemlich noch eine Weile im Speicher, bis kein Platz mehr ist und neue angefordert werden muessen. Das naechte Update-Statement koennte also die noetigen Pages schon im Speicher vorfinden.

        Bei sehr hoher Last und Locking-Problemem kann man auch mit zwei Tabellen arbeiten, zwischen denen  hin- und hergeschaltet wird. Eine Tabelle nimmt die Aenderungen auf und die andere dient der Abfrage. In regelmaessigen Abstaenden (5 Minuten, Viertelstunde, ...) Wird gewechselt.

        <sinnierend>Hm, liest sich ja nett. Doch wie war das gerade noch bei meinem eigenen Projekt? Sollte ich mich nicht auch selbst daran zu halten? ... *seufz*</sinnierend> ;-)

        Viele Gruesse
         Kess

      2. Hallo,

        Daher gilt: Spalten fester Länge an den Anfang, Varchar-Spalten ans Ende der Tabelle.
        Haeufiger benoetigte Spalten nach vorne, selten benoetigte Spalten ans Ende.

        Super-Hinweis, wäre mir selber nie in den Sinn gekommen, das die Feldreihenfolge so grossen Einfluss haben kann.
        Damit lässt sich bestimmt einiges optimieren.

        MySQL akzeptiert Tabellen mit CHAR und VARCHAR-Spalten nicht und macht aus den CHAR-Spalten ebenfalls VARCHAR. Das hat einen einfachen Grund: Besteht eine Tabelle nur aus Spalten fester Länge (INT, CHAR usw.), kann man beim Suchen die Zeilen schneller abgrasen. (Man sucht zB. nach Inhalten der 2. Spalte, dann findet man diese genau aller x Bytes). Das ganze hat sich erledigt, sobald eine der Spalten keine feste Länge hat.

        Man sollte also Überlegen: alle Spalten als CHAR werden schneller durchsucht, brauchen aber mehr Speicher und vor allem mehr Ladezeit. Tabellen mit VARCHAR-Zellen verursachen mehr Suchaufwand, werden aber schneller in den Speicher geladen. Außerdem verursachen UPDATES einen großen Overhead, wenn zB. die neue VACHAR-Länge größer ist als die alte, und die Zeile deshalb ans Datenbankende geschoben wird. Auch alle anderen Insert- oder Indexaufgaben werden vermutlich langsamer.

        Varchar-Spalten bis Länge 3 werden übrigens als CHAR behandelt.

        soviel zur Theorie.. viel Spaß beim optimieren :o)
        Falk