Mailinglisten-Archive |
Stefan Pfister wrote: > Konkret hab ich hier eine MySQL Datenbank in der als eindeutiges Unter- > scheidungsmerkmal der Datensätze eine Feld mit einer UID-Nummer > vorkommt. > Weshalb sollte ich dieses Feld als Primärschlüssel deklarieren ? In einer relationalen Datenbank besteht eine Tabelle aus Zeilen, die Elemente einer Menge darstellen. Die einzelnen Elemente sind Tupel (also Mengen mit einer Reihenfolge) von atomaren Werten. Ein atomarer Wert ist ein Wert aus einem Basisdatentyp der Datenbank, also integer, varchar, timestamp und so weiter. Ein Tupel von solchen Werten ist also vergleichbar einen Struct in C. Eine Menge von Werten ist vergleichbar einem Hash in Perl (nicht einem Hash in PHP: Hashes in PHP haben eine definierte Reihenfolge!). In SQL ist es zunächst einmal nicht notwendig, daß zwei Tupel in einer Tabelle verschieden sind: mysql> create table beispiel ( -> i integer, -> f float, -> s varchar(20), -> t text ); Query OK, 0 rows affected (0.09 sec) mysql> insert into beispiel values ( 10, 3.14, "bla", "fasel" ); Query OK, 1 row affected (0.00 sec) mysql> insert into beispiel values ( 10, 3.14, "bla", "fasel" ); Query OK, 1 row affected (0.00 sec) Dabei entsteht das Problem, daß diese beiden Elemente nicht mehr unterscheidbar sind. Du kannst keine Operation im relationalen Modell formulieren, die auf das eine Tupel wird, aber nicht auf das andere (aber es gibt SQL-Erweiterungen, die in einigen Datenbanken existieren, die das relationale Modell verletzen und mit denen das wieder möglich ist). Daher definiert man in der Regel für eine jede Tabelle eine Spalte (atomarer Primärschlüssel) oder eine Kombination von Spalten (zusammengesetzter Primärschlüssel) als Primärschlüssel, sodaß keine zwei Zeilen existieren können, die in den als Primärschlüssel deklarierten Spalten dieselben Werte haben können. Mathematisch gesehen hat man nun eine Bijektion zwischen Zeilen und Primärschlüsselwerten definiert und definiert eine Äquivalenzrelation über die Zeilen mit Hilfe der Primärschlüssel. Nicht mathematisch und verständlich ausgedrückt heißt dies: Jede Mögliche Kombination von Werten in einer Zeile wird durch den Primärschlüssel repräsentiert. Wenn Du den Primärschlüssel kennst, kannst Du die entsprechenden anderen Werte daraus (durch Nachsehen in der Tabelle) bestimmen und umgekehrt. Außerdem sind zwei Zeilen genau dann gleich, wenn ihre Primärschlüssel gleich sind und alle zwei verschiedenen Zeilen haben unterschiedliche Primärschlüssel (Gleichheit von Zeilen wird definiert über die Gleichheit von Primärschlüsseln). Oder ganz praktisch formuliert: Alle Zeilen werden durch ihre Primärschlüsselwerte überhaupt erst unterscheidbar. Primärschlüssel können natürlich oder künstlich (synthetisch) sein. Bei künstlichen Primärschlüsseln kannst Du an Kundennummern denken. Für natürliche Primärschlüssel können in einer Tabelle mehrere Kandidaten geben, etwa kommen in einer Fahrzeugtabelle je nach Anwendung die Fahrgestellnummer oder das KFZ-Kennzeichen in Frage. Man muß dann in einer Designentscheidung entscheiden, ob man einen der Schlüsselkandidaten zum Primärschlüssel adelt oder ob man einen synthetischen Schlüssel generiert. Wichtig ist, daß man in einen Schlüssel (Primär oder nicht) keine weiteren Eigenschaften codiert. Ein Primärschlüssel definiert erst einmal KEINE Ordnung über die Zeilen, die er repräsentiert. Er ist eine Äquivalenzrelation (Operatoren == und !=), aber keine Ordnungsrelation. Wichtig ist auch, daß ein Schlüssel zunächst einmal keine INDEX repräsentiert. Rein theoretisch ist es denkbar, eine Spalte als Primärschlüssel zu deklarieren, ohne daß man deswegen einen Index angelegn müßte. Einfügeoperationen wären dann nur furchbar ineffizient: Beim Einfügen neuer Elemente muß, um die Eindeutigkeit sicherstellen zu können, nachgesehen werden, ob dieses Element schon existiert. Ohne Index ist dazu ein full table scan notwendig und das ist natürlich nicht effizient ohne einen Index zu haben. Daher legen viele Datenbanken für ihre PRIMARY KEY Spalten implizit einen UNIQUE INDEX an. Ein INDEX oder UNIQUE INDEX ist ein Detail der physikalischen Implementierung einer relationalen Tabelle. Anders als Primär- und andere Schlüssel, die auf der rein mathematischen Ebene des relationalen Modells existieren, handelt es sich um physikalische und maschinenabhängige Entitäten. Ein Index ist ein Auszug von interessanten Werten einer Tabelle, um Existenzprüfungen oder Ordnungsrelationen vorherzuberechnen. Um zum Beispiel prüfen zu können, ob ein Element in einer Tabelle bereits existiert, können einige Datenbanken Hashes anlegen, mit denen sie diese Frage schneller als mit einem full table scan beantworten können. Die Ergebnisse aller möglichen Existenzprüfungen sind durch das Anlegen und aktuell Halten des Index quasi schon vorher berechnet und müssen jetzt nur noch nachgeschlagen werden. Ordnungsrelationen auf einer Tabelle werden durch das Anlegen eines Tree Index vorausberechnet und können in Suchoperationen, Sortieroperationen oder in Joinoperationen verwendet werden, um die Operation effizienter zu machen. Dabei kann es zu Rückkopplungen zwischen der physikalischen Implementierung und dem mathematischen Modell kommen: Wenn eine Datenbank einen PRIMARY KEY dadurch unterstützt, daß sie für die Spalten des PRIMARY KEY einen Tree Index anlegt, dann werden auch Sortier- und Suchoperationen gegen den PRIMARY KEY schneller (nicht so, wenn der PRIMARY KEY als Hash realisiert wird). Indices machen jedoch Einfüge-, Lösch- und Aktualisierungsoperationen auf einer Tabelle langsamer, da neben dem Einfügen der Elemente auch die Indices mitgepflegt werden müssen. Bei bulk operations kann es daher sinnvoll sein, alle Indices zu droppen und am Ende der bulk operation neu zu generieren - das hängt aber von einer Reihe von physikalischen Parametern ab. Ebenso kann es sinnvoll sein, stattdessen während der bulk operation die Indexpflege anzuhalten und die Indices gesammelt am Ende des Batchupdates nachzuholen. Dafür gibt es dann in der Datenbank besondere Anweisungen. Die Qualität von physikalischen Indices ist in der Regel besser, wenn der Index gesammelt gepflegt wird, also neu erzeugt wird oder im Batch aktualisiert wird. Durch eine Reihe von einzelnen Löschungen oder Einfügungen kann man Fälle erzeugen, in denen etwa Bäume degenerieren und wenig effizient werden. Viele Datenbanken haben dafür Diagnose- und Optimierungstools. Kristian -- Kristian Köhntopp, NetUSE Kommunikationstechnologie GmbH Siemenswall, D-24107 Kiel, Germany, +49 431 386 436 00 Using PHP3? See our web development library at http://phplib.netuse.de/ (We have moved! Update your bookmarks!)
php::bar PHP Wiki - Listenarchive