3K\VLVFKH'DWHQRUJDQLVDWLRQ 3K\VLVFKH'DWHQRUJDQLVDWLRQ Datenbanken – externe Ebene – konzeptionelle Ebene – physische Ebene Leistungsfähigkeit eines DBMS – maßgeblich bestimmt durch die Datenstrukturen auf der physischen Ebene Abbildung der konzeptionellen Ebene auf die physische Ebene Zugriffsstrukturen Pufferorganisation Externspeicherverwalt. ext. Speichermedium Datenobjekte: Datensätze Relationen Abbildung Datenobjekte: Seiten Dateien ? Seite 250 3K\VLVFKH'DWHQRUJDQLVDWLRQ $UFKLWHNWXU AWP 1 AWP 2 ••• AWP n Algorithmen – Implementierung der Operatoren der relationalen Algebra Anfragebearbeitung logische Seitenreferenzen Systempufferverwaltung Zugriffstrukturen – physische Seitenreferenzen Hilfsdatenstrukturen für den schnellen Zugriff auf die relevanten Datensätze. Externspeicherverwaltung Speicherstrukturen Plattenzugriffe – Physische Repräsentation der Relationen Seite 251 3K\VLVFKH'DWHQRUJDQLVDWLRQ $XIEDXHLQHV0DJQHWSODWWHQVSHLFKHUV Magnetplatten – seit über 40 Jahren die Technologie zur persistenten Datenspeicherung Eigenschaften – JQVWLJ*%IU¼ – robust – große Speicherkapazität: bis 400 GB/Platte – langsam Entwicklung der Plattenspeichertechnologie 0,85 Zoll Durchmesser Plattenspeicher 1957 Plattenspeicher heute (2.5” Durchmesser) RAID-Plattensysteme Seite 252 3K\VLVFKH'DWHQRUJDQLVDWLRQ )XQNWLRQVZHLVHYRQ3ODWWHQV\VWHPHQ Festplatte besteht aus einem Stapel übereinander liegender Magnetplatten. – Jede Oberfläche hat einen Lese/Schreibarm. – Lese/Schreibarme bewegen sich synchron, wobei nur einer davon aktiv ist. Strukturierung: – =\OLQGHU, 6SXU und 6HNWRU6HLWH – Zugriff über einen Kamm mit Schreib-/Leseköpfen, der quer zur Rotation bewegt wird Zugriff auf Seiten – Positionierung des Schreib-/Lesekopfes (Seek) Zeit für die Armbewegung [5 ms] – Warten auf den Sektor / Seite (5RWDWLRQVYHU]|JHUXQJ) halbe Rotationszeit der Platte [3 - 4,3 ms] – Übertragung der Seite7UDQVIHU]HLW Zeit für Schreiben bzw. Lesen einer 4 KByte Seite [0,05 ms] – Kontrolle der Übertragung: Zeit des Platten-Controllers [ < 1 ms] =HLWIU=XJULIIHLQHU6HLWH!!=HLWIU+DXSWVSHLFKHU]XJULII Seite 253 3K\VLVFKH'DWHQRUJDQLVDWLRQ 6\VWHPSXIIHU9HUZDOWXQJ Umsetzung der logischen in physische Seitenadressen Schnittstelle: Bereitstellen einer DB-Seite im DB-Puffer (zur exklusiven oder gemeinsamen Benutzung). Bereitstellen einer neuen Seite Freigeben einer Seite intern verwendete Funktionen: Effiziente Suche im Puffer – Hash-Tabelle Suche nach freiem Platz im Puffer (Frames) Bestimmen einer Seite (Opfer), die aus dem Puffer entfernt wird. – Least-Recently-Used: Verkettung der Seiten nach dem letzten Zeitpunkt der Nutzung Schreiben modifizierter Seiten – Erfolgt in Absprache mit der Transaktionsverarbeitung Seite 254 3K\VLVFKH'DWHQRUJDQLVDWLRQ 6SHLFKHUVWUXNWXUHQ Datenbanken werden typischerweise auf eine Datei bzw. eine Menge von Dateien abgebildet. Beim Anlegen der Datenbank werden noch wichtige Parameter mitgegeben: – Initiale Dateigröße – Maximale Dateigröße – Inkrementelle Größe Beim Anlegen einer Relation wird der Relation eine initiale Seite zugewiesen. – Alle weiteren Seiten werden dann miteinander verkettet. Tuple-Indentifier (TID auch RowID und RID genannt) TID ist eine eindeutige Kennung des Datensatzes innerhalb der Datenbank. Dieser setzt sich zusammen aus der Seitenadresse und einer relativen Adresse innerhalb der Seite. Der markierte Datensatz hat die TID (42,3) Seitenadresse: 42 Seite 255 3K\VLVFKH'DWHQRUJDQLVDWLRQ – TIDs sind invariant bzgl. Verschiebungen innerhalb einer Seite Die TID ändert sich auch nicht, wenn ein Datensatz in eine andere Seite verschoben wird. – Anlegen eines Stellvertreters in der ursprünglichen Seite, der auf die neue Position verweist. j (4711,j) Seitenadresse: 42 Seitenadresse 4711 Vorteil des TID-Konzepts – TID sind stabil Nachteil – hohe Zugriffskosten, wenn es viele Stellvertreter gibt. ==> Reorganisation der Datenbank Seite 256 3K\VLVFKH'DWHQRUJDQLVDWLRQ 5HFRUGPDQDJHU Komponente zur Verwaltung der Datensätze in Seiten Zentrale Aufgabe des Recordmanager Für einen neuen Datensatz soll eine Seite mit genügend freiem Speicherplatz gefunden werden. – Ggf. muss hierfür eine neue Seite angefordert werden. Wünschenswert wäre auch eine Ballung (Clusterung) der Datensätze: – Datensätze, die oft gemeinsam zugegriffen werden, sollen auch gemeinsam in einer Seite liegen. Unterscheidung Datensätze mit konstanter Länge – einfache Lösungen: z. B. Verkettung der Seiten, die noch Platz haben. Datensätze mit variabler Länge – relativ kompliziert Seite 257 3K\VLVFKH'DWHQRUJDQLVDWLRQ =XJULIIDXIGLH%DVLVUHODWLRQHQ Bei Datenbanken unterscheidet man zwischen zwei Zugriffsarten: Relationen-Scan – Durchlaufen der zu der Relation gehörenden Seiten. Index-Scan – Zugriff erfolgt indirekt über eine Hilfsstruktur, in der die Verweise (TID) auf die Datensätze (zusammen mit z. B. einem Attribut) der Relation hinterlegt sind Index auf dem Attribut Lohn der Relation Personal (1000, (42,3)) (2100, (42,1)) (3000,(4711,2)j (4711,j) Seitenadresse: 42 Seitenadresse 4711 Seite 258 3K\VLVFKH'DWHQRUJDQLVDWLRQ ,QGH[VWUXNWXUHQ Ziel: Effizienter Zugriff auf die Datensätze einer Relation, die ein bestimmtes Prädikat erfüllen. Strukturen sollen keinen erheblichen Mehraufwand verursachen. – Änderungsoperationen – Speicherplatz Klassifizierung Eindimensionale Prädikate (bzgl. einem Attribut) – Exakte Prädikate: – Bereichsprädikate und exakte Prädikate: Mehrdimensionale Prädikate – Bereichsprädikate Metrische Prädikate – Nachbarprädikate Mengenbasierte Prädikate Dyn. Hash-Verfahren B+- Bäume Seite 259 3K\VLVFKH'DWHQRUJDQLVDWLRQ $QIRUGHUXQJHQ Allgemeine Ziele beim Entwurf von Indexstrukturen Hohe Speicherplatzausnutzung Kurze Antwortzeiten für eine Operation – Benötigte Zeit entspricht dabei der Anzahl der Seitenzugriffe Operationen Suchanfragen – Einlesen einer Teilmenge der Daten einer Relation – Exakte Suche: select * from R where R.A = c – Bereichssuche: select * from R where c1 d R.A and R.A d c2 Einfügen, Löschen und Ändern – Reorganisationen der Daten des Index erforderlich – Reorganisationen sollen nur lokal auf einem kleinen Teil der Daten einwirken (G\QDPLVFKH Indexstrukturen) Seite 260 3K\VLVFKH'DWHQRUJDQLVDWLRQ 6XFKElXPH Wichtige Datenstruktur für Hauptspeicher und Hintergrundspeicher zur Unterstützung von Bereichsprädikaten (siehe Prakt. Info II) Definitionen (Baum) Ein %DXP ist eine endliche Menge T von Elementen, .QRWHQgenannt,mit: (1) Es gibt einen ausgezeichneten Knoten w(T), die :XU]HO von T (2) Die restlichen Knoten sind in P t 0 disjunkte Mengen T1, …, TP zerlegt, die ihrerseits Bäume sind. T1, …, TP heißen 7HLOElXPH der Wurzel w(T). Der *UDG eines Knotens [, GHJ[, ist gleich der Anzahl der Teilbäume von [. Gilt GHJ([) = 0, so nennt man [ ein %ODWW. Jeder Knoten [DXHUZ7hat einen eindeutigen Vorgänger YP[, auch als 9DWHU0XWWHU bezeichnet. Ein 3IDG in einem Baum ist eine Folge von Knoten p1, …, pQ mit: pi = YP(pi+1), i = 1, …, Q-1. Die /lQJHGHV3IDGHV ist Q. Die +|KH eines Baums entspricht der Länge des längsten Pfads. Seite 261 3K\VLVFKH'DWHQRUJDQLVDWLRQ Definition (Suchbaum) Sei auf der Menge T eine Ordnungsrelation “<“ definiert. Ein Suchbaum vom Grad b ist entweder – leer oder – die Wurzel beseht aus einer Folge p0,t1,p1,t2,…,tm,pm, m d b, wobei gilt: a) ti < ti+1, i = 1,…,m-1 b) p0,p1,…,pm Verweise auf Suchbäume mit folgenden Eigenschaften: (i) Für alle Elemente t in p0 gilt t d t1 und für alle Elemente t in pm gilt t ! tm. (ii) Für alle Elemente t in pi, 1d i m, gilt: ti dtti+1 Wichtige Resultate für binäre Suchbäume: Für n Datensätze ist die PLQLPDOH+|KH eines binären Baums ªlog2(Q+1)º Es gibt binäre Suchbäume (z. B. AVL-Bäume), die folgendes Leistungsverhalten im schlechtesten Fall aufweisen: – Speicherplatzbedarf: O(n) – Höhe: O(log n) – Kosten für exakte Suche, Einfügen und Löschen: O(log n) – Kosten für Bereichssuche: O(r + log n), wobei r die Anzahl der Antworten ist. Seite 262 3K\VLVFKH'DWHQRUJDQLVDWLRQ 'LHVFKOHFKWH1DFKULFKW Einfache Abbildung von binären Knoten auf Seiten führt zu schlechten Strukturen. – im schlechtesten Fall: ein Knotenzugriff = ein Plattenzugriff – exakte Suche ist dann sehr teuer z. B. für 106 Datensätze beträgt die Höhe bereits 20 Binäre Suchbäume sind also nicht für die Verwaltung auf dem Externspeicher geeignet. binärer Baum ideale Baumstruktur für den Externspeicher Zentrale Frage (bis Ende der 60er Jahre): Gibt es eine effiziente Zugriffsstruktur für einen seitenorientierten Externspeicher? Seite 263 3K\VLVFKH'DWHQRUJDQLVDWLRQ % %lXPH Prinzipien Im Gegensatz zu binären Bäumen enthält ein Knoten viele Einträge/Sätze – 1:1-Beziehung zwischen Knoten und Seiten – Daten werden exklusiv in den Blättern verwaltet Basieren auf dem Konzept von – ISAM (Index Sequentiel Access Method) statisch: globale Reorganisation periodisch erforderlich – B-Bäumen (Bayer & McCreight, 1972) Funktionsumfang und Leistung Leistung des B+-Baums hängt von dem Verzweigungsgrad b eines Knotens ab. Suchfunktionen: – Exaktes Prädikat – Bereichsprädikat Effizienz (Speicherplatz u. Antwortzeiten) ist asymptotisch unabhängig von der Einfügereihenfolge. Seite 264 3K\VLVFKH'DWHQRUJDQLVDWLRQ Definition (B+-Baum) Ein B+-Baum vom Typ (b, c) ist ein Baum mit folgenden Eigenschaften 1. Jeder Weg von der Wurzel zum Blatt hat die gleiche Länge. 2. Die Wurzel ist ein Blatt oder hat mindestens 2 Söhne. 3. Jeder Zwischenknoten hat mindestens b+1 und höchstens 2b+1 Söhne. 4. Jedes Blatt hat mindestens c und höchstens 2c Einträge. Zwischenknoten: p0 k1 p1 k2 p2 • • • km pm – pi = Zeiger Sohnseite, ki = Schlüssel – es gilt stets: ki < ki+1 für 0 < i < m. frei Blattknoten: V k1 TID1 k2 TID2 • • • km TIDm frei – TIDi = Verweis auf den Satz mit Wert ki – – N = Zeiger auf den rechten Blattknoten V = Zeiger auf den linken Blattknoten N Seite 265 3K\VLVFKH'DWHQRUJDQLVDWLRQ (LJHQVFKDIWHQGHV% %DXPV lokale Ordnungserhaltung: Für jeden Zwischenknoten Z mit j Schlüsseln k1,…,kj und (j+1) Söhnen p0,…,pj gilt: Für jedes i, 1 d i d j, sind alle Schlüssel in dem zu pi-1 gehörenden Teilbaum nicht größer als ki und ki ist größer als alle Schlüssel, die im Teilbaum von pi liegen. B+-Baum … … Datenraum … Seite 266 3K\VLVFKH'DWHQRUJDQLVDWLRQ %HLVSLHO b=2, c=1 Beachte: b und c sind nur aus Gründen der Übersicht so klein gewählt! Seite 267 3K\VLVFKH'DWHQRUJDQLVDWLRQ :LHKRFKNDQQHLQ% %DXPZHUGHQ" Welche Höhe besitzt ein B+-Baum zur Abspeicherung von N Datensätzen im schlechtesten Fall? Oder anders gefragt: Wie viele Datensätze müssen mindestens (dürfen höchstens) in einem B+-Baum der Höhe h sein? Vereinfachende Annahme: b+1 = c Wurzel hat mindestens 2 Einträge Zwischenknoten in der Ebene 2 hat mindestens b +1 Einträge Zwischenknoten in der Ebene 2 hat mindestens b +1 Einträge … b +1 Einträge Blattknoten in der Ebene h hat mindestens b + 1 Sätze Daraus ergibt sich, dass in einem B+-Baum der Höhe h mindestens 2*(b+1)h-1 Datensätze liegen. Es gilt also N t 2*(b+1)h-1 und somit 1+1 K d 1 + log E + 1 §© -------------·¹ = 2 log E 1 2 Besonderheit der asymptotischen Analyse: b ist keine Konstante Seite 268 3K\VLVFKH'DWHQRUJDQLVDWLRQ 6SHLFKHUSODW]IUGHQ% %DXP Speicherplatzausnutzung (SPAN): minimal erforderlicher Speicherplatz--------------------------------------------------------------------------------------tatsächlich reservierter Speicherplatz Im schlimmsten Fall – Jeder Knoten (mit Ausnahme der Wurzel) ist mit mindestens der Hälfte der möglichen Schlüssel gefüllt. Ein B+-Baum braucht (im schlechtesten Fall) doppelt soviel Speicher wie ein optimal gefüllter Baum. Damit ergibt sich eine Speicherplatzausnutzung von mindestens 50%. Im Durchschnitt – OQ (etwa 69%). – Wie viele Einträge passen in einen Zwischenknoten der Größe 4 KB? – pro Zeiger: 4 Byte – pro Schlüssel: 4 Byte Dies ergibt ca. 500 Einträge in einem Zwischenknoten. Seite 269 3K\VLVFKH'DWHQRUJDQLVDWLRQ ([DNWH6XFKHLP%%DXP Problem: Gegeben ein Schlüssel x. Liefere den TID des Datensatzes r mit r.key = x in dem B+-Baum mit Wurzel URRW: EMQ(root, x). Algorithmus EMQ(pakt: Knoten, x: Key) ReadPage(pakt); IF (pakt ist ein Zwischenknoten) THEN index := m; // m = Anzahl der Schlüssel im Zwischenknoten Bestimme im Knoten pakt den kleinsten Schlüssel ki, so dass x d ki. IF (es gibt solch ein ki) THEN index := i-1; END; RETURN EMQ(pindex, x); // rekursiver Aufruf ELSE Bestimme im Knoten pakt den Datensatz (ki,TIDi) mit x = ki. RETURN (es gibt solch einen Datensatz) ? TIDi : NULL; END; END EMQ; Seite 270 3K\VLVFKH'DWHQRUJDQLVDWLRQ %HLVSLHO Vereinfachende Annahme Es wird nur als Ergebnis geliefert, ob der Datensatz im Baum ist. Suche den Datensatz mit Schlüssel 42. Suche den Datensatz mit Schlüssel 41. 41 12 28 1 5 9 12 15 19 28 46 67 33 37 41 45 46 53 59 67 71 83 99 Seite 271 3K\VLVFKH'DWHQRUJDQLVDWLRQ %HUHLFKVDQIUDJHLP% %DXP Gegeben ein Schlüsselpaar ORZ und XS, ORZ d XS. Finde alle TID der Datensätze r mit ORZ d r.key d XS im B+-Baum mit Wurzel URRW: RQ(root,low,up) Algorithmus RQ(pakt: Knoten; low,up: Key) Bestimme analog zur exakten Suche das Blatt first, in dem ein Datensatz mit Schlüssel low liegen könnte; Res = pakt = first; LOOP ReadPage(pakt); FOREACH (r mit r.key in [low,up] im Knoten pakt) IF Res += {r.TID} ((es gibt ein Datensatz r mit r.key ! up in pakt) OR (pakt ist das am weiten rechts liegende Blatt im B+-Baum)) THEN RETURN Res; pakt := pakt.N; // Gehe zum rechten Nachbarknoten END; END RQ; Seite 272 3K\VLVFKH'DWHQRUJDQLVDWLRQ %HLVSLHO Suche alle Datensätze im Bereich [40, 52]. 41 12 28 1 5 9 12 15 19 28 46 67 33 37 41 45 46 53 59 67 71 83 99 Seite 273 3K\VLVFKH'DWHQRUJDQLVDWLRQ (LQIJHQXQG/|VFKHQLQ% %lXPHQ Meistens ist das Einfügen und Löschen sehr einfach: Entspricht fast immer einer exakten Suche, dem Einfügen des neuen Satzes und dem Zurückschreiben des modifizierten Blatts (Datenseite). Manchmal treten aber folgende Problemfälle auf: Was passiert wenn die Seite keinen Datensatz mehr aufnehmen kann? 1. Lösung: Einführung von Überlaufseiten und verketten mit der Primärseite. – Nachteil: Kosten für Suche, Einfügen und Löschen erhöhen sich. 2. Lösung: Reorganisation der Datenstruktur 6RIRUW: Überlaufseiten werden nicht zugelassen. Reorganisation des B+Baums soll aber lokal begrenzt bleiben. – 9HU]|JHUW: kurzzeitige Verwendung von Überlaufseiten und spätere globale Reorganisation des Datenbestands. Was passiert wenn es zu wenige Datensätze in der Seite gibt? – Seite 274 3K\VLVFKH'DWHQRUJDQLVDWLRQ (LQIJHQLP% %DXP Gegeben einen Datensatz r = (key,TID) und die Wurzel root des B+-Baums. Füge den Datensatz in den B+-Baum ein: Insert(root,r). Algorithmus Insert(pakt: Knoten; r: Record); Suche nach dem Datensatz mit Wert r.key; (* siehe EMQ(pakt, r.key *) IF (Datensatz wurde gefunden) THEN Print(“ERROR”); RETURN END; Setze pakt auf das zuletzt gelesene Blatt; Füge r in pakt ein; WHILE (pakt ist übergelaufen) THEN Teile die Datensätze in pakt in zwei gleich große Gruppen L und R, so dass alle Datensätze in L kleiner sind als die Datensätze in R; Speichere die Datensätze in R in einem neuen Blatt pneu und die in L in pakt; Sei kmax der größte Schlüssel in L; pakt = (vm(pakt) != NULL) ? vm(pakt) : newRoot(pakt);// Gehe zum Vater Füge das Paar (kmax, pneu) in den Vaterknoten ein; END Insert; Seite 275 3K\VLVFKH'DWHQRUJDQLVDWLRQ 6SH]LDOIDOOhEHUODXIGHU:XU]HO Schleife wird spätestens durch eine Überlaufbehandlung der Wurzel beendet. Durch den Aufruf der Methode newRoot wird eine neue Wurzel bereitgestellt: neue Wurzel pakt pakt – Der neue Wurzelknoten verfügt zunächst über nur einen Eintrag. Sofort danach wird dann der zweite Eintrag eingefügt. Seite 276 3K\VLVFKH'DWHQRUJDQLVDWLRQ %HLVSLHO Einfügen von 45 in folgenden B+-Baum 12 28 46 67 1 5 9 12 – 15 19 28 33 37 41 46 53 59 67 71 83 99 Suche nach dem Blatt 12 28 46 67 1 5 9 12 – 15 19 28 45 33 37 41 46 53 59 67 71 83 99 Einfügen in das Blatt, Spalten des Blatts und Einfügen in den Vater 12 28 46 67 (41, ) 1 5 9 12 15 19 28 33 37 41 45 46 53 59 67 71 83 99 Seite 277 3K\VLVFKH'DWHQRUJDQLVDWLRQ – Einfügen in die Wurzel, Spalten der Wurzel und Erzeugen der neuen Wurzel 41 12 28 1 5 9 12 15 19 28 46 67 33 37 41 45 46 53 59 67 71 83 99 Wichtige Eigenschaften beim Einfügen: Einfügeoperation bleibt auf einen Pfad des B+-Baums beschränkt. – Pro Ebene wird höchstens ein neuer Knoten hinzugefügt. – Der Aufwand für das Einfügen eines Datensatzes beträgt O(logb N) Beim Einfügen bleiben alle Invarianten des B+-Baums erhalten. Seite 278 3K\VLVFKH'DWHQRUJDQLVDWLRQ /|VFKHQLP% %DXP Gegeben ein Schlüssel k und die Wurzel des B+-Baums. Finde den Datensatz mit Schlüssel k im B+-Baum und entferne diesen. Problemfälle: Wie kann verhindert werden, dass ein Knoten zu wenig Datensätze enthält? – Ausgleich mit einem Geschwisterknoten – Ggf. muss der Knoten mit einem Geschwisterknoten verschmolzen werden. Was passiert, wenn ein Datensatz gelöscht wird, dessen Schlüssel auch als Referenz in einem Elternknoten benutzt wird? – Das stellt kein Problem dar, weil die internen Schlüssel nur eine Wegweiserfunktion besitzen. 41 Löschen von 41 12 28 1 5 9 12 15 19 28 46 67 33 37 41 45 46 53 59 67 71 83 99 Seite 279 3K\VLVFKH'DWHQRUJDQLVDWLRQ .RVWHQIU6XFKHQ(LQIJHQXQG/|VFKHQ Exakte Suche, Einfügen und Löschen sind auf einen Pfad beschränkt Im schlechtesten Fall ergeben sich folgende Kosten für den B+-Baum: exakte Suche: O(logb N) Bereichanfrage: O(logb N + r/b) Einfügen: O(logb N) Löschen: O(logb N) Praktische Überlegungen Wie viele Datensätze können in einem B+-Baum der Höhe 3 gespeichert werden? Beispiel (b = 200, 4 KB pro Seite); ,PVFKOHFKWHVWHQ)DOO: 400*200*200 = 16*106 Datensätze, 8*104 Datenseiten = 320 MB Speicherplatz für die Blattebene des B+-Baums. – ,P'XUFKVFKQLWW: Da Knoten zu etwa 2/3 im Durchschnitt gefüllt sind, können voraussichtlich 400*270*270 = 29*106 Datensätze verwaltet werden. Es wird nun 430 MB an Speicherplatz für die Blattebene benötigt. In vielen Anwendungen: Wurzel im Hauptspeicher ==> 2 Plattenzugriffe für exakte Suche – Seite 280 3K\VLVFKH'DWHQRUJDQLVDWLRQ ,QGH[HLQ'DWHQEDQNHQ Cluster-Index Höchstens ein Index pro Relation kann als Cluster-Index angelegt werden: create clustered index MeinIndex on … Durch einen Cluster-Index wird das Speicherlayout der Datensätze der Relation bestimmt. – Bespiel: DB2 von IBM (a) Datensätze werden entsprechend der Ordnung im Index auf die Seiten abgebildet. (b) Häufiges Einfügen zerstört die Ordnung. (c) Reorganisation der Relation (TEUER) clustert die Datensätze wieder. – Beispiel: SQL Server Sicherstellung der Eindeutigkeit durch einen Index Durch Anlegen eines Index kann sehr effizient überprüft werden, ob die Bedingung eines Schlüsselkandidats erfüllt ist. Anlegen eines unique-Index: create unique index MeinIndex on … Seite 281