phpbar.de logo

Mailinglisten-Archive

[php] OT Wozu ist denn ein =?iso-8859-1?Q?Prim=E4rschl=FCssel?= gut ?

[php] OT Wozu ist denn ein =?iso-8859-1?Q?Prim=E4rschl=FCssel?= gut ?

Kristian =?iso-8859-1?Q?K=F6hntopp?= kk_(at)_netuse.de
Fri, 26 Nov 1999 11:55:45 +0100


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