Kess: Normalisierung vs. Performance

Beitrag lesen

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