Datenbanksysteme I - Praktische Informatik

Werbung
Udo Kelter
Datenbanksysteme I
Datenbanksysteme I
Udo Kelter
2013-12
Inhaltsverzeichnis
Vorwort
6
Lehrmodul 1: Datenverwaltungssysteme
1.1
1.2
1.3
1.4
1.5
Einleitung und Übersicht . . . . . . . . . . . . . . . .
Grundbegriffe . . . . . . . . . . . . . . . . . . . . . . .
1.2.1 Daten – Wissen – Information . . . . . . . . .
1.2.2 Informationssysteme . . . . . . . . . . . . . . .
1.2.3 Externe Darstellung von Daten . . . . . . . . .
1.2.4 Datenverwaltungssysteme . . . . . . . . . . . .
Datenverwaltungsprobleme . . . . . . . . . . . . . . .
1.3.1 Anwendungsnahe Datenmodellierungskonzepte
1.3.2 Korrekheitsüberwachung . . . . . . . . . . . . .
1.3.3 Such- und Auswertungsfunktionen . . . . . . .
1.3.4 Backup und Versionierung . . . . . . . . . . . .
1.3.5 Datenschäden durch Systemabstürze . . . . . .
1.3.6 Mehrbenutzerfähigkeit und Zugriffskontrollen .
1.3.7 Entfernter Zugriff . . . . . . . . . . . . . . . . .
1.3.8 Paralleler Zugriff . . . . . . . . . . . . . . . . .
1.3.9 Datenintegration und Sichten . . . . . . . . . .
1.3.10 Evolution der Datenbestände . . . . . . . . . .
Dateisysteme . . . . . . . . . . . . . . . . . . . . . . .
1.4.1 Arten von Dateisystemen . . . . . . . . . . . .
1.4.2 Verwaltung formatierter Daten in Dateien . . .
1.4.2.1 Codierungen . . . . . . . . . . . . . .
1.4.2.2 Such- und Auswertungsfunktionen . .
OLTP-Datenbankmanagementsysteme . . . . . . . . .
1.5.1 Datenbankmodelle . . . . . . . . . . . . . . . .
5
13
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
14
14
14
16
17
18
22
23
24
25
27
28
29
30
31
32
33
33
34
35
35
37
37
38
6
1.5.2
Datenintegration, Datenunabhängigkeit
Ebenen-Schema-Architektur . . . . . . .
1.5.3 Transaktionsverarbeitung . . . . . . . .
1.6 Information-Retrieval-Systeme . . . . . . . . .
1.7 Ein- und Ausgabeschnittstellen . . . . . . . . .
Glossar . . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
und die
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
3. .
. .
. .
. .
. .
Lehrmodul 2: B-Bäume
49
2.1
2.2
Historischer Hintergrund . . . . . . . . . . . . . . . . .
Verzeichnisse . . . . . . . . . . . . . . . . . . . . . . .
2.2.1 Generische ADT . . . . . . . . . . . . . . . . .
2.2.2 Der generische ADT directory [S,I] . . . .
2.3 B-Bäume . . . . . . . . . . . . . . . . . . . . . . . . .
2.3.1 Grundlegende Implementierungsentscheidungen
2.3.2 Vielweg-Suchbäume . . . . . . . . . . . . . . .
2.3.3 Merkmale von B-Bäumen . . . . . . . . . . . .
2.3.4 Primärschlüssel . . . . . . . . . . . . . . . . . .
2.4 Algorithmen . . . . . . . . . . . . . . . . . . . . . . . .
2.4.1 Suche . . . . . . . . . . . . . . . . . . . . . . .
2.4.2 Einfügung . . . . . . . . . . . . . . . . . . . . .
2.4.3 Löschung . . . . . . . . . . . . . . . . . . . . .
2.4.4 Beispiel . . . . . . . . . . . . . . . . . . . . . .
2.5 B*-Bäume . . . . . . . . . . . . . . . . . . . . . . . . .
Glossar . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Lehrmodul 3: Architektur von DBMS
3.1
3.2
3.3
3.4
Einleitung . . . . . . . . . . . . . . . . . . . . . . . .
Produkt vs. Laufzeitkern . . . . . . . . . . . . . . .
Prozeßarchitektur von Informationssystemen . . . .
Eine Abstraktionshierarchie von Datenbankobjekten
3.4.1 Übersicht . . . . . . . . . . . . . . . . . . . .
3.4.2 Ebene 0: physische Blöcke . . . . . . . . . . .
3.4.3 Ebene 1: DB-Segmente und DB-Seiten . . . .
3.4.4 Ebene 2: Zugriffsmethode für Sätze . . . . .
3.4.4.1 Zugriffsstrukturen . . . . . . . . . .
3.4.4.2 Realisierung von Sätzen auf Seiten .
3.4.4.3 Indexe . . . . . . . . . . . . . . . . .
3.4.5 Ebene 3: Einzelobjekt-Operationen . . . . . .
39
41
42
45
47
50
50
50
52
53
53
54
56
57
58
58
58
60
62
63
65
66
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
67
67
68
72
72
74
74
75
76
79
80
81
(gen: 2013-12-9-600)
7
3.4.6 Ebene 4: Mengen-Schnittstelle . . . . . . . . . . . . .
3.4.7 Beziehung zur 3-Ebenen-Schema-Architektur . . . . .
Glossar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Lehrmodul 4: Das relationale Datenbankmodell
84
4.1
4.2
Datenbankmodelle vs. reale Datenbanksprachen . . . . .
Die Struktur relationaler Datenbanken . . . . . . . . . .
4.2.1 Tabellen . . . . . . . . . . . . . . . . . . . . . . .
4.2.2 Relationen . . . . . . . . . . . . . . . . . . . . .
4.2.3 Integritätsbedingungen . . . . . . . . . . . . . . .
4.3 Die relationale Algebra . . . . . . . . . . . . . . . . . . .
4.3.1 Die Selektion . . . . . . . . . . . . . . . . . . . .
4.3.2 Die Projektion . . . . . . . . . . . . . . . . . . .
4.3.3 Die Mengenoperationen . . . . . . . . . . . . . .
4.3.4 Die Umbenennung . . . . . . . . . . . . . . . . .
4.3.5 Das Kreuzprodukt . . . . . . . . . . . . . . . . .
4.3.6 Verbundoperationen . . . . . . . . . . . . . . . .
4.3.6.1 Beispiel . . . . . . . . . . . . . . . . . .
4.3.6.2 Der natürliche Verbund . . . . . . . . .
4.3.6.3 Der Theta-Verbund . . . . . . . . . . .
4.3.6.4 Äußere Verbunde . . . . . . . . . . . .
4.3.7 Die Division . . . . . . . . . . . . . . . . . . . . .
4.3.8 Relationale Vollständigkeit . . . . . . . . . . . .
4.3.9 Ausdrücke in der relationalen Algebra . . . . . .
4.4 Schlüssel . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.4.1 Superschlüssel und Identifizierungsschlüssel . . .
4.4.2 Primärschlüssel . . . . . . . . . . . . . . . . . . .
4.4.3 Fremdschlüssel . . . . . . . . . . . . . . . . . . .
4.4.4 Kriterien für die Festlegung von IdentifizierungsPrimärschlüsseln . . . . . . . . . . . . . . . . . .
4.4.5 Weitere Schlüsselbegriffe . . . . . . . . . . . . . .
Glossar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
und
. . .
. . .
. . .
Lehrmodul 5: Der relationale Tupel-Kalkül
5.1
5.2
Die relationalen Kalküle . . .
Der relationale Tupel-Kalkül
5.2.1 Beispiel 1 (Selektion) .
5.2.2 Beispiel 2 (Projektion)
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
82
82
83
85
86
86
88
90
91
91
93
94
95
96
98
98
100
102
103
103
107
108
109
109
112
113
114
115
117
119
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
120
121
121
122
8
5.2.3 Beispiel 3 (Mengenoperationen) .
5.2.4 Beispiel 4 (natürlicher Verbund)
5.2.5 Beispiel 5 (Division) . . . . . . .
5.3 Syntax von Ausdrücken im RTK . . . .
5.4 Sichere RTK-Ausdrücke . . . . . . . . .
Glossar . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Lehrmodul 6: Einführung in SQL
123
123
124
124
125
128
129
6.1
6.2
Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Abfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.2.1 Grundform . . . . . . . . . . . . . . . . . . . . . . . .
6.2.2 Nachbildung der Operationen der relationalen Algebra
in SQL . . . . . . . . . . . . . . . . . . . . . . . . . .
6.2.3 Gruppierungen und Aggregationen . . . . . . . . . . .
6.3 Änderungsoperationen . . . . . . . . . . . . . . . . . . . . . .
6.3.1 Erzeugen von Tupeln . . . . . . . . . . . . . . . . . . .
6.3.2 Löschen von Tupeln . . . . . . . . . . . . . . . . . . .
6.3.3 Ändern von Tupeln . . . . . . . . . . . . . . . . . . . .
6.4 Nullwerte . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.5 Schema-Operationen . . . . . . . . . . . . . . . . . . . . . . .
6.5.1 Definition von Relationen . . . . . . . . . . . . . . . .
6.5.1.1 Attributdefinitionen . . . . . . . . . . . . . .
6.5.1.2 Definition von Integritätsbedingungen . . . .
6.5.2 Änderung der Definition einer Relation . . . . . . . .
6.5.3 Sichten . . . . . . . . . . . . . . . . . . . . . . . . . .
Glossar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
130
131
131
133
137
141
141
142
144
144
146
147
147
148
151
152
152
Lehrmodul 7: Implementierung relationaler Operationen
154
7.1
7.2
7.3
Einleitung . . . . . . . . . . . . . . . . .
Triviale Implementierungen . . . . . . .
Exkurs: Indexstrukturen . . . . . . . . .
7.3.1 Primärindexe . . . . . . . . . . .
7.3.2 Sekundärindexe . . . . . . . . . .
7.4 Optimierungen der Selektion . . . . . .
7.5 Optimierungen der Projektion . . . . . .
7.6 Optimierungen der Verbundberechnung
Glossar . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
155
155
157
157
159
160
163
163
167
(gen: 2013-12-9-600)
9
Lehrmodul 8: Abfrageverarbeitung und Optimierung169
8.1
Motivation . . . . . . . . . . . . . . . . . . .
8.1.1 Grobablauf einer Abfrageverarbeitung
8.1.2 Optimierungsansätze . . . . . . . . . .
8.2 Optimierungskriterien . . . . . . . . . . . . .
8.3 Algebraische Optimierung . . . . . . . . . . .
8.3.1 Äquivalente algebraische Ausdrücke .
8.3.2 Optimierungsheuristiken . . . . . . . .
8.3.3 Optimierungsalgorithmen . . . . . . .
8.4 Kostenschätzung . . . . . . . . . . . . . . . .
Glossar . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Lehrmodul 9: Metadaten
9.1
9.2
9.3
9.4
9.5
Einordnung und Motivation . . . . . . . . . . . . . . . . . . .
9.1.1 Metadaten in Datenbanken . . . . . . . . . . . . . . .
9.1.2 Metadaten in der Dokumentverwaltung . . . . . . . .
9.1.3 Metadaten vs. Nutzdaten . . . . . . . . . . . . . . . .
9.1.4 Selbstreferentialität . . . . . . . . . . . . . . . . . . .
9.1.5 Sprachebenen in der Linguistik . . . . . . . . . . . . .
Arten von Metadaten . . . . . . . . . . . . . . . . . . . . . .
9.2.1 Typbezogene vs. entitätsbezogene Metadaten . . . . .
9.2.2 Instantiierbare Metadaten . . . . . . . . . . . . . . . .
Selbstreferentialität in relationalen Datenbanken . . . . . . .
9.3.1 Repräsentation relationaler Schemata durch Tabellen .
9.3.2 Zugriff auf selbstreferentiell repräsentierte Schemata .
9.3.3 Metatypen und Meta-Metadaten . . . . . . . . . . . .
9.3.4 Übersicht über die semantischen Ebenen . . . . . . . .
9.3.5 Meta-Ebenen vs. Implementierungsebenen von Datenbankobjekten . . . . . . . . . . . . . . . . . . . . . . .
Selbstreferentialität in XML . . . . . . . . . . . . . . . . . . .
9.4.1 Aufbau von XML-Dateien . . . . . . . . . . . . . . . .
9.4.2 Typ-Annotationen . . . . . . . . . . . . . . . . . . . .
9.4.2.1 Typ-Annotationen in schwach strukturierten
Daten . . . . . . . . . . . . . . . . . . . . . .
9.4.2.2 Typ-Annotationen in strikt typisierten Nutzdaten . . . . . . . . . . . . . . . . . . . . . .
Metadaten in der UML-Begriffswelt . . . . . . . . . . . . . .
9.5.1 Bedeutungsebenen von UML-Modellen . . . . . . . . .
9.5.2 “ist-Instanz-von”-Beziehungen . . . . . . . . . . . . .
170
170
171
174
175
175
179
181
183
187
188
189
190
191
192
193
194
195
195
196
199
199
201
202
204
206
208
208
209
209
210
212
212
216
10
9.5.2.1 Interpretation der UML-Modelle der Ebene M1217
9.5.2.2 Interpretation der UML-Modelle der Ebene M2218
Glossar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
Lehrmodul 10: Entwurf redundanzfreier Datenbankschemata
220
10.1 Einleitung und Einordnung . . . . . . . . . . . . . . . . . . . 221
10.2 Fehler beim Entwurf relationaler Datenbankschemata . . . . 222
10.2.1 Zu viele Attribute in einem Relationentyp . . . . . . . 222
10.2.2 Zu “kleine” Relationentypen . . . . . . . . . . . . . . 224
10.2.3 Verlustfreie Zerlegungen . . . . . . . . . . . . . . . . . 226
10.3 Funktionale Abhängigkeiten . . . . . . . . . . . . . . . . . . . 227
10.3.1 Beispiel und Definition . . . . . . . . . . . . . . . . . . 227
10.3.1.1 Beispiel für die Analyse einer Tabelle . . . . 229
10.3.1.2 Identifizierungs- und Superschlüssel . . . . . 230
10.3.2 Funktionale Abhängigkeiten als Integritätsbedingungen 230
10.3.3 Verlustfreie Zerlegungen . . . . . . . . . . . . . . . . . 231
10.3.4 Die Armstrong-Axiome . . . . . . . . . . . . . . . . . 232
10.3.5 Die transitive Hülle einer Menge funktionaler
Abhängigkeiten . . . . . . . . . . . . . . . . . . . . . . 235
10.3.6 Kanonische Überdeckung von funktionalen Abhängigkeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
10.4 Das Boyce-Codd-Kriterium . . . . . . . . . . . . . . . . . . . 241
10.4.1 Definition . . . . . . . . . . . . . . . . . . . . . . . . . 241
10.4.2 Boyce-Codd-Zerlegungen . . . . . . . . . . . . . . . . 243
10.5 Lokale Überwachbarkeit . . . . . . . . . . . . . . . . . . . . . 246
10.5.1 Motivation und Definition . . . . . . . . . . . . . . . . 246
10.5.2 Beispiel: Postleitzahlenbuch . . . . . . . . . . . . . . . 247
10.6 Die dritte Normalform . . . . . . . . . . . . . . . . . . . . . . 251
10.6.1 Motivation und Definition . . . . . . . . . . . . . . . . 251
10.6.2 Konstruktion einer Zerlegung in dritter Normalform . 252
10.7 Überwachung funktionaler Abhängigkeiten . . . . . . . . . . . 257
10.8 Weitere Normalformen . . . . . . . . . . . . . . . . . . . . . . 258
10.8.1 Die erste Normalform . . . . . . . . . . . . . . . . . . 258
10.8.2 Die zweite Normalform . . . . . . . . . . . . . . . . . 261
10.8.3 Mehrwertige Abhängigkeiten und die vierte Normalform 261
Glossar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
Literatur
269
(gen: 2013-12-9-600)
Index
11
270
Vorwort
Dieses Buch ist im Kontext verschiedener Vorlesungen über Informations- bzw. Datenbanksysteme entstanden, die ich in den letzten Jahren am Fachbereich Elektrotechnik und Informatik der Universität
Siegen angeboten habe. Die Vorlesungen sind Komponenten der Studiengänge Technische Informatik, Wirtschaftsinformatik, Angewandte Informatik sowie diverser Nebenfachinformatiken. Bei diesen Studiengängen handelt es sich meist um integrierte Studiengänge, die sowohl einen Abschluß nach 7 Semestern (vergleichbar mit dem Bachelor) als auch nach 9 Semestern ermöglichen.
In den letzten Jahren wurden die Studiengänge erheblich umstrukturiert oder neu entworfen. Die frühere Vorlesung “Informationssysteme”, die einen Umfang von 4 SWS zzgl. Übungen hatte, die Teil
des Hauptstudiums war und die in dieser Form auch in vielen anderen Informatik-Studiengängen anzutreffen ist, wurde abgeschafft. Sie
wurde ersetzt durch
1. das Kernfach “Datenbanksysteme I”, das von fast allen InformatikStudenten besucht wird, und
2. darauf aufbauende speziellere, aus Katalogen wählbare Vorlesungen, die von wesentlich weniger Studenten besucht werden.
Kernfächer haben einen Umfang von 2 SWS zzgl. 1 SWS Übungen und
decken zentrale, praxisrelevante Bereiche vor allem der praktischen Informatik in einer einführenden, kompakten Darstellung ab [Ke00]. Das
vorliegende Buch ist am Denkmodell des Kernfachs orientiert und unterscheidet sich in zwei Merkmalen deutlich von üblichen Lehrbüchern
Stand: 01.12.2013
c
2013
Udo Kelter
Vorwort
13
über Datenbanksysteme (DBS), die sich am Denkmodell der 4-SWSVorlesung im Hauptstudium orientieren:
Stoffumfang: Mit rund 270 Seiten ist es wesentlich weniger umfangreich als übliche DBS-Lehrbücher, die meist zwischen 600 und 1000
Seiten Umfang und teilweise enzyklopädischen Charakter haben.
Derartige Lehrbücher sind für Kernfächer wenig geeignet: das Herausfiltern der Teilmenge des Stoffs, der als prüfungsrelevant definiert wird, ist nicht trivial, denn jedes einzelne Thema wird in
solchen umfangreichen Werken von vorneherein vertiefter angelegt
und behandelt werden als in einer kompakten Darstellung.
Während bei umfangreichen Werken - wenn überhaupt - die
Möglichkeit besteht, Teilmengen zu bilden, verfolgt das vorliegende
Buch genau den umgekehrten Ansatz: es definiert eine Stoffmenge,
die der Autor als grundlegend ansieht. Dieser Kern kann dann flexibel um Ergänzungsbände bzw. noch feingranularer um einzelne
Lehrmodule erweitert werden; Details hierzu s. unten.
Phase des Studiums: Während konventionelle DBS-Lehrbücher eher
für das Hauptstudium konzipiert sind, geht das vorliegende Buch
von der Annahme aus, daß das Kernfach “Datenbanksysteme I” im
3. Semester besucht wird.
Die theoretischen Vorkenntnisse und praktischen Erfahrungen
der Hörer sind somit signifikant schlechter als bei Hörern im Hauptstudium. Daher werden in diesem Buch formale Darstellungsformen
und Themen, die entsprechende Erfahrung erfordern, ausgespart,
soweit dies dem präzisen Verständnis nicht abträglich ist.
Stoffumfangsbegrenzung. Unterstellt wird, wie schon erwähnt, eine Vorlesung im Umfang von 2 SWS Vorlesung, die im Wintersemester
stattfindet. Der Stoffumfang ist daher auf 15 Vorlesungstermine eingestellt.
Das Thema Datenbanksysteme ist sehr umfangreich. Das Problem ist nicht, für eine Vorlesung genügend Stoff zu finden, sondern
im Gegenteil den prüfungsrelevanten Stoff auf ein realistisches Maß
einzugrenzen. Als Richtschnur dient hier die Stoffmenge, die man
14
Vorwort
bei einem klassischen Vortrag mit stichpunktartigen Tafelanschrieben
schafft. Alle in diesem Buch vorliegenden Texte sind schriftliche Varianten solcher Vorträge, es wurde natürlich anders formuliert, es wurden aber keine Ergänzungen oder sonstiger Stoff hinzugefügt, der letztlich zusätzlich zu lernen ist. Unter diesen Bedingungen ergibt sich mit
relativ hoher Genauigkeit ein Text von etwa 3300 Worten für einen
Vorlesungstermin von 90 Minuten (eine “Vorlesungsdoppelstunde”),
bei kniffligen Themen etwas weniger Text, bei einfachen etwas mehr.
Die 3300 Worte entsprechen bei der vorliegenden Formatierung etwa
16 Seiten. In diesem Sinne ist das Buch “umfangskontrolliert”.
Frühere Umfragen haben ergeben, daß man für eine erste Lektüre,
bei der man sich Notizen macht oder kleinere Selbsttests durchführt,
ca. 60 - 90 Minuten Zeit für 16 Seiten Text benötigt, für das Nachlesen
nach dem Vortrag etwa die Hälfte davon.
Stoffauswahl. Allgemeines Ziel der Vorlesung ist, die wesentlichsten konzeptionellen und technologischen Grundlagen zu vermitteln,
die für die Realisierung von datenbankbasierten Informationssystemen
benötigt werden, wobei der Schwerpunkt auf Abfragesprachen und den
Schemaentwurf gelegt wird. Der Inhalt dieses Buchs kann dementsprechend in folgende Blöcke eingeteilt werden:
1. eine allgemeine und einführende Darstellung der Probleme bei der
persistenten Verwaltung von Daten und eine Übersicht über die
wichtigsten Klassen von Datenverwaltungssystemen
2. eine Einführung in die Architektur von Datenbankmanagementsystemen (incl. der Vorstellung von B-Bäumen)
3. das relationale Datenbankmodell: seine Grundlagen und mehrere Abfragesprachen (relationale Algebra, relationaler Tupelkalkül,
SQL); vorgestellt wird nur die Kernfunktionalität der Sprachen,
wobei ein Überblick über die verschiedenen Sprachstile gewonnen
werden soll
4. Grundbegriffe der Optimierung
5. Entwurf von Datenbankschemata: die wichtigsten Normalformen
Vorwort
15
6. Grundbegriffe im Bereich Transaktionen, Concurrency Control und
Recovery
Kein Lernziel dieses Buchs sind die Installation, Administration
oder Tuning von konkreten DVS-Produkten, eine komplette Behandlung der Sprache SQL, die Modellierung von Daten mit ER- oder Klassendiagrammen; viele dieser Themen werden in aufbauenden Veranstaltungen bzw. Lehrmodulen behandelt werden (s.u.).
Zur Struktur dieses Buchs. Dieses Buch besteht im Gegensatz zu
anderen Bücher nicht aus Kapiteln, sondern aus Lehrmodulen. Jedes
Lehrmodul ist auch als selbständiger Text im WWW ausgehend von
http://pi.informatik.uni-siegen.de oder http://www.kltr.de
erreichbar. Motiviert wurde seinerzeit das Konzept der Lehrmodule dadurch, daß immer wieder Teile des Lehrstoffs gezielt benötigt
wurden (z.B. zur kurzfristigen Einarbeitung von Studentischen Hilfskräften oder Diplomanden) und daß bei spezielleren Themen häufig
zusätzliche Texte oder neue Versionen der Texte verfügbar waren.
Im Unterschied zu den Kapiteln eines Buchs sind Lehrmodule möglichst autark gestaltet. Durchgehende Beispiele oder häufige Verweise
auf andere Kapitel, auf die man in “normalen” Büchern besonders
stolz ist, werden hier ganz bewußt vermieden, weil sie Abhängigkeiten
erzeugen und das separate Lesen einzelner Kapitel erschweren. Wenn
ohne allzuviel Redundanz möglich, wird statt eines Verweises auf andere Stellen der Lerngegenstand, auf den Bezug genommen wird, direkt
dargestellt, ggf. in skizzenhafter Form.
Während ein Buch fast immer sequentiell gelesen wird, ist die Lesereihenfolge der Lehrmodule wesentlich freier. Der Graph in Bild 1
zeigt die relativ wenigen noch vorhandenen Reihenfolgerestriktionen.
Ein gepunkteter Pfeil stellt nur eine Empfehlung dar. Die Abkürzungen bedeuten folgendes:
DVS
DBIF
DBSA
BB
Datenverwaltungssysteme
Schnittstellen zu Datenbankinhalten
Architektur von DBMS
B-Bäume
16
Vorwort
DVS
DBIF
DBSA
BB
RDBM
RTK
IRO
TID
SQL1
ERS
AVO
Abbildung 1: Lesereihenfolge der Lehrmodule
RDBM
RTK
SQL1
IRO
AVO
ERS
TID
Das relationale Datenbankmodell
Der relationale Tupel-Kalkül
Einführung in SQL
Implementierung relationaler Operationen
Abfrageverarbeitung und Optimierung
Entwurf redundanzfreier Datenbankschemata
Transaktionen und die Integrität von Datenbanken
Ergänzendes Material. In einigen Fällen ist zu den Lehrmodulen
ergänzendes Material erhältlich, z.B. Formulare, Software etc. Das
Material ist unter den o.g. URLs im WWW frei verfügbar.
Vortragsfolien. Für die meisten Lehrmodule sind Vortragsfolien in
Form von PostScript-Dateien auf Anfrage für Lehrende frei verfügbar.
Die Folien sind nicht über die WWW-Seiten abrufbar.
Begleitende Übungen. Es wird dringend empfohlen, den zunächst
im Buch und/oder in der Vorlesung erlernten Stoff in Übungsaufgaben anzuwenden und so zu festigen. Dies gilt ganz besonders für die
hier vorgestellten Datenbankabfragesprachen (insb. SQL). Übungsaufgaben und eine SQL-Übungsdatenbank sind ebenfalls im WWW
ausgehend von den o.g. Adressen erreichbar.
Vorwort
17
Dank. Danken möchte ich den Lesern früherer Versionen dieser Texte für die vielen Hinweise auf Fehler und Verbesserungsmöglichkeiten.
Kommentare und Fehlermeldungen. Kein langer Text ist fehlerfrei, so auch dieser. Hinzu kommt, daß sich manche Gebiete der
Informatik immer noch so rasch weiterentwickeln, daß auch Lehrtexte
schnell eine störende “Patina” bekommen können. Daher sind Hinweise auf Fehler und Verbesserungsmöglichkeiten sowie Kommentare aller Art sehr willkommen (am besten elektronisch an [email protected]).
Aufbauende und ergänzende Lehrmaterialien. Auf die Vorlesung Datenbanksysteme I bauen die Vorlesungen Datenbanksysteme II
und weitere Spezialvorlesungen auf. Themenschwerpunkte darin sind:
– objektorientierte Datenbanken
– XML und XML-basierte Datenbanken bzw. Abfragesprachen
– WWW-Schnittstellen zu Datenbanken und die dahinterstehenden
Server-Architekturen, inkl. Applikationsserver
– Transaktionen, Concurrency Control und Recovery
Zu allen vorstehenden Themen sind Lehrmodule im WWW ausgehend
von den o.g. Adressen erhältlich.
Nicht behandelt in der Vorlesung Datenbanksysteme I und den vorstehend genannten aufbauenden Vorlesungen wird die datenorientierte
Anforderungsanalyse anhand von Entity-Relationship- oder Klassendiagrammen. Dieses Themengebiet wurde aufgrund mehrerer Gründe
komplett der parallel angebotenen Vorlesung Softwaretechnik I bzw.
den dazu gehörigen Buch zugeordnet:
– Die Anforderungsanalyse umfaßt viele Aspekte – Daten, Funktionen, Zustände, Bedienschnittstellen usw. –, und diese sind integriert
zu betrachten.
– Die Datenmodellierung ist unabhängig davon sinnvoll und einsetzbar, ob es sich um Daten in einem Datenbanksystem, Dateisystem,
18
Vorwort
irgendeinem anderen Datenverwaltungssystem oder sogar um transiente, also nur im Hauptspeicher vorhandene Daten handelt.
– Thema der Vorlesung sind Datenbanksysteme und nicht Informationssysteme. Datenbank[management]systeme sind eine Komponente in der Gesamtarchitektur eines Informationssystems, die Standardoperationen zum Speichern und Durchsuchen von Daten anbietet.
Datenmodellierungssprachen für die Anforderungsanalyse (insb.
die ER-Notationen oder UML-Notationen für Analyseklassendiagramme) haben zwar viele begriffliche Berührungspunkte mit Datenbankmodellen, sind aber prinzipiell etwas anderes, denn sie beinhalten überhaupt keine operationalen Schnittstellen (also Standardoperationen). Von derartigen Details soll während der Anforderungsanalyse gerade abstrahiert werden. Umgekehrt sind die Standardoperationen und deren exakte Semantik der wichtigste Aspekt
eines Datenbankmodells.
Für ein und dieselbe Datenmodellierungssprache können die Details zugehöriger Standardoperationen kraß verschieden ausgestaltet werden. Illustrieren kann man dies daran, daß z.B. auf Basis der Grundkonzepte der ER-Modellierung sowohl navigierende
Datenbankmodelle als auch mengenorientierte Datenbankmodelle
(ähnlich wie das relationale Modell) definiert wurden.
Nichtsdestotrotz sind gute Kenntnisse in der Datenmodellierung
für jeden, der Informationssysteme entwickelt, absolut unerläßlich. Sofern also nicht ohnehin irgendeine komplette Vorlesung über Softwaretechnik (z.B. das parallel angebotene Kernfach Softwaretechnik I)
besucht wird, sollten wenigstens Grundkenntnisse in der Datenmodellierung erworben werden. Hierfür sind die Lehrmodule [SASM],
[DMER] und [TAE] aus der Vorlesung Softwaretechnik I geeignet.
Lehrmodul 1:
Datenverwaltungssysteme
Zusammenfassung dieses Lehrmoduls
Drei wichtige Arten von Datenverwaltungssystemen sind Dateisysteme, Datenbankmanagementsysteme zur Transaktionsverarbeitung
(OLTP-Systeme) und Information-Retrieval-Systeme. Dieses Lehrmodul listet die wichtigsten Datenverarbeitungsaufgaben auf und
vergleicht die Fähigkeiten der einzelnen Systeme in den jeweiligen
Aufgabenbereichen. Einleitend werden grundlegende Begriffe wie
Information, Wissen und Daten definiert. Abschließend gehen wir
noch auf die softwaretechnische Frage ein, inwieweit die Datenverwaltungssysteme die Konstruktion von Ein- und Ausgabeschnittstellen
unterstützen.
Vorausgesetzte Lehrmodule:
keine
Stoffumfang in Vorlesungsdoppelstunden:
c
2005
Udo Kelter
2.2
Stand: 17.10.2005
20
1.1
Datenverwaltungssysteme
Einleitung und Übersicht
Dieses Lehrmodul betrachtet das Problem der Datenverwaltung aus
einer sehr allgemeinen Perspektive. Ziel ist es, eine Übersicht über
die wesentlichen Alternativen, wie Daten persistent gespeichert werden können, zu geben und die Vor- und Nachteile dieser Alternativen
zu vergleichen. Aus Platzgründen können nur die wichtigsten Klassen
von Datenverwaltungssystemen (DVS) skizziert werden. Wir beschreiben in Abschnitt 1.3 zunächst eine Reihe von Einzelproblemen, die bei
der Verwaltung von Daten auftreten und die für die Bewertung und
Einschätzung einzelner DVS heranzuziehen sind. In den folgenden Abschnitten 1.4 bis 1.6 werden die wichtigsten Datenverwaltungssysteme
skizziert. Einleitend werden in Abschnitt 1.2 die zentralen Begriffe
Daten, Wissen und Information eingeführt.
1.2
1.2.1
Grundbegriffe
Daten – Wissen – Information
Information ist der zentrale Begriff der Informatik – dementsprechend
vielschichtig ist er, und deshalb wird er meist nicht exakt definiert. Die
unterschiedlichen Definitionen sind nicht alle konsistent zueinander.
Da wir hier die Themen “Informations”systeme und “Daten”banken
behandeln wollen, kommen wir aber nicht umhin, diese Begriffe wenigstens für diesen Kontext festzulegen; wir brauchen daher auch nicht
den Anspruch aufzustellen, alle Aspekte z.B. des Begriffs Information
abzudecken.
Wir beginnen mit dem Begriff Daten. Die folgende Zeichenfolge
ist ein Beispiel eines Datums:
2000
Dargestellt ist hier offensichtlich eine Zahl, nämlich 2000. Genauer
gesagt sieht man hier auf dem Bildschirm oder einem Blatt Papier die
externe Darstellung einer Zahl. Intern in einem Rechner könnte unsere Zahl binär in einem Speicherwort gespeichert sein oder als Text
Datenverwaltungssysteme
21
oder vielleicht auf noch andere Weise; diese Aspekte werden durch die
“Syntax”, der unser Datum unterliegt, festgelegt. Unter Syntax versteht man Regeln, die für ein zugrundeliegendes Alphabet bestimmen,
welche Zeichenfolgen, also Texte, als korrekt geformt anzusehen sind.
Wir verallgemeinern den Begriff Syntax dahingehend, daß wir nicht
nur Zeichen eines Alphabets, sondern genereller Inhalte von Speicherzellen irgendeines Speichermediums zulassen.
Unsere Zahl 2000 ist zwar syntaktisch korrekt, aber sie sagt als solche nichts aus. Es könnte eine Jahreszahl sein oder eine Gewichtsangabe oder eine Benutzernummer. Offensichtlich benötigen wir immer
einen Kontext, um ein Datum zu interpretieren, also seine Bedeutung erkennen zu können. Neben der Syntax benötigen wir somit eine
Semantik, die bestimmt, wie (syntaktisch korrekte) Texte zu interpretieren sind. Durch die Semantik wird aus einem Datum (Fakten-)
Wissen. In unserem Beispiel könnte uns das Datum 2000 zu dem
Wissen verhelfen, daß Speichermodule des Typs X eine Kapazität von
2000 MB haben. Kompliziertere Sachverhalte müssen durch mehrere Daten repräsentiert werden, die dann gemeinsam zu interpretieren
sind.
Die nächste Frage ist, ob uns das Wissen über bestimmte Sachverhalte überhaupt interessiert bzw. uns etwas nützt. Vielleicht ist es
mir völlig egal, daß Platten des Typs X eine Kapazität von 2000 MB
haben, weil ich schon ausreichend große Platten in meinem Rechner
habe und jetzt keine Platten mehr kaufe. Für jemand anders könnte
dieses Wissen hingegen eine wichtige Information sein, weil ein anderer Rechner umkonfiguriert werden soll. Umgangssprachlich1 versteht
man unter Information Wissen (oder einen Zugewinn an Wissen),
das nutzbar ist und ggf. einen Effekt hat, z.B. dahingehend, daß jemand seine politische Meinung ändert oder sich neue Speichermodule
kauft oder nach Südfrankreich verreist. Ob ein bestimmtes Wissen
auch Information ist, ist offenbar nur subjektiv entscheidbar.
Wir haben bisher den Weg vom Datum über das Wissen zur Infor1
Beispielsweise in Sätzen wie “Ich brauche Informationen über die Firma XY”
oder “Er ist gut informiert”.
22
Datenverwaltungssysteme
mation beschrieben. Daten entstehen auf dem umgekehrten Weg: Man
hat Informationen in einem bestimmten Interessengebiet. Für dieses
Interessengebiet (auch als Weltausschnitt oder universe of discourse
bezeichnet) muß zunächst im Rahmen einer semantischen Modellierung eine geeignete Syntax und Semantik entwickelt werden, so daß
anschließend Wissen in diesem Weltausschnitt durch Daten repräsentiert werden kann.
Wie Informationen durch Faktenwissen zu repräsentieren sind, ist
oft ganz offensichtlich. Die Kapazität einer Festplatte kann man hinreichend gut durch eine einzige Zahl ausdrücken. Schwieriger ist es, eine
Syntax und Semantik zu finden, in der man ausdrücken kann, daß sich
die Festplatte mit diesem oder jenem Plattencontroller nicht verträgt,
vor allem, wenn noch ein CD-ROM am gleichen Bus angeschlossen ist,
und dies speziell dann, wenn die Gehäuse-Innentemperatur über 34
Grad Celsius liegt. Bei solchen komplexen Sachverhalten ist das Ergebnis einer semantischen Modellierung keineswegs eindeutig, und je
nach der gewählten Syntax und Semantik kann es sein, daß bestimmte Details der Ausgangsinformation gar nicht mehr oder nur mit viel
Aufwand aus den vorhandenen Daten rekonstruierbar sind. Dies gilt
ganz besonders dann, wenn freier umgangssprachlicher Text verwendet
wird.
1.2.2
Informationssysteme
Wir haben Daten bisher verstanden als interne Speicherstrukturen.
Damit ein Benutzer die Daten kennenlernen, also zu Wissen umformen kann, müssen sie auf einem Bildschirm angezeigt oder auf Papier
gedruckt oder in eine sonstige geeignete externe Darstellung überführt
werden; vorher muß man natürlich Daten eingeben können.
Unter einem Informationssystem verstehen wir ganz allgemein
ein (Software-) System, durch das Daten erfaßt, angezeigt, weitergegeben, durchsucht und ausgewertet werden können. Typischerweise
handelt es sich um umfangreiche Datenbestände.
Für Informationssysteme ist die in Bild 1.1 gezeigte 3-SchichtenArchitektur als Grobarchitektur zu empfehlen. Diese reflektiert die
Datenverwaltungssysteme
23
(G)UI-Schicht
Batch-Applikationen
Fachkonzeptschicht
Datenhaltungsschicht
Abbildung 1.1: 3-Schichten-Architektur von Informationssystemen
drei Hauptaufgaben, die ein Informationssystem bewältigt:
– Speicherung von Daten
– anwendungsbezogene Verarbeitungsfunktionen
– Interaktion mit den Benutzern über graphische oder textuelle
Schnittstellen oder alternativ nichtinteraktive Stapeljobs.
1.2.3
Externe Darstellung von Daten
Ein bestimmtes Datum, das in der Datenhaltungsschicht existiert,
kann i.a. auf dem Bildschirm oder auf Papier unterschiedlich dargestellt werden. Eine ganze Zahl kann bspw. als Dual-, Oktal-, Dezimaloder Hexadezimalzahl dargestellt werden. Eine Fließkommazahl könnte gerundet dargestellt sein.
Nicht nur elementare Datenelemente, auch komplette Strukturen
können alternative Darstellungen besitzen. Als Beispiel betrachten wir
einen Familienstammbaum. Dieser enthält Daten über Eltern-KindBeziehungen von mehreren Personen. Diese Daten kann man in einer
Tabelle darstellen, die zu jeder Person die Mutter und den Vater angibt. Alternativ könnte man die Daten als Graph darstellen, wobei die
Personen die Knoten des Graphen bilden. Wir nehmen jetzt einmal
an, daß die Anordnung der Knoten auf einer Fläche (also die Koordinaten) vom Benutzer bestimmbar sind. Dann stellen diese Koordinaten
ebenfalls Daten dar, die allerdings keine inhaltliche Bedeutung haben:
24
Datenverwaltungssysteme
die graphische Anordnung der Knoten mag zwar die Übersichtlichkeit
erhöhen, “inhaltlich” ändert sich dadurch aber nichts. Die Koordinaten und ähnliche Daten nennt man auch Layout-Daten.
Manchmal gibt es nur eine naheliegende externe Darstellung. Diese Darstellung kann ggf. dynamisch geändert werden: beispielsweise
könnte es möglich sein, bei der Anzeige von Fließkommazahlen zu
wählen zwischen einer Darstellung mit 8 Stellen hinter dem Komma
oder einer gerundeten Darstellung als ganze Zahl und zwischen einer Darstellung als Oktal-, Dezimal- oder Hexadezimalzahl. Derartige
Darstellungsvarianten werden typischerweise durch Steuerparameter
des Anzeigewerkzeugs gesteuert; diese Steuerparameter werden nicht
als Teil der eigentlichen Daten angesehen.
1.2.4
Datenverwaltungssysteme
Die bisherigen Überlegungen waren unabhängig davon, wie umfangreich die Datenmengen sind und welche Lebensdauer die Daten haben.
Bei fast allen Anwendungsprogrammen müssen größere Datenmengen
langfristig gespeichert werden. Wenn die Datenmengen größer werden,
reicht irgendwann der Hauptspeicher nicht mehr aus, und es muß auf
externe Medien, heute praktisch immer Magnetplatten, ausgewichen
werden. Die langfristige Speicherung erfordert den Einsatz persistenter Speichermedien, was ebenfalls auf Magnetplatten oder sog. tertiäre
Speichermedien hinausläuft.
Durch den Einsatz persistenter Speichermedien entstehen andere
Randbedingungen als bei einer Speicherung im Hauptspeicher, ferner
entstehen durch die Merkmale der persistenten Speichermedien eigene neue Probleme. Daher ist es sinnvoll, eigene Systeme zu schaffen, mit deren Hilfe große Datenbestände persistent gespeichert werden können; solche Systemen nennen wir Datenverwaltungssysteme (DVS).
DVS bestehen überwiegend aus Komponenten, die in der 3Schichten-Architektur, die in Bild 1.1 gezeigt ist, der Datenhaltungsschicht zuzuordnen sind.
Es gibt sehr unterschiedliche Arten von Datenverwaltungssyste-
Datenverwaltungssysteme
25
men. Die bekanntesten Datenverwaltungssysteme sind Dateisysteme.
Sie sind praktisch auf jedem Rechner vorhanden, weil bereits das Betriebssystem selbst für den Eigenbedarf Daten persistent speichern
muß.
Welches DVS in einer gegebenen Problemstellung eingesetzt werden soll, ist in der softwaretechnischen Denkwelt des Phasenmodells
eine Frage, die in der Analyse- oder Entwurfsphase zu entscheiden ist.
Für die Auswahl eines DVS sind die relevanten Anforderungen festzustellen, und die verfügbaren DVS sind anhand dieser Anforderungen
zu bewerten. Ziel dieses Lehrmoduls ist es daher, eine Übersicht über
die wichtigsten Arten von Datenverwaltungssystemen zu geben und
ihre Fähigkeiten und Einsatzbereiche zu beschreiben. Konkret werden
wir drei Arten von Systemen etwas näher betrachten:
– Dateisysteme
– OLTP- (on-line transaction processing) Datenbankmanagementsysteme (DBMS)2 ; hierunter fallen objektorientierte und
konventionelle, insb. relationale DBMS. OLTP-Systeme dienen dazu, die betrieblichen Daten von Unternehmen, z.B. Konten, Verkäufe, Buchungen usw., zu verwalten. Diese Daten werden durch
Transaktionen ständig ergänzt oder modifiziert. OLTP-Systeme
müssen sehr hohe Anforderungen hinsichtlich Verfügbarkeit, Datensicherung, Performanz, parallelem Zugriff, Zugriffskontrollen u.a.
erfüllen.
– IR- (information retrieval) Systeme; typische Beispiele hierfür
sind Auskunftssysteme für Bibliotheksbestände, Fahrpläne, Produktkataloge usw. IR-Systeme haben oft einen statischen Datenbestand (z.B. auf einer CD-ROM gespeichert).
Die Abgrenzung zwischen OLTP-Systemen und IR-Systemen ist
nicht scharf, ferner gibt es viele Unterarten von OLTP-Systemen und
IR-Systemen, u.a.
– XML-DBMS,
2
Diese Systeme werden oft einfach als DBMS bezeichnet; wie wir gleich sehen
werden, gibt es andere DBMS, die nicht zur Transaktionsverarbeitung gedacht oder
geeignet sind.
26
–
–
–
–
–
–
Datenverwaltungssysteme
Geo-DBMS,
deduktive DBMS,
Entwurfsdatenbanken, Projektdatenbanken, Repositories,
OLAP-Systeme, Decision-Support-Systeme,
Dokumentarchivierungssysteme
Multimedia-DBMS
usw. Diese Systeme unterscheiden sich oft hinsichtlich ihrer Leistungsmerkmale und internen Architektur erheblich von OLTP-DBMS, so
daß man sie als selbständige Typen von DVS ansehen kann. Die originäre Kernaufgabe eines DVS besteht darin, Daten abzulegen und
wiederaufzufinden; viele der genannten Systeme bieten Funktionen an,
die man eher als Auswertung und Aufbereitung bezeichnen könnte
und die man daher intuitiv eher der Fachkonzeptschicht (vgl. Bild 1.1)
oberhalb der reinen Datenverwaltung zuordnen würde. Eine solche
Trennung ist aber oft aus Performance-Gründen nicht praktikabel. Bei
den obengenannten Systemen sind daher für konkrete Anwendungsgebiete Teile des Fachkonzepts in der Datenhaltung integriert. Noch
einen Schritt weiter gehen sogenannte erweiterbare DBMS, bei denen über entsprechende Schnittstellen Teile der Applikation3 in den
Datenbankkern integriert werden können.
Für eine erste Begriffsbildung, die das Ziel dieses Lehrmoduls ist,
ist aber die Beschränkung auf die drei o.g. DVS-Typen sinnvoll.
Um begrifflich sauber zu bleiben, muß man eigentlich trennen zwischen dem Datenbestand und der Software, die den Datenbestand einkapselt (s. auch Bild 1.2). Unter einem DBMS versteht man das Softwaresystem, unter einer Datenbank den Datenbestand, unter einem
Datenbanksystem (DBS) das DBMS zusammen mit der Datenbank. Bei Dateisystemen wird hingegen nicht sauber zwischen beiden Begriffen getrennt. Die Bezeichnung Dateisystem wird sowohl für
3
Hinweis: In der Datenbankliteratur versteht man unter einer “Applikation” ein
Anwendungsprogramm, das ein DBMS benutzt. Dieser Begriff hat nichts zu tun
mit dem Begriff application (als Gegensatz zu applet) aus der Denkwelt von Java.
(Datenbank-) Applikationen sind häufig in COBOL, C und C++ geschrieben; erst
seit kurzem werden auch vermehrt Applikationen in Java geschrieben.
Datenverwaltungssysteme
27
“Dateiverwaltungssystem” verwendet als auch für den verwalteten Datenbestand, also z.B. den Inhalt einer Magnetplatte. Aus dem Kontext
wird meist klar, was gemeint ist.
Exkurs: Persistente Speichermedien. Zur persistenten Speicherung eines Datenbestands sind persistente Speichermedien erforderlich.
Die gängigsten Beispiele hierfür sind Magnetplatten, CD-ROMs und
Disketten. Im Gegensatz zum Arbeitsspeicher eines Rechners geht
der Inhalt persistenter Speichermedien beim Ausschalten des Systems
nicht verloren.
Durch die zu einem Speichermedium gehörige Hardware werden
zunächst sehr elementare Möglichkeiten vorgegeben, wie das Speichermedium formatiert werden kann und wie Daten auf das Speichermedium geschrieben (bei schreibbaren Medien) und gelesen werden können.
Typischerweise werden immer ganze Datenblöcke von z.B. 1 kB Größe
zwischen dem Medium und dem Arbeitsspeicher übertragen.
Anwendungsprogramm
Datenverwaltungssystem
Daten
Abbildung 1.2: Kapselung von Daten auf Speichermedien
Diese hardwarenahen Schnittstellen werden aber aus diversen
Gründen nicht für normale Anwendungsprogramme zugänglich gemacht, sondern analog zum information hiding bei Datenobjekten
durch ein DVS eingekapselt (s. Bild 1.2). Das DVS bietet somit bestimmte Datenverwaltungsdienste an. Technisch kann dies in Form
eines API oder einer graphischen Bedienschnittstelle oder auf noch
andere Art realisiert sein; diese Unterschiede sind hier nicht relevant.
Entscheidend ist vielmehr, welche Funktionen das DVS letztlich anbie-
28
Datenverwaltungssysteme
tet; hier liegen die wesentlichen Unterschiede zwischen den verschiedenen DVS.
Im Sinne der Einkapselung ist es auch unerheblich, ob ein DVS
A auf ein anderes DVS B aufbaut. Beispielsweise bauen viele DBMS
auf einem Dateisystem auf, während andere direkt auf die Hardwareschnittstellen aufsetzen, das Betriebssystem also umgehen. Größere
DBMS bieten sogar beide Optionen an.
Laufzeitkern und Dienstprogramme. Der Laufzeitkern eines
DVS realisiert die Schnittstelle, auf die die Anwendungen aufsetzen.
Technisch gesehen kann der Laufzeitkern z.B. aus einer Bindemodulbibliothek bestehen. Neben dem Laufzeitkern gehören zu einem DVS
immer auch Administrations- und Dienstprogramme, die eigene Bedienschnittstellen haben und insofern neben den Anwendungen stehen
(s. Bild 1.3). Beispiele sind Programme zur Benutzerverwaltung,
Systeminstallation, Systemüberwachung, Unterstützung der Anwendungsentwicklung und Performance-Optimierung.
Anwendungsprogramm
Dienstprogramme
Laufzeitkern
Daten
Abbildung 1.3: Laufzeitkern und Dienstprogramme eines DVS
1.3
Datenverwaltungsprobleme
Wie schon oben erwähnt kann die Auswahl eines DVS nur auf Anforderungen im Zusammenhang mit der Verwaltung von Daten basieren.
In diesem Abschnitt analysieren wir daher aus einer sehr allgemeinen
Datenverwaltungssysteme
29
Anschauung heraus derartige Anforderungen und bewerten die drei
oben genannten DVS-Typen schon einmal grob hinsichtlich dieser Anforderungen.
1.3.1
Anwendungsnahe Datenmodellierungskonzepte
Natürlich muß es möglich sein, die Daten einer Anwendung überhaupt
in das DVS und zurück zu übertragen. Diese Anforderung ist allerdings
recht unspezifisch, denn irgendwie kann man fast alle Daten in jedes
gegebene DVS übertragen. Beispielsweise könnte man den Text eines
Buchs zeilenweise mithilfe eines relationalen DBMS in einer Relation
speichern. Dies ist aber wenig sinnvoll, weil die Struktur des Buchs
so weitgehend verlorengeht. Bei einer derartigen Diskrepanz zwischen
der Struktur der Daten aus Anwendungssicht und der Struktur der
Daten im DVS spricht man auch von einer Fehlanpassung (impedance
mismatch). Beispiele für eine solche Diskrepanzen sind Arrays und
Zeiger, die z.B. in relationalen Datenbanken nicht unterstützt werden.
Ein n-dimensionales Array muß i.w. durch eine Tabelle mit n Spalten
für die Indexwerte und eine Spalte für den Wert des Array-Elements
nachgebildet werden. Wenn also a[4,5,6] = 999 ist, dann würde die
Tabelle das Tupel (4,5,6,999) enthalten.
Eine Fehlanpassung kann nicht nur aufgrund ungeeigneter Datenmodellierungskonzepte, sondern auch aufgrund ungünstig gestalteter
Programmschnittstellen auftreten. Eine Fehlanpassung führt dazu,
daß in den Applikationsprogrammen aufwendige Konversionen realisiert werden müssen, die zwischen der Darstellung der Daten im
Hauptspeicher und im DVS konvertieren.
Zu fordern ist also, daß das DVS eine möglichst einfache und direkte Nachbildung der Strukturen der konkreten Anwendung ermöglicht.
Dateisysteme sind in dieser Hinsicht oft ideal, weil man
in allen gängigen Programmiersprachen (insb. deren EinAusgabebibliotheken) Laufzeitobjekte direkt auf Dateien schreiben
bzw. von dort zurückladen kann4 . Problematisch ist nur die Rekon4
Besonders unterstützt wird dieser Ansatz durch das sogenannte MMIO (memory-mapped IO), das von allen modernen Betriebssystemen angeboten wird und
30
Datenverwaltungssysteme
struktion von Zeigern zwischen Datenobjekten. Weitere Probleme
werden unten diskutiert werden.
Objektorientierte OLTP-Systeme unterstützen ebenfalls persistente Laufzeitobjekte und verhalten sich damit ähnlich günstig wie Dateisysteme. OLTP-Systeme mit klassischen Datenbankmodellen (insb.
relationale Systeme) sind für übliche betriebliche Anwendungen, in
denen große Mengen gleichförmig strukturierter Daten anfallen, gut
geeignet, nicht gut hingegen bspw. für technische Anwendungen, in
denen sehr komplexe Datenstrukturen auftreten.
IR-Systeme sind hier wie relationale OLTP-Systeme anzusehen.
Eine Fehlanpassung ist kaum vermeidbar, wenn auf den gleichen
Daten mehrere Anwendungsprogramme arbeiten sollen, die in verschiedenen Sprachen geschrieben sind, und wenn diese Sprachen signifikant verschiedene Typbildungskonzepte haben.
1.3.2
Korrekheitsüberwachung
Die grundlegenden Möglichkeiten eines DVS zur Datenmodellierung
geben zunächst nur einen Rahmen vor. Dieser erzwingt immerhin ein
Mindestmaß an Korrektheit der Daten. Oft sind aber über einen rein
syntaktischen Rahmen hinausgehende Korrektheitskriterien einzuhalten. Beispielsweise sollte das Alter einer Person nicht irgendeine Zahl
sein, sondern eine Zahl zwischen 1 und ca. 100, für die Namensschreibweise kann eine Codiervorschrift vorliegen, daß der erste Vorname ausgeschrieben und alle folgenden durch ihre Initialen abgekürzt werden,
und in der Adresse sollte die Postleitzahl zum Ort passen.
Wenn in einer Personendatenbank ein Attribut Personennummer
vorhanden ist, wird man fordern, daß die Personennummern eindeutig sind, daß also zu jeder Personennummer höchstens eine Person
eingetragen ist. Das Attribut Personennummer ist somit geeignet, einzelne Datenelemente zu identifizieren, und wird daher als Identifizierungsschlüssel bezeichnet. Die Schlüsseleigenschaft ist immer dann
bei dem Dateiinhalte direkt in den (virtuellen) Hauptspeicher eines ausgeführten
Programms eingeblendet werden. Das MMIO wird typischerweise in Vorlesungen
über Betriebssysteme behandelt.
Datenverwaltungssysteme
31
gefährdet, wenn eine neue Person mit einer bestimmten Nummer eingetragen werden soll; es muß dann geprüft werden, ob diese Nummer
schon benutzt ist.
Die vorstehenden Korrektheitskriterien sind insofern statisch, als
sie jederzeit gelten sollen. Zusätzlich sind dynamische Kriterien denkbar. Beispielsweise kann eine Person vom Zustand verheiratet in den
Zustand geschieden oder verwitwet übergehen, nicht hingegen in den
Zustand ledig.
Dateisysteme unterstützen die Korrekheitsüberwachung überhaupt
nicht, IR-Systeme meist ebenfalls nicht. Nur OLTP-Systeme bieten
üblicherweise eine nennenswerte Unterstützung der Korrekheitsüberwachung. Komplexe Korrektheitskriterien müssen aber auch dort
durch die Applikation überwacht werden.
1.3.3
Such- und Auswertungsfunktionen
Unter Suchfunktionen verstehen wir Funktionen, die anhand bestimmter Kriterien einzelne Elemente des Datenbestands auffinden. Hierbei
muß klar getrennt werden zwischen zwei Arten, wie Suchkriterien zu
verstehen sind:
– Bei der exakten Suche wird die Menge der Datenelemente, die die
Suchkriterien exakt erfüllen, gewünscht. Wenn z.B. die Kunden mit
einem Jahresumsatz von über 100.000 DM einen Sonderrabatt von
1 % bekommen sollen, dann werden exakt diese Kunden gesucht,
sonst keine.
– Bei der vagen Suche weiß der Frager nicht genau, wonach er sucht;
man sucht z.B. nach irgendeinem Kunden, der in Bonn oder Umkreis wohnt und ca. 100.000 DM Umsatz gemacht hat. Ein Kunde
in Bonn mit 50.000 DM Umsatz wäre besser als einer in Köln mit
90.000 DM Umsatz.
Während die Treffermenge bei der exakten Suche keine relevante
Sortierung hat, erwartet man bei der vagen Suche für jeden Treffer
eine Schätzung der Relevanz, also der Wahrscheinlichkeit, ein passendes Element zu sein, und eine Sortierung der Treffermenge anhand
32
Datenverwaltungssysteme
dieser Wahrscheinlichkeiten. Bei der vagen Suche wird man Elemente, die knapp neben dem angegebenen Selektionskriterium liegen (z.B.
wenn sich die Schreibweise eines Namens nur geringfügig unterscheidet), trotzdem in die Treffermenge aufnehmen. IR-Systeme enthalten
meist sehr ausgefeilte Verfahren, mit denen “knapp danebenliegende”
Treffer gefunden und Treffer bewertet werden können.
Unter Auswertungsfunktionen – im Gegensatz zu Suchfunktionen
– verstehen wir Funktionen, die aus den originären Daten abgeleitete Daten liefern, von einfachen Zählungen und Aggregationen bis hin
zu anspruchsvollen mathematischen Analysen, Hochrechnungen und
ähnlichem.
OLTP-DBMS bieten primär die exakte Suche an, ferner einfache
Auswertungen. IR-Systeme unterstützen primär die vage Suche und
bieten keine Auswertungsfunktionen an. Dateisysteme bieten als solche überhaupt keine Such- oder Auswertungsfunktionen an; allerdings
können derartige Aufgaben oft durch Dienstprogramme, die zum Standardumfang des Betriebssystems gehören, gelöst werden (s.u. im Abschnitt 1.4).
Bei den Such- und Auswertungsfunktionen interessiert insbesondere, wieweit sie skalieren. Man sagt, daß eine Funktion skaliert, wenn
sie auf große Datenbestände anwendbar ist und dabei Laufzeiten und
sonstiger Ressourcenbedarf nicht überproportional ansteigen. Wir unterscheiden hierzu ganz grob drei Größenklassen von Datenbeständen:
klein: ca. 1 MB
mittel: ca. 1 GB
groß: ca. 1 TB (= 1024 GB)
Bei mittleren bis großen Datenbeständen lassen sich akzeptable Antwortzeiten der Suchfunktionen und mancher Auswertungsfunktionen nur durch den Einsatz von Indexen erreichen. Indexe werden
durch OLTP-DBMS und IR-Systeme unterstützt, nicht hingegen durch
Dateisysteme.
Datenverwaltungssysteme
1.3.4
33
Backup und Versionierung
Auch bei “persistenten” Speichermedien besteht die Gefahr von Datenverlusten. Ursachen können Gerätedefekte, Verlust oder Beschädigung von Datenträgern, absichtliche oder versehentliche Löschung von
Daten usw. sein. Im Falle eines solchen Datenverlusts muß versucht
werden, möglichst rasch einen akzeptablen Zustand der Daten wiederherzustellen. Die Randbedingungen und Konzepte der einzelnen
DVS-Typen unterscheiden sich hier erheblich.
Backup-Programme für Dateisysteme arbeiten i.d.R. mit “Archiven”, die Kopien von Dateien – ggf. in komprimierter Form – enthalten und die auf sequentiell les- bzw. schreibbaren Medien, insb. Magnetbändern, gespeichert werden können. Ein Beispiel eines solchen
Systems für UNIX-Rechner ist tar (tape archive). Eine Datei kann
zu verschiedenen Zeiten in Archive kopiert werden und existiert dann
in mehreren Versionen; hierdurch wird implizit eine rudimentäre Versionsverwaltung unterstützt. Im Falle eines Defektes können einzelne
Dateien wieder von einem Archiv in das Dateisystem zurückkopiert
werden. Dies kann bewußt dazu eingesetzt werden, einen früheren Zustand einer Datei wiederherzustellen. Archive eignen sich auch gut
dazu, Daten von einem Rechner zu einem anderen zu transportieren.
In OLTP-Systemen können normalerweise nicht ohne weiteres Teile
des Datenbestands in ein Archiv kopiert und später, nachdem sich die
Datenbank verändert hat, wieder dorthin zurückkopiert werden. Im
schlimmsten Fall sind die Datenbankschemata verändert worden, das
Wiedereinspielen scheitert dann sozusagen schon syntaktisch. Selbst
bei unveränderten Schemata könnten durch die eingespielten Daten
Konsistenzkriterien verletzt werden. Ein partielles Zurücksetzen der
Datenbank auf einen früheren Zustand ist aber auch bei den typischen Anwendungen von OLTP-Systemen nicht sinnvoll: die DB muß
jeweils einen aktuell gültigen Inhalt haben, nicht irgendeinen früheren veralteten. Daher stellen die Backup-Konzepte für OLTP-Systeme
nur auf den Fall von Medienfehlern ab mit dem Ziel, durch weitere
Maßnahmen möglichst rasch wieder den aktuell gültigen Inhalt der
Datenbank zu rekonstruieren. Will man mit OLTP-Systemen auch
34
Datenverwaltungssysteme
früher gültige Daten verwalten, muß dies in den Datenbankschemata
explizit berücksichtigt werden; zu jedem Datenwert muß dann zusätzlich die Gültigkeitsdauer gespeichert werden, was die Formulierung von
Abfragen verkompliziert und zu Performance-Problemen führen kann.
Bei IR-Systemen, die aus anderen, “originären” Datenbeständen
generiert werden, muß im Fall einer Beschädigung nur die Generierung wiederholt werden. Eine Rücksetzung auf eine frühere Version
des Systems ist hier ebenfalls aus Anwendungssicht nicht sinnvoll.
1.3.5
Datenschäden durch Systemabstürze
Ein weiteres Gefahrenpotential für Datenbestände sind Systemabstürze, entweder des Betriebssystems oder der Anwendungsprogramme. Bei Abstürzen der Anwendungsprogramme können infolge von unvollständig durchgeführten Änderungen inkonsistente Zuständen hinterlassen werden, bei Betriebssystemabstürzen können auch interne
Strukturen des Dateisystems oder der Speichermedien beschädigt werden. In jedem Fall können beliebig große Teile des Datenbestands
betroffen und unbrauchbar geworden sein; im Extremfall liegt ein Totalschaden wie bei einem Medienfehler vor. Welche und wie aufwendige Maßnahmen zur Vorbeugung bzw. Schadensbehebung vorgesehen
werden, hängt stark vom Wert der Daten und der tolerierbaren Stillstandszeit der Anwendungen ab.
Bei einem Absturz des Systems oder Anwendungsprogramms ist
der Zustand von Dateien, in denen geschrieben worden ist, i.a. unvorhersehbar; es können weitreichende Schäden bis zum völligen Datenverlust auftreten. Bei einem Systemabsturz können auch schon
zurückliegende, scheinbar abgeschlossene Schreibzugriffe verloren sein,
da die Änderungen u.U. zunächst nur in Puffern erfolgen.
OLTP-Systemen beinhalten sehr umfangreiche Schutzmaßnahmen
gegen Datenschäden infolge von Systemabstürzen.
Konventionelle Dateisysteme bieten nur einen sehr schlechten
Schutz: es sind praktisch keine vorbeugenden Maßnahmen vorhanden,
nach einem Systemabsturz muß das gesamte Dateisystem auf Defekte
durchsucht werden. Dies kann bei großen Systemen selbst bei schnellen
Datenverwaltungssysteme
35
Rechnern 10 - 30 Minuten dauern, was oft zu lang ist. Modernere, sogenannte journaling Dateisysteme beinhalten präventive Maßnahmen,
durch die die Auswirkungen von Systemabstürzen stark reduziert werden und nur noch in extremen Ausnahmefällen umfangreiche Schäden
eintreten können, d.h. in der Regel ist ein sofortiger Neustart des Systems möglich.
Bei IR-Systemen werden typischerweise keine Änderungen on-line
ausgeführt; daher entsteht das Problem von Schäden durch Systemabstürze hier nicht.
1.3.6
Mehrbenutzerfähigkeit und Zugriffskontrollen
Datenbestände müssen oft von verschiedenen Benutzern benutzt werden; oft haben diese Benutzer unterschiedliche Rechte. Fast alle DVS
beinhalten daher Zugriffskontrollen. Basis hierfür ist stets eine Benutzerverwaltung, mit der die Benutzer erfaßt werden, die überhaupt
Zugang zu dem System haben sollen. Ferner ist es fast immer möglich,
Benutzer zu Gruppen zusammenzufassen und den Gruppen Rechte
einzuräumen. Bei Dateisystemen ist die Benutzer- bzw. Gruppenverwaltung naheliegenderweise die des Betriebssystems5 ; DBMS haben
oft eine eigene Benutzerverwaltung.
Die Administration von Rechten an Datenelementen ist bei Dateisystemen wesentlich anders als bei DBMS bzw. IR-Systemen. In Dateisystemen kann im Prinzip für jede einzelne Datei bestimmt werden,
wer sie lesen bzw. schreiben darf. In DBMS bzw. IR-Systemen wäre
dies wegen der vielen kleinen Datengranulate viel zu aufwendig. Stattdessen werden Rechte für Mengen von Objekten vergeben, die durch
Selektionsbedingungen beschrieben werden. An neu erzeugten Objekten, die in eine so beschriebene Menge fallen, gelten dadurch automatisch die entsprechenden Rechte; eine explizite Vergabe von Rechten
ist nicht notwendig. Die mengenorientierte Rechtevergabe ist dem Bedarf in typischen betrieblichen Anwendungen angepaßt, die objektorientierte Vergabe von Rechten in Dateisystemen eher dem Bedarf bei
5
PC-Betriebssysteme, die keine Benutzerverwaltung beinhalten, betrachten wir
nicht, da sie offensichtlich keine sinnvolle Basis für wertvolle Datenbestände sind.
36
Datenverwaltungssysteme
der Dokumentverarbeitung.
In DBMS können Zugriffe von Benutzern außerdem nicht nur auf
Basis der Instanzen, sondern auch auf Basis von Typen eingeschränkt
werden. Beispielsweise könnten bei einer Mitarbeiterdatenbank die
Telephonnummern u.ä. vom Pförtner lesbar sein, Gehaltsdaten könnten nur von entsprechenden Mitarbeitern der Verwaltung gelesen und
geschrieben werden. Allgemein können einzelne Attribute der Objekte eines bestimmten Typs für einen bestimmten Benutzer nicht lesoder schreibbar sein. Derartige typbasierte Zugriffskontrollen sind in
Dateisystemen prinzipiell nicht möglich.
1.3.7
Entfernter Zugriff
Bei vielen parallelen Benutzern muß von verschiedenen Rechnern aus
auf den gemeinsamen Datenbestand zugegriffen werden. Häufig will
man die Datenanzeige und Kommunikation mit dem Bediener auf einem PC abwickeln, während das DBMS auf einem zentralen Rechner
läuft. In der Schichtenarchitektur aus Bild 1.1 laufen somit die GUISchicht und die Datenhaltungsschicht in separaten Programmen auf
verschiedenen Rechnern.
Die mittlere, für die Fachlogik zuständige Schicht kann ebenfalls auf
einem eigenen Rechner ausgeführt werden (der “Applikationsserver”).
Operationsaufrufe von einer höheren Schicht auf eine untere werden
so zu entfernten Aufrufen. Entfernte Aufrufe sind wesentlich aufwendiger als lokale. Dies fällt vor allem dann ins Gewicht, wenn sehr viele
Einzelaufrufe auftreten oder große Datenvolumina übertragen werden
müssen. Dies betrifft vor allem die Kommunikation zwischen der Fachkonzeptschicht und der Datenhaltungsschicht.
Auf Details der Verteilungsarchitekturen können wir hier aus Platzgründen nicht eingehen. Festzuhalten bleibt jedenfalls, daß ein DVS
bei bestimmten Verteilungsarchitekturen Schnittstellen anbieten muß,
die einen entfernten Zugriff auf die Datenbestände ermöglichen und
daß ggf. die Entwicklung verteilter Applikationen unterstützt werden
sollte.
Im Zusammenhang mit der Verteilung tritt oft zusätzlich das Pro-
Datenverwaltungssysteme
37
blem der Heterogenität auf. Ganz elementar können auf den verschiedenen Arbeitsplatzrechnern verschiedene Prozessoren vorliegen, die
z.B. verschiedene Zahlendarstellungen benutzen. Dementsprechend
müssen alle Datentypen bei der Übertragung zwischen Applikation
und DVS zwischen dem internen Format des DVS und einem plattformspezifischen Format konvertiert werden.
Ein ähnliches (allerdings nicht durch die Verteilung verursachtes)
Problem entsteht, wenn die Applikationen in unterschiedlichen Sprachen geschrieben sind.
1.3.8
Paralleler Zugriff
Sofern auf gleiche Datenbestände von verschiedenen Benutzern parallel zugegriffen wird, können Parallelitätsanomalien entstehen. Sofern
alle Benutzer nur lesen, treten keine Probleme auf, insofern entstehen
bei IR-Systemen keine diesbezüglichen Probleme.
Bei Dateisystemen und OLTP-Systemen sind aber (natürlich) auch
schreibende Zugriffe möglich. Zur Lösung der Probleme gibt es
verschiedene Concurrency-Control-Verfahren; das bekannteste ist der
wechselseitige Ausschluß (bzw. allgemeiner das 2-Phasen-Sperrprotokoll), der mithilfe von Sperrungen realisiert wird.
Sperren werden inzwischen in vielen Betriebssystemen angeboten;
Gegenstand einer Sperre ist immer eine komplette Datei. Sofern man
viele Daten in einer Datei speichert, muß also die gesamte Datei gesperrt werden, auch wenn nur für ein einziges darin enthaltenes Datenelement eine Sperre benötigt wird. Dies führt zu sachlich unnötigen
Serialisierungen von Zugriffen und zu einem sehr geringen Parallelitätsgrad. Teilt man den Datenbestand auf sehr viele kleine Dateien auf,
behebt man zwar das Granularitätsproblem der Sperren, bekommt
aber ein erhebliches Performance-Problem wegen des ständigen Lokalisierens, Öffnens und Schließens der Dateien.
Leistungsfähige OLTP-DBMS bieten sehr ausgefeilte Sperrverfahren an, durch die relativ kleine Sperreinheiten (einzelne Tupel oder
Sätze) gesperrt und die große Mengen von Sperren verwaltet werden
können. Nur mit derartigen OLTP-DBMS kann man Systeme bauen,
38
Datenverwaltungssysteme
die von sehr vielen Benutzern parallel genutzt werden können.
Bei IR-Systemen entfällt die gesamte Problematik, weil auf IRSysteme nur lesend zugegriffen wird.
1.3.9
Datenintegration und Sichten
Von mittleren bis großen Applikationen, insb. betrieblichen Informationssystemen, müssen verschiedene Arten von Benutzern (“Rollen”)
gleichzeitig bedient werden. Unterschiedliche Rollen haben unterschiedliche Informationsbedürfnisse; neben Daten, die von allgemeinem Interesse sind, treten auch rollenspezifische Daten auf. In einer
Bank könnten z.B. folgende Arbeitsgebiete mit jeweils eigenen Daten
vorhanden sein:
– Privat-Girokonten
– Firmen-Girokonten
– Wertpapierhandel
– Hypotheken
Bestimmte Daten, z.B. Kundenadressen, werden natürlich ganz oder
teilweise in mehreren Arbeitsgebieten benötigt. Es wäre nun sehr ungeschickt, diese Daten mehrfach, also redundant zu speichern; stattdessen sollten diese Daten nur einmal im DVS gespeichert, unsere Kundenadressen z.B in einem einzigen zentralen Adreßverzeichnis. Die
Daten, die eine Applikation benötigt, müssen für diese nun wieder
geeignet zusammengesetzt werden.
Eine redundanzfreie Modellierung und Speicherung ist im Prinzip bei allen DVS möglich6 . Das entscheidende Problem ist das Wiederzusammensetzen von zerlegten Datenbeständen: die meisten DVS
unterstützen diesen Vorgang überhaupt nicht, eine nennenswerte Unterstützung bieten nur relationale DBMS durch den Sichtenmechanismus.
6
Wie Datenbestände zerlegt werden müssen, damit Redundanzen vermieden
werden, ist im Kontext von relationalen Datenbanken unter dem Begriff “Normalform” zuerst erforscht worden. Normalformen sind aber völlig unabhängig davon
anwendbar, welches DVS eingesetzt wird. Auch dann, wenn “tabellarische” Daten
in Dateien gespeichert werden (z.B. wie in Abschnitt 1.4 beschrieben), können die
Typstrukturen normalisiert werden.
Datenverwaltungssysteme
1.3.10
39
Evolution der Datenbestände
Viele Informationssysteme existieren über sehr lange Zeiträume. Im
Lauf der Zeit müssen die Datenbestände und Anwendungen aufgrund
neuer Anforderungen immer wieder ergänzt werden. In einfachen
Fällen werden nur Daten ergänzt, z.B. kommen neue Attribute bei
vorhandenen Datenelementen hinzu. In komplizierteren Fällen müssen
die vorhandenen Daten umstrukturiert werden, z.B. um Redundanzen
zu vermeiden (s. voriger Abschnitt). Die Frage ist nun, wie stark die
vorhandenen Applikationen - bei großen Informationssystemen können
dies Tausende von Programmen sein - von einer Änderung der Struktur
der Datenbestände betroffen sind.
Verwendet man Dateisysteme zur Datenverwaltung, müssen selbst
bei trivialen Modifikationen der Dateiformate, z.B. beim Anfügen eines
neuen Felds am Ende der Sätze, alle Applikationen angepaßt werden.
D.h. die Quelltexte der Applikationen müssen vorliegen und vom vorhandenen Compiler übersetzbar sein; bei sehr alten Programmen ist
das oft nicht der Fall. Weiter müssen alle betroffenen Programmteile
gesucht und korrigiert werden, das Programm muß nach der Änderung
getestet werden; dies kann signifikante Aufwände verursachen.
Ideal wäre es daher, wenn die vorhandenen Applikationen als Binärprogramme unverändert weiterbenutzt werden könnten oder allenfalls neu compiliert werden müßten; dies bezeichnet man als Datenunabhängigkeit der Applikationen. DBMS leisten dies zumindest bei
“einfachen” Änderungen. Bei relationalen DBMS können die Applikationen durch den Sichtenmechanismus auch vor etwas komplexeren
Änderungen der Datenstrukturen geschützt werden.
1.4
Dateisysteme
Datei(management)systeme sind mit Abstand die verbreitetsten DVS.
In diesem Abschnitt stellen wir einige speziellere Arten von Dateisystemen vor und behandeln die Frage, ob und wie durch Dienstprogramme
auch formatierte Daten in Dateien verwaltet werden können.
Wir gehen auf einige wesentliche Aspekte von Dateisystemen nicht
40
Datenverwaltungssysteme
ein, insb. nicht auf den Aufbau und die Struktur von Verzeichnissen,
Blockverwaltung auf den Medien u.ä. Themen, die üblicherweise in
Vorlesungen über Betriebssysteme behandelt werden. Stattdessen konzentrieren wir uns auf Merkmale einzelner Dateien, insb. auf die Frage,
wie Daten in einer Datei strukturiert abgespeichert werden können.
1.4.1
Arten von Dateisystemen
Man unterscheidet zeichen- und satzorientierte Dateisysteme. Zeichen
bzw. Sätze sind die elementaren Einheiten, aus denen eine Datei besteht, und können nur als Ganze gelesen oder geschrieben werden. Bei
den satzorientierten Dateisystemen unterscheidet man zusätzlich solche mit fester bzw. variabler Satzlänge.
Für die Menge der Elemente (Zeichen bzw. Sätze) einer Datei existieren folgende Strukturen, die auch die Zugriffsmöglichkeiten festlegen:
– sequentielle Struktur: alle Elemente bilden eine Sequenz, die nur in
dieser Reihenfolge durchlaufen werden kann.
– Arraystruktur: auf jedes Element kann direkt anhand seiner Nummer zugegriffen werden. Die für einen Zugriff benötigte Zeit ist bei
allen Elementen in etwa gleich.
– Verzeichnisstruktur (nur bei satzorientierten Systemen): Jedes Element bekommt bei seiner Erzeugung einen Schlüsselwert (meist ein
Text fester Länge), der in der Datei eindeutig sein muß. Mit Hilfe
dieses Schlüsselwerts kann später direkt auf den Satz zugegriffen
werden. Die für einen Zugriff benötigte Zeit ist auch hier bei allen
Elementen in etwa gleich.
Bei einer Arraystruktur bzw. einer Verzeichnisstruktur ist meist
zusätzlich eine sequentielle Struktur verfügbar. Eine kombinierte
Verzeichnis- / sequentielle Struktur wird auch indexsequentiell (ISAM;
index sequential access method) genannt.
Datenverwaltungssysteme
1.4.2
1.4.2.1
41
Verwaltung formatierter Daten in Dateien
Codierungen
Übliche Dateisysteme unterstützen applikationsspezifische Datentypen
bzw. formatierte Daten nicht. Applikationsspezifische Datenstrukturen können nur als “Syntax” einer Datei realisiert werden. So könnte
z.B. in einem UNIX-System die Datei /etc/passwd folgende Textzeilen enthalten:
root:x:0:0:root:/root:/bin/tcsh
bin:x:1:1:bin:/bin:/bin/bash
daemon:x:2:2:daemon:/sbin:/bin/bash
lp:x:4:7:lp daemon:/var/spool/lpd:/bin/bash
man:x:13:2::/var/catman:/bin/bash
at:x:25:25::/var/spool/atjobs:/bin/bash
wwwrun:x:30:65534:Daemon user for apache:/tmp:/bin/bash
Jede Zeile enthält Angaben zu einem Systembenutzer, und zwar den
Namen, verschlüsseltes Paßwort, interne Benutzernummer, Gruppennummer, Beschreibung, home-Verzeichnis und Login-Shell. Die Felder
sind durch einen Doppelpunkt getrennt, dürfen also selbst keinen Doppelpunkt enthalten. In einigen Feldern darf nur die textuelle Darstellung einer Zahl, deren Größe begrenzt ist, stehen. Das Dateisystem
kennt derartige syntaktische Restriktionen nicht und überwacht sie daher auch nicht; die Restriktionen müssen allein durch die Programme,
die die Daten verändern, sichergestellt werden.
Ein offensichtlicher Nachteil des Dateiformats im letzten Beispiel
ist die schlechte Erkennbarkeit, wo die einzelnen Felder liegen, so daß
das Editieren solcher Dateien mit einem normalen Texteditor sehr fehleranfällig ist. Dieses Problem wird bei Dateiformaten reduziert, in
denen textuelle Bezeichner für die Felder verwendet werden, etwa wie
im folgenden Beispiel:
42
Datenverwaltungssysteme
#begin{user}
{
USERNAME=root
PASSWD=x
USERID=0
GROUPID=0
DESCRIPTION=root
HOMEDIR=/root
SHELL=/bin/tcsh
}
In solchen Formaten können die Felder in beliebiger Reihenfolge angegeben werden und fehlen, dann wird ein Vorgabewert verwendet. Zu
derartigen Formaten gehören Parser bzw. Unparser, die eine Datei in
eine Menge von Laufzeitobjekten konvertieren und umgekehrt.
Ein ähnliche Idee liegt dem XML-Ansatz zugrunde. Allerdings
werden bei der XML sogenannte tags benutzt, um Datenelemente zu
klammern, bspw.:
<USERNAME>root</USERNAME>
<USERID>0</USERID>
<SHELL>/bin/tcsh</SHELL>
Ein tag besteht u.a. aus den Sonderzeichen < und > und einem
Schlüsselwort, das das tag identifiziert. Ein einleitendes tag (sozusagen die öffnende Klammer) kann zusätzlich Steueranweisungen hinter
dem Tag-Namen haben, ein schließendes tag hat einen / vor dem tagNamen.
Eine Besonderheit des XML-Ansatzes besteht darin, daß eine Datei
nicht nur die eigentlichen Nutzdaten enthält, sondern auch das Schema
für diese Daten enthalten kann. Statt von Schema spricht man hier
von einer Dokumenttypdefinition (DTD). Der eigentliche Nutzen
der DTD liegt darin, daß man sie als Spezifikation für einen Parser
ansehen kann, der einen Dateiinhalt in eine Hauptspeicherdarstellung
konvertiert, oder für einen Editor, der Instanzen des Dokumenttyps
bearbeiten kann. Mit einem einzigen “generischen” Parser oder Editor können daher beliebige XML-Dateien bearbeitet werden.
Datenverwaltungssysteme
1.4.2.2
43
Such- und Auswertungsfunktionen
Dateisysteme bieten direkt keine Such- oder Auswertungsfunktionen
an. Allerdings sind in fast allen Betriebssystemen Textprozessoren
vorhanden, durch die (direkt oder mit Hilfe von Shell-Skripten) in formatierten Dateien gesucht werden kann. So sind in UNIX-Systemen
die Programme sed , cut , awk , perl usw. hierfür einsetzbar, ferner diverse in die Kommandointerpreter eingebaute Funktionen. Mit
diesen Programmen kann man u.a. aus einer Datei diejenigen Zeilen selektieren, in denen ein bestimmtes Textmuster auftritt, einzelne Felder
ausschneiden, diese Daten mit anderen Daten mischen und für Ausgaben aufbereiten. Diese Programme und Funktionen haben allerdings
zwei gravierende Nachteile:
– Sie skalieren nicht. Bei mittleren Datenbeständen sind die Antwortzeiten i.a. nicht mehr akzeptabel. Bei kleinen Datenbeständen
sind die Antwortzeiten dagegen gut oder sogar sehr gut, Textprozessoren können unter dieser Annahme eine durchaus vorteilhafte
Implementierungstechnologie sein.
Durch Indexierungssysteme wie z.B. glimpse lassen sich zwar
auch für umfangreiche Datenbestände in Dateien Indexe aufbauen,
die die Suche stark beschleunigen können, allerdings gilt dies nur
mit diversen signifikanten Einschränkungen.
– Entwickler solcher Anwendungen müssen mehrere Skript- und Textprozessorsprachen und deren Kombination beherrschen, und es
müssen komplizierte Algorithmen realisiert werden. Dies ist für
gelegentliche Benutzer nicht zumutbar.
1.5
OLTP-Datenbankmanagementsysteme
OLTP ist die Abkürzung von on-line transaction processing. Diverse Merkmale von OLTP-Systemen sind schon in den vorstehenden
Abschnitten erläutert worden, insb. Funktionen für die exakte Suche, Recovery, Mehrbenutzerfähigkeit, Datenintegration und Datenunabhängigkeit. Wir gehen in diesem Abschnitt auf einige Punkte
detaillierter ein.
44
Datenverwaltungssysteme
1.5.1
Datenbankmodelle
Daten werden in einem OLTP-DBMS strukturiert gespeichert, d.h. das
OLTP-DBMS kennt die Struktur der Daten. Dies ist die entscheidende Basis dafür, bei Abfragen Strukturelemente der gesuchten Daten
benennen zu können oder Daten für einzelne Applikationen zusammenstellen zu können, um deren Datenunabhängigkeit zu erreichen.
Wie die Daten strukturiert werden können, legt das Datenbankmodell
des OLTP-DBMS fest.
Vereinfacht gesagt definiert ein Datenbankmodell die Struktur einer Datenbank und die Operationen auf dieser Struktur. Man teilt
die bekannten Datenbankmodelle in konventionelle und nichtkonventionelle ein:
– Zu den konventionellen Datenbankmodellen zählen das relationale,
das Netzwerk- und das hierarchische Datenbankmodell.
– Zu den nichtkonventionellen Datenbankmodellen zählen u.a. objektorientierte, Geo-, deduktive und Multimedia-Datenbankmodelle.
Darüber hinaus gibt es Mischformen, z.B. objekt-relationale Systeme.
Etwas konkreter gesagt ist ein Datenbankmodell bestimmt
durch:
1. Eine “Denkwelt”, in der anwendungsspezifische Datentypen (z.B.
ein Objekttyp Person mit den Attributen Name, Vorname usw.) definiert werden können. Notiert werden derartige Definitionen üblicherweise in einer Datendefinitionssprache (data definition language, DDL)7 Diese ist analog zu sehen zu den Teilen einer Programmiersprache, die in Typdefinitionen benutzt wird.
2. Operationen auf dem Inhalt einer Datenbank, insb. Operationen,
die einzelne Datenelemente erzeugen, schreiben, lesen, selektieren oder löschen. Diese Operationen werden meist in Form einer
7
Eigentlich müßte es Datentypdefinitionssprache heißen; wir schließen uns hier
aber dem allgemeinen Sprachgebrauch an.
Datenverwaltungssysteme
45
Abfrage- bzw. Datenmanipulationssprache (data manipulation language, DML) angeboten. Sie sind in dem Sinne generisch,
daß sie mit beliebigen anwendungsspezifischen Datentypen arbeiten. Der gewünschte Datentyp muß oft als Parameter explizit angegeben werden, z.B. muß in der Operation, die ein neues Objekt
erzeugt, der gewünschte Typ (z.B. Person) angegeben werden.
Die Operationen des Datenbankmodells stellen gemäß dem Prinzip der Datenkapselung die Schnittstelle dar, über die auf die Datenbank, die hier die Rolle des “schwarzen Kastens” spielt, zugegriffen
wird, ohne daß interne Realisierungsdetails nach außen bekanntgegeben werden.
3. ggf. Integritätsbedingungen, typischerweise Einschränkungen der
zulässigen Datenbankinhalte.
Als Beispiel geben wir einige Merkmale des relationalen Datenbankmodells an:
1. Man kann Tabellen mit beliebigen “Spaltenköpfen” definieren;
2. Man kann z.B. Tupel in einer Relation selektieren oder zwei Relationen anhand gleicher Attributwerte “verbinden”;
3. Man kann als Integritätsbedingung festlegen, daß bestimmte Attribute bzw. Attributmengen Identifizierungsschlüssel sein sollen.
1.5.2
Datenintegration, Datenunabhängigkeit und die
3-Ebenen-Schema-Architektur
Eine zentrale Leistung von DBMS besteht darin, Daten auf drei verschiedenen “Ebenen” betrachten und in Form von “Schemata” Eigenschaften der Daten definieren zu können. Veranschaulicht wird dies in
der 3-Ebenen-Schema-Architektur, die in Bild 1.4 gezeigt ist.
Um Mißverständnissen vorzubeugen sei darauf hingewiesen, daß es
sich hier nicht um eine Software-Architektur, also um eine Zerlegung
des Systems in Komponenten handelt, wie sie z.B. in Bild 1.1 gezeigt ist. Die 3-Ebenen-Schema-Architektur beschreibt ausschließlich
Eigenschaften der Datenhaltungsschicht.
46
Datenverwaltungssysteme
Sicht 1
........
Sicht n
konzeptuelles Schema
internes Schema
Abbildung 1.4: Schema-Architektur von DBMS
Das konzeptuelle Schema in der Mitte dieser Architektur definiert die logische Gesamtstruktur aller Daten, d.h. hier werden alle Applikationen, die innerhalb eines Unternehmens benötigt werden,
aus einer Gesamtsicht heraus betrachtet, und es werden alle einzelnen
Datenelemente, die in irgendeiner der Applikationen benötigt werden,
hierin vereinigt. Ferner werden hier Beziehungen der Daten untereinander festgelegt, und es werden solche Integritätsbedingungen formuliert, die systemweit gelten sollen. Nicht berücksichtigt werden hierin Implementierungsaspekte oder Optimierungen (zumindest in der
Theorie; in der Praxis muß man oft von dieser Regel abweichen).
Das interne Schema gibt an, wie die Strukturen, die auf der
konzeptuellen Ebene definiert worden sind, auf physische Strukturen
abzubilden sind. Unter physischen Strukturen verstehen wir hier Festlegungen, wie die Daten auf Platten bzw. in Dateien angeordnet, sortiert und formatiert werden. Ebenfalls geregelt wird auf dieser Ebene, welche Indexe, d.h. welche Hilfsstrukturen zur Beschleunigung von
Zugriffen, angelegt werden sollen. Hier wird die Sortierreihenfolge von
Sätzen innerhalb von Dateien bestimmt, und es können noch diverse andere Optimierungen, je nach dem Datenmodell und nach dem
DBMS, eingebaut werden.
Ein einzelnes Anwendungsprogramm benötigt i.a. nur einen kleinen
Teil der vielen Typdefinitionen, die im konzeptuellen Schema enthalten
Datenverwaltungssysteme
47
sind. Die komplette Datenbank muß also sozusagen “gefiltert” und auf
den Bedarf dieser Anwendung reduziert werden. Genau dieses leistet
der Sichtenmechanismus eines DBMS. Ein externes Schema, auch
Sicht (view) genannt, spezifiziert eine solche eingeschränkte Sicht auf
die Datenbank. Im Vergleich zum konzeptuellen Schema werden nur
ein Teil der Daten oder abgeleitete Daten sichtbar gemacht.
Entsprechend dieser Schema-Architektur unterscheidet man zwei
Arten der Datenunabhängigkeit:
Physische Datenunabhängigkeit bedeutet, daß die konzeptionellen Strukturen der Daten unabhängig von den physischen Strukturen sind und daß somit die physischen Strukturen geändert
werden können, ohne daß dies einen Einfluß auf die konzeptionellen Strukturen hat.
Datenbankmanagementsysteme unterstützen also die Trennung zwischen physischer und logischer Organisation der Daten.
Logische Datenunabhängigkeit bedeutet, daß die Sichten, auf denen die Applikationen arbeiten, von [gewissen] Änderungen des
konzeptuellen Schemas nicht betroffen sind, in diesem Sinne also
unabhängig vom konzeptuellen Schema sind.
1.5.3
Transaktionsverarbeitung
Die eigentliche Besonderheit von OLTP-DBMS liegt darin, daß sie
Transaktionen unterstützen und hohe Anforderungen an die Sicherheit
der Daten und an die Systemverfügbarkeit erfüllen8 . Diese Sicherheitseigenschaften sind weitestgehend unabhängig vom Datenbankmodell
und in der Praxis oft viel wichtiger als technische Finessen des Datenbankmodells. Transaktionen adressieren mehrere Bedrohungen der
Integrität des Datenbestands.
Datenschäden durch parallelen Zugriff (vgl. Abschnitt 1.3.8) werden durch Concurrency-Control-Verfahren verhindert. CC-Verfahren
in OLTP-Systemen gehen davon aus, daß Transaktionen kurz sind,
8
Letzteres gilt natürlich nur für jahrelang in der Praxis bewährte Produkte.
48
Datenverwaltungssysteme
also nur wenige Datengranulate betreffen und Ausführungszeiten im
Sekundenbereich haben.
Datenschäden können ferner durch Systemabstürze (s. Abschnitt
1.3.5) und natürlich durch Medienfehler verursacht werden; Defekte
an Magnetplatten sind zwar selten, aber keineswegs unmöglich. Für
fast alle Unternehmen ist eine Zerstörung oder wesentliche Beschädigung des Datenbestands eine Katastrophe. Die heute verwalteten Datenbestände sind so umfangreich, daß sie bei einem Verlust der Datenbank in “endlicher” Zeit nicht mehr von Hand rekonstruiert werden können, es kommen also ausschließlich automatische RecoveryVerfahren in Betracht. Selbst ein kurzer Systemausfall führt bei den
heute üblichen on-line-Zugriffen praktisch zu einem sofortigen Stillstand aller geschäftlichen Aktivitäten und entsprechend hohen Verlusten, die Recovery-Verfahren müssen daher sehr effizient arbeiten.
1.6
Information-Retrieval-Systeme
Das klassische Beispiel eines Information-Retrieval- (IR-) Systems ist eine Literaturdatenbank. Neuere und vielleicht sogar bald
wichtigere Beispiele sind Warenkataloge, Wirtschaftsauskünfte oder
Büroinformationssysteme. Im Gegensatz zu anderen DVS versteht
man ein IR-System immer als komplettes Informationssystem incl. einer interaktiven Bedienschnittstelle.
Äußerlich betrachtet erscheint ein IR-System bzgl. der Datenverwaltung i.w. als ein relativ einfaches relationales System, denn der
Datenbestand entspricht i.w. einer einzigen Tabelle, die z.B. Buchbeschreibungen enthält. Daß diese Tabelle recht groß (105 bis 107
Einträge) und längere Texte enthält (z.B. die Zusammenfassung eines Buchs), ist dabei sekundär. Dieser äußerliche Eindruck täuscht
allerdings. IR-Systeme unterscheiden sich in vielen Aspekten ganz wesentlich von OLTP-Systemen.
Auf die andere Interpretation von Suchanfragen wurde schon in
Abschnitt 1.3.3 hingewiesen. Der Benutzer erwartet für jeden Treffer
eine Einschätzung von dessen Relevanz. Um die Treffer besser bewer-
Datenverwaltungssysteme
49
ten zu können, ist es in IR-Systemen sinnvoll, in einem Suchauftrag
Gewichtungen für die einzelnen Selektionskriterien anzugeben. Negierte Kriterien (“nicht von der Firma X”) sollten nicht zum Ausschluß
von Elementen aus der Treffermenge führen, sondern nur als Minuspunkte bei der Bewertung behandelt werden.
Nicht nur die Suchaufträge sind vage zu interpretieren, auch die
vorhandenen Daten können eine gewisse Unschärfe aufweisen. So beschreibt weder der Titel noch die Inhaltsangabe eines Buches den Inhalt des Buchs exakt. Manchmal fehlen auch Daten (z.B. das Erscheinungsjahr des Buches ist unbekannt). Auch mit unscharfen oder
unvollständigen Daten muß vernünftig umgegangen werden.
IR-Systeme sind praktisch immer interaktiv. Die Interaktion eines
Benutzer mit einem IR-System unterscheidet sich erheblich von der
mit einem OLTP-System. Wenn bei der Inventur eines Buchladens
die Liste der Bücher in der Abteilung “Gartenbau” gefragt ist, muß
die komplette Liste dieser Bücher erscheinen, bspw. 250 Stück. Wenn
eine Kundin ein Buch über Gartenbau sucht, will sie 1 Buch kaufen,
keine 250. Erst nachdem sie weiß, daß insg. 250 Bücher zum Thema Gartenbau zur Auswahl stehen, ist klar, daß der Suchraum weiter
eingeschränkt werden muß.
Die Suche in einem IR-System hat daher typischerweise 2 Phasen:
in der ersten Phase werden einzelne oder kombinierte Selektionskriterien ausprobiert und das System zeigt nur die Zahl der Treffer an,
sozusagen als eine extrem kompakte Darstellung der Treffermenge, etwa wie im folgenden Beispiel:
Nr. Treffer Selektionskriterium
1
250
Gartenbau
2
83
Rosen
3
44
Obstbaeume
4
31
Hecken
5
75
#1 & #2
6
17
#1 & #2 & #3
7
0
#1 & #2 & #3 & #4
Sobald die Treffermenge klein genug ist (ca. 10 - 20 Treffer), läßt
50
Datenverwaltungssysteme
sich unsere Kundin eine detailliertere Beschreibung der Treffer anzeigen. Wenn nichts Passendes dabei ist, werden ggf. neue Selektionskriterien ausprobiert. Letzteres sollte auch so möglich sein, daß
bisher vorhandene Treffer als irrelevant oder besonders relevant markiert werden können und bei der nächsten Suche nach ähnlichen bzw.
unähnlichen Elementen gesucht wird.
Letztlich liegt also ein iterativer Prozeß vor, das IR-System muß
derartige Dialoge unterstützen.
Benutzer von IR-Systemen suchen i.a. Information (im Sinne des
Abschnitts 1.2.1), die wegen ihrer Komplexität keine eindeutige Repräsentation hat. Wird bei der Suche eine andere Repräsentation
unterstellt als bei der Speicherung, werden Informationen bei einer
reinen Faktensuche, insb. auch bei einer Stichwortsuche anhand von
Textmustern (pattern matching), nicht gefunden.
Hierzu ein Beispiel: Unsere Kundin sucht Bücher über Obstbäume, also sucht sie nach dem Stichwort Obstbaeume ; ein Buch, das
im Titel Obstbaum , Steinobstbaeume , Birnbaeume oder Frisches
Obst von eigenen Baeumen enthält, würde bei einer reinen Faktensuche nicht gefunden. Das IR-System sollte erkennen können, daß die
vorstehenden Terme Ähnlichkeiten aufweisen. Unähnlichkeiten entstehen u.a. durch Flexionen, unterschiedliche Wortstellungen und Verwendung allgemeinerer, speziellerer oder synonymer Begriffe. Nur in
einfachen Fällen kann man diese ähnlichen Terme durch Textmuster
finden, i.a. sind wesentlich komplexere Verfahren notwendig.
Die Fachgruppe Information Retrieval innerhalb der Gesellschaft
für Informatik definiert Information Retrieval wie folgt (s. [Fu05]):
“Im Information Retrieval (IR) werden Informationssysteme in bezug auf
ihre Rolle im Prozeß des Wissenstransfers vom menschlichen Wissensproduzenten zum Informations-Nachfragenden betrachtet. Die Fachgruppe “Information Retrieval” in der Gesellschaft für Informatik beschäftigt sich dabei
schwerpunktmäßig mit jenen Fragestellungen, die im Zusammenhang mit vagen Anfragen und unsicherem Wissen entstehen. Vage Anfragen sind dadurch gekennzeichnet, daß die Antwort a priori nicht eindeutig definiert ist.
Hierzu zählen neben Fragen mit unscharfen Kriterien insbesondere auch sol-
Datenverwaltungssysteme
51
che, die nur im Dialog iterativ durch Reformulierung (in Abhängigkeit von
den bisherigen Systemantworten) beantwortet werden können; häufig müssen
zudem mehrere Datenbasen zur Beantwortung einer einzelnen Anfrage durchsucht werden. Die Darstellungsform des in einem IR-System gespeicherten
Wissens ist im Prinzip nicht beschränkt (z.B. Texte, multimediale Dokumente, Fakten, Regeln, semantische Netze). Die Unsicherheit (oder die Unvollständigkeit) dieses Wissens resultiert meist aus der begrenzten Repräsentation von dessen Semantik (z.B. bei Texten oder multimedialen Dokumenten);
darüber hinaus werden auch solche Anwendungen betrachtet, bei denen die
gespeicherten Daten selbst unsicher oder unvollständig sind (wie z.B. bei vielen technisch-wissenschaftlichen Datensammlungen). Aus dieser Problematik
ergibt sich die Notwendigkeit zur Bewertung der Qualität der Antworten eines Informationssystems, wobei in einem weiteren Sinne die Effektivität des
Systems in bezug auf die Unterstützung des Benutzers bei der Lösung seines
Anwendungsproblems beurteilt werden sollte. ”
1.7
Ein- und Ausgabeschnittstellen
Wir haben Datenverwaltungssysteme bisher vor allem hinsichtlich ihrer Datenmodellierungs-, Analyse- und Suchfunktionen betrachtet, also Funktionen, die man der Datenhaltungsschicht in Bild 1.1 zuordnet
und die im Laufzeitkern des DVS (s. Bild 1.3) realisiert werden.
Für die Auswahl eines DVS ist ein weiterer wichtiger Aspekt, ob
und wie die Konstruktion der erforderlichen Benutzerschnittstellen zur
Ein- und Ausgabe der Daten unterstützt wird. Der Aufwand zur Realisierung dieser Schnittstellen (s. GUI-Schicht in Bild 1.3) kann ganz erheblich sein. Vereinfacht werden kann die Realisierung dieser Schnittstellen durch fertige Standardapplikationen und/oder durch Applikations-Frameworks.
Bei Dateisystemen sind immer Texteditoren wie z.B. emacs
verfügbar. Unter einem Texteditor verstehen wir hier einen Editor,
der normalerweise jedes einzelne darstellbare Byte einer Datei als Zeichen anzeigt, wobei eine Zeichencodierung wie ISO 8859-1 (Latin-1)
benutzt wird. Nicht gemeint sind hier Editoren für formatierten Text,
52
Datenverwaltungssysteme
die Fettschrift, mehrere Schriftgrößen und -Arten und das Seitenlayout
anzeigen können und die üblicherweise in Büropaketen enthalten sind.
Mit derartigen Texteditoren können beliebige Dateiinhalte ediert
werden, insb. natürlich auch Dateiformate wie in Abschnitt 1.4.2.1 beschrieben. Auf die Realisierung von speziellen Eingabeschnittstellen
kann daher völlig verzichtet werden.
Bei OLTP-DBMS sind formularartige Schnittstellen zur Eingabe
und Änderung einzelner Datenelemente üblich, ferner tabellarische
Darstellungen von Mengen von Datenelementen. In betrieblichen Anwendungen treten viele Datentypen (Größenordnung 100 bis 1000) auf,
für jeden Datentyp ist eine eigene Schnittstelle erforderlich. Aufgrund
der großen Anzahl verursacht eine “manuelle” Konstruktion all dieser
Schnittstellen einen unvertretbar hohen Aufwand.
Eine erste Lösung dieses Problems besteht in “generischen” Editoren, die formularartige oder tabellenförmige Darstellungen benutzen.
Derartige Werkzeuge arbeiten für beliebige Datenbankschemata und
sind praktisch ohne Anpassungsaufwand einsetzbar. In den Formularen bzw. Tabellen werden üblicherweise z.B. Namen von Attributen, die im Schema definiert sind, direkt als Spaltenköpfe eingesetzt,
d.h. lesbarere Bezeichnungen, Sprachvarianten oder an den konkrete
Anwendung angepaßte Hilfefunktionen sind nicht möglich. Systembedingt können die Standardschnittstellen daher keine höheren Ansprüche an die Gestaltung der Schnittstellen erfüllen.
Höhere Ansprüche können nur von individuell gestalteten Schnittstellen erfüllt werden. Viele DBMS unterstützen die Entwicklung
derartiger Schnittstellen durch Listengeneratoren oder AnwendungsFrameworks. Listengeneratoren interpretieren Spezifikationen von
Schnittstellen, ihre Flexibilität ist daher begrenzt durch vorgegebene
Optionen und beschränkter als die von Anwendungs-Frameworks, die
beliebig durch Individualsoftware ergänzt werden können. Bei allen
Varianten muß wegen der Komplexität der Systeme mit einem signifikanten Einarbeitungsaufwand gerechnet werden. Der gesamte Problemkomplex ist ein eigenes Themengebiet der Softwaretechnik und
kann hier nicht vertieft behandelt werden.
Datenverwaltungssysteme
53
In IR-Systemen gibt es normalerweise nur einen oder nur wenige Dokumenttypen; das bei betrieblichen Anwendungen auftretende
Mengenproblem stellt sich hier also nicht. Hinzu kommt, daß Ähnlichkeitsbegriffe und Relevanzbewertungen oft dokumenttypspezifisch
sind. Daher werden i.d.R. individuelle Schnittstellen realisiert. Wenn
die Generierung von Indexen sehr aufwendig ist und nur in längeren
Intervallen erfolgt, kann es sinnvoll sein, die Abfrageschnittstelle und
die Dateneingabe völlig verschieden zu gestalten.
Glossar
3-Ebenen-Schema-Architektur: Strukturmodell eines DBS, das eine externe, eine konzeptuelle und eine interne Ebene unterscheidet, in denen Typen definiert und andere Festlegungen zu den Typen gemacht
werden können
3-Schichten-Architektur: eines Informationssystems: Grobarchitektur
mit Schichten für die Datenhaltung, Funktionslogik und Benutzerinteraktion
Dateisystem: a) Software: Komponente eines Betriebssystems, die Dateien, Verzeichnisse und weitere damit zusammenhängende Konzepte auf einer Platte oder ähnlichen Datenspeichern realisiert; b) Daten: Inhalt einer Platte eines ähnlichen Datenspeichers, die von einer
Dateisystem-Software verwaltet wird
Dateisystem, satzorientiertes: Dateisystem-Software,
Sätze elementare Speichereinheiten sind
bei der ganze
Concurrency Control: Steuerung der parallelen Ausführung von Transaktionen, so daß eine gegenseitige Beeinflussung vermieden wird
Datenbankmanagementsystem (DBMS): Software, die eine Datenbank verwaltet und einkapselt
Datenbankmodell: konzeptuelle Basis eines DBMS; definiert u.a. eine
Denkwelt zur Definition applikationsspezifischer Schemata und eine
allgemeine Abfragesprache
Datenbankmodell, Netzwerk-: “konventionelles” Datenbankmodell; die
Datenbank hat die Struktur eines Netzwerks
Datenbankmodell, hierarchisches: “konventionelles” Datenbankmodell;
die Datenbank hat die Struktur einer Menge von Bäumen
54
Datenverwaltungssysteme
Datendefinitionssprache (data definition language): Sprache, in der für
ein DBMS (oder allgemeiner DVS) Typdefinitionen notiert werden
können
Datenintegration: Behandlung des bei größeren Informationssystemen
auftretenden Problems, daß verschiedene Nutzertypen überlappende
Datenbestände nutzen
Datenverwaltungssystem (DVS): System, das Daten persistent verwalten kann und das Suchfunktionen und andere Dienste anbietet
Normalform: Korrektheits- bzw. Qualitätskriterium für Schemata; Beispiele: 1., 2. und 3. Normalform und Boyce-Codd-Normalform
OLTP-System (on-line transaction processing system): DBMS, das eine
größere Anzahl von Transaktionen, die i.d.R. nur auf kleine Teile der
Datenbank zugreifen, parallel ausführen kann und das umfangreiche
Schutzvorrichtungen gegen Applikationsfehler und sonstige Störungen
bietet
Recovery: Schutzvorrichtungen im DBMS gegen Applikationsfehler, Medienfehler, Systemabstürze und sonstige Störungen, die zu Datenverlusten führen könnten
Schema: Typdefinitionen in einer Datenbank
Transaktion: Folge von Zugriffen auf eine Datenbank, die einen konsistenten Datenbankzustand in einen neuen konsistenten Datenbankzustand
überführt und die vom DBMS “atomar” ausgeführt wird, also ganz
oder gar nicht wirksam wird und nicht mit parallelen Transaktionen
interferiert
Lehrmodul 2:
B-Bäume
Zusammenfassung dieses Lehrmoduls
B-Bäume bzw. B*-Bäume sind eine der wichtigsten Erfindungen
der Informatik. Sie implementieren den generischen abstrakten Datentyp “Verzeichnis”. Im Gegensatz zu den hauptspeicherorientierten
binären Bäumen sind B-Bäume plattenorientiert. Weiterhin weisen
sie die Besonderheit auf, nicht zu degenerieren und Suchzeiten in der
Größenordnung von log(n) zu garantieren. B*-Bäume verbessern die
Suchgeschwindigkeit weiter, indem die Nutzdaten nur noch in den
Blättern des Suchbaums gespeichert werden, wodurch die Indexknoten
einen höheren Verzweigungsgrad haben können.
Vorausgesetzte Lehrmodule:
keine
Stoffumfang in Vorlesungsdoppelstunden:
c
2005
Udo Kelter
1.0
Stand: 22.10.2005
56
2.1
B-Bäume
Historischer Hintergrund
B-Bäume sind eine der wichtigsten Erfindungen der Informatik. BBäume entstanden im Kontext der Entwicklung relationaler Datenbanken [BaM72]; ohne B-Bäume wären die heute allgegenwärtigen relationalen Datenbanksysteme nicht denkbar. In der Architektur von
DBMS realisieren sie eine Direktzugriffsmethode für Speichersätze.
B-Bäume sind Suchbäume, sie gehören zu den grundlegenden Datenstrukturen, sie werden daher oft in Informatik-Grundvorlesungen
vorgestellt. Im Gegensatz zu den hauptspeicherorientierten binären
Bäumen sind B-Bäume plattenorientiert. Weiterhin weisen sie (ähnlich wie AVL-Bäume) die Besonderheit auf, nicht zu degenerieren; es
ist garantiert, daß die Höhe eines B-Baums logarithmisch von der Zahl
der enthaltenen Elemente abhängt.
B-Bäume können im Detail recht unterschiedlich implementiert
sein, sogar die Schnittstellen können viele fallspezifische Besonderheiten aufweisen. Um von diesen Besonderheiten zu abstrahieren, führen
wir zunächst den Begriff generischer abstrakter Datentyp (gADT) ein
und beschreiben einen B-Baum als einen gADT.
Dieser gADT beinhaltet natürlich eine Operation, die in einem
Datenbestand nach einzelnen Elementen sucht, daneben aber auch
Operationen zum Einfügen und Löschen von Datenelementen. Das
entscheidende Problem ist hierbei, die Balancierung des Suchbaums
zu erhalten. In diesem Lehrmodul beschreiben wir die Techniken, die
dieses Ziel erreichen.
Abschließend gehen wir noch kurz auf B*-Bäume ein; diese optimieren die Suchgeschwindigkeit durch Trennung der Indexstrukturen
von den Datenblöcken weiter.
2.2
2.2.1
Verzeichnisse
Generische ADT
B-Bäume realisieren eine Zugriffsstruktur, die man Verzeichnis nennt.
“Verzeichnis” ist wiederum ein wichtiger generischer abstrakter Da-
B-Bäume
57
tentyp.
Ein generischer abstrakter Datentyp (gADT, auch Typkonstruktor genannt) ist ein abstrakter Datentyp, in dessen Schnittstelle,
insb. bei den Parametern der Operationen, ein bestimmter Basisdatentyp (ggf. auch mehrere) offenbleiben; durch Einsetzen eines konkreten Basisdatentyps wird der generische abstrakte Datentyp zu einem
einfachen abstrakten Datentyp, von dem Instanzen gebildet werden
können.
gADT kommen versteckt schon in der Informatik-Grundausbildung
vor: dort werden z.B. Listen, Stapel, Suchbäume usw. als Datenstrukturen eingeführt, i.d.R. aber für einen bestimmten Typ von darin enthaltenen Datenelementen, z.B. ganze Zahlen oder Zeichenketten; diesen Typ nennt man auch den Basisdatentyp. Man macht sich leicht
klar, daß der Basisdatentyp für die Funktionsweise einer “abstrakten”
Liste oder eines Stapels völlig unerheblich ist. Aus einer Implementierung einer Liste von ganzen Zahlen kann man leicht eine Implementierung einer Liste von Zeichenketten machen, indem man überall dort,
wo der Basisdatentyp auftritt, den passenden neuen Typ einsetzt9 .
Der gADT Liste abstrahiert gerade von den Differenzen dieser Listenarten und könnte Liste[B] genannt werden, um auszudrücken, daß
ein formaler Typ-Parameter B vorhanden ist.
Der Begriff gADT bezieht sich nur auf die Syntax und Semantik der
Schnittstelle, also die exportierten Typen und Operationen, und die
Wirkung der Operationen, nicht hingegen auf die Implementierung.
Man kann in manchen Programmiersprachen generische Implementierungen realisieren, die Details sind unterschiedlich und hier irrelevant.
Man kann jedenfalls wie üblich bei abstrakten Datentypen verschiedene Implementierungen derselben Schnittstelle realisieren.
Arrays lassen sich ebenfalls als gADT auffassen; daß man ihre Implementierung nicht sieht, weil sie als Teil der Programmiersprache
implementiert sind, ist dabei unerheblich. Arrays haben zwei formale
Typ-Parameter: (a) den Indexbereich N, der immer ein endliches In9
Ferner können typspezifische Kopieroperationen auftreten und andere Details
anzupassen sein, diese Details spielen im weiteren aber keine Rolle.
58
B-Bäume
tervall der ganzen Zahlen ist, und (b) der Typ der Arrayelemente B.
Man könnte also vom gADT array [N,B] reden.
2.2.2
Der generische ADT directory [S,I]
Ein Verzeichnis (directory) ist eine Datenstruktur, die Elemente
(“Sätze”) enthält, die aus einem Schlüsselwert und zugeordneten Daten (dem “Inhalt”) bestehen. Ein Beispiel für ein solches Element ist
eine Personenbeschreibung, wobei die Personalnummer der Schlüsselwert ist und diverse Angaben zur Person die zugeordneten Daten.
Der gADT directory [S,I] hat also zwei Basisdatentypen, für
die folgendes gilt:
– S ist der Typ der Schlüsselwerte; er muß eine Operation größer als(S,S), die zwei Schlüsselwerte vergleicht, anbieten.
Implementierungen von Directories haben meist zusätzliche implementierungsspezifische Restriktionen für diesen Typ, z.B. könnten nur ganze Zahlen oder Strings der Länge 8 zulässig sein.
– I ist der Typ des Inhalts eines Eintrags. I hat keinen Einfluß auf
die Funktionslogik eines directory. Auch hier kann es implementierungsspezifische Restriktionen geben.
Der gADT directory [S,I] bietet folgende Operationen auf Verzeichnissen an (die Kleinbuchstaben v, s und i bezeichnen den übergebenen Wert bzw. die übergebene Referenz; hinter dem Doppelpunkt
steht ggf. der Typ des Rückgabewerts):
create(): V
Anlegen eines leeren Verzeichnisses
dispose(V)
Löschen des Verzeichnisses v
insert(V,S,I) Einfügen bzw. Überschreiben des Satzes mit dem
Schlüsselwert s in v; der neue Inhalt ist i
delete(V,S)
Löschen des Satzes mit Schlüsselwert s in v
read(V,S): I
Lesen des Satzes mit Schlüsselwert s in v; zurückgegeben wird der Satzinhalt.
read liefert einen Fehler, wenn kein Satz mit Schlüsselwert s in Verzeichnis v vorhanden ist.
B-Bäume
59
Die vorstehenden Operationen stellen einen Minimalumfang dar.
Darüberhinaus bieten manche Implementierungen des gADT Verzeichnis zusätzliche Operationen an:
next key(V,S) liefert den nächstgrößeren Schlüsselwert nach s in v.
Diese Operation ermöglicht es, alle Einträge des
Verzeichnisses v sequentiell zu durchlaufen.
read interval(V,S,S): liste[I] liest alle Sätze mit einem Schlüsselwert zwischen den beiden übergebenen Schlüsselwerten in Verzeichnis v.
Diese Operation kann im Prinzip auch unter Benutzung von next key realisiert werden, allerdings
kann sie effizienter implementiert werden als die sonst
notwendigen Einzelzugriffe.
Ein B-Baum ist eine effiziente, plattenorientierte Implementierung
des gADT directory, incl. sequentiellem Durchlauf und Intervallabfrage.
2.3
2.3.1
B-Bäume
Grundlegende Implementierungsentscheidungen
Zwei Optimierungsziele stehen hier im Vordergrund:
– Bei der Suche nach dem Satz mit dem Schlüsselwert s sollen möglichst wenige Seiten besucht (also Blöcke übertragen) werden. Der
bei hauptspeicherorientierten Suchstrukturen im Vordergrund stehende Rechenaufwand spielt hier keine Rolle, da ein Plattenzugriff
in der Größenordnung von 10 Millisekunden dauert, also ca. 106 bis
107 mal mehr als ein Rechenschritt der CPU.
– Der Platz auf der Platte soll möglichst gut ausgenutzt werden. Das
Verhältnis von den Nutzdaten zu dem Brutto-Platzbedarf sollte
über 50 % liegen. Unter Nutzdaten verstehen wir hier die Schlüsselwerte und die zugehörigen Satzinhalte, die ja auf jeden Fall gespeichert werden müssen. Hinzu kommen Zeigerstrukturen und
60
B-Bäume
sonstige Hilfsdaten und insb. Speicherbereiche, die aus technischen
Gründen reserviert werden müssen. Der Brutto-Platzbedarf ist die
Gesamtgröße der letztlich auf der Platte für das Verzeichnis benutzten Sektoren.
2.3.2
Vielweg-Suchbäume
Binäre Suchbäume sind in ihrer Grundform hauptspeicherorientiert,
d.h. man unterstellt eine Speicherverwaltung, bei der einzelne Knoten in Abschnitten des Hauptspeichers liegen, die direkt adressierbar
sind. Eine sehr simple Methode, die Struktur eines binären Suchbaums auf der Platte zu realisieren, besteht darin, einfach jeden Knoten des Suchbaums in einen eigenen Block zu schreiben. Im Vergleich
zu einer Hauptspeicherimplementierung wären die Verweise auf die Unterbäume, die in jedem Knoten stehen, keine Hauptspeicheradressen
mehr, sondern Nummern von Blöcken auf der Platte (“Medienadressen”). Die grundlegenden Algorithmen zum Suchen, Einfügen und
Löschen in Bäumen können ansonsten unverändert bleiben.
Dieser simple Ansatz hat indes den gravierenden Nachteil, i.a. den
Platz auf der Platte schlecht auszunutzen. Bei einem binären Suchbaum enthält ein Knoten folgenden Daten:
– die Zeiger auf linken und rechten Unterbaum
– den Schlüsselwert
– den Inhalt mit Nutzdaten, von dem wir annehmen, daß er in einem
Bytefeld fester Länge gespeichert werden kann
Knoten
im Baum
s
linker
Unterbaum
Nutzdaten
rechter
Unterbaum
Nehmen wir z.B. folgende Größen an:
B-Bäume
b
t
k
i
61
Blockgröße in Bytes
Platzbedarf für eine Medienadresse (Verweis
auf Teilbaum)
Platzbedarf für einen Schlüsselwert
Platzbedarf für Satzinhalt
z.B. b = 2048
z.B. t = 8
z.B. k = 8
z.B. i = 110
Jeder Block wäre in unserem Beispiel also nur zu 134/2028 oder ca.
6.6 % gefüllt. Dies entspricht nicht unseren obigen Optimierungszielen. Um den Füllungsgrad der Blöcke zu verbessern, müssen mehrere
Sätze und Verweise auf Unterbäume in einem Block gepackt werden.
Wir sprechen dann von einem Vielweg-Suchbaum.
Um die Funktion eines Vielweg-Suchbaums zu verstehen, betrachten wir noch einmal die Struktur eines Knotens in einem binären
Suchbaum. Der in einem Knoten enthaltene Schlüsselwert s teilt den
Schlüsselwertbereich in zwei Intervalle. Alle Schlüsselwerte, die im
linken bzw. rechten Unterbaum vorkommen, liegen im unteren bzw.
oberen Intervall.
Ein Vielweg-Suchbaum verallgemeinert nun die Idee des binären
Suchbaums dahingehend, nicht nur zwei Intervalle des Schlüsselwertbereichs und zugehörige Unterbäume zu haben, sondern n > 2. Für
einen Vielweg-Suchbaum gilt daher:
– Ein Knoten besteht aus
– n Verweisen auf Teilbäume T1 , ..., Tn und
– n − 1 Schlüsselwerten s1 , ..., sn−1 und zugehörigen Inhalten.
s1
T1
s2
T2
s3
T3
s4
T4
T5
– Die Schlüsselwerte s1 , ..., sn−1 teilen den gesamten Schlüsselwertbereich in n Intervalle auf. Deshalb bezeichnen wir sie oft als Trennschlüsselwerte. Sei Ki die Menge der im Teilbaum Ti auftretenden Schlüsselwerte. Alle x ∈ Ki liegen im i-ten Intervall, also:
62
B-Bäume
– ∀x ∈ K1 :
x < s1
– ∀x ∈ Ki , 1 < i < n : si−1 < x < si
– ∀x ∈ Kn :
sn−1 < x
Der Platzbedarf für einen Knoten eines Vielweg-Suchbaums steigt
linear mit n an. Bei gegebener Blockgröße und gegebenem Platzbedarf für eine Medienadresse, einen Schlüsselwert und einen Satzinhalt
(s.o.) kann man die Zahl der Schlüsselwerte, die maximal in einen
Block passen, mit folgender Formel berechnen:
⌊(b − t)/(k + i + t)⌋
In unserem obigen Beispiel (b=2048; t=8; k=8; i=110) ergibt sich
n=16.
2.3.3
Merkmale von B-Bäumen
B-Bäume sind spezielle Vielweg-Suchbäume. Ihre besonderen Eigenschaften sind:
1. Alle Knoten mit Ausnahme der Wurzel sind wenigstens zur Hälfte
gefüllt.
Man spricht von einem B-Baum der Ordnung m, wenn in jedem
Knoten (mit Ausnahme der Wurzel) mindestens m und maximal 2m
Schlüsselwerte auftreten.
Für die Wurzel gilt: entweder ist sie ein Blatt (d.h. der Baum
hat ≤ 2m Knoten), oder sie hat wenigstens 2 Unterbäume.
2. Alle Pfade von der Wurzel zu einem Blatt sind gleich lang.
3. Ein innerer Knoten mit n Schlüsselwerten hat n+1 nichtleere Unterbäume, d.h. innere Knoten haben keine leeren Unterbäume.
Bild 2.1 zeigt einen B-Baum der Ordnung 2.
Abschätzung der Suchgeschwindigkeit: B-Bäume sind sehr effiziente Datenstrukturen, die Zeit zum Auffinden eines Datenelements
anhand seines Schlüsselwerts hängt nur logarithmisch ab von der Zahl
der Datenelementen in dem B-Baum. Um dies zu zeigen, untersuchen
B-Bäume
63
12
2 5
34
17 19
76
42 50 59 70
83 102
Abbildung 2.1: B-Baum der Ordnung 2
wir zunächst, wieviele Schlüsselwerte bzw. Sätze ein Baum der Höhe
h und Ordnung m mindestens enthält.
Ebene
wenigstens
2 Teilbäume
0
1
Sei h die Höhe des B-Baums (also
die Zahl der Ebenen ohne Wurzelebene). Dann ist die Zahl der
Knoten eines Teilbaums der Ebene 1
2
jeweils > m Teilbäme
h
=
=
1 + (m + 1) + (m + 1)2 +
.... + (m + 1)h−1
(m+1)h −1
(m+1)−1
Die Zahlh der in einem Teilbaum der Ebene 1 enthaltenen Schlüssel
−1
h
ist m∗ (m+1)
(m+1)−1 = (m + 1) − 1. Da mindestens 2 Teilbäume der Ebene
1 vorhanden sind, enthält der gesamte Baum n > 2 ∗ ((m + 1)h − 1) + 1
Schlüssel. Wenn wir diese Formel nach h auflösen, erhalten wir:
h ≤ logm+1
n+1
2
Beispiel:
Für n = 1.000.000 Sätze und m = 8 ergibt sich
1000000+1
h ≤ log9
≈ 5.97 bzw. aufgerundet h < 6. Für das Durch2
laufen des Baumes von der Wurzel bis zu einem Blatt werden also
maximal 7 Seitenzugriffe benötigt.
2.3.4
Primärschlüssel
Bei einem B-Baum bilden die Daten zur Realisierung der Baumstruktur und die Nutzdaten eine untrennbare Einheit. Anders gesehen sind
64
B-Bäume
die Indexstrukturen in Primärdaten eingebettet. Man spricht deshalb
hier von einem Primärindex.
Der durch den Primärindex unterstützte Suchschlüssel wird Primärschlüssel genannt.
Da die Einträge im B-Baum in aufsteigender Reihenfolge gemäß
dem Primärschlüssel sortiert sind, ist für einen Datenbestand nur ein
Primärindex möglich.
2.4
Algorithmen
Im folgenden beschreiben wir die Algorithmen, mit denen die Verzeichnis-Operationen in einem B-Baum realisiert werden.
Bei Bäumen als Suchstrukturen steht man immer von dem Problem, daß der Suchbaum degenerieren kann, wenn z.B. Elemente in
sortierter Reihenfolge eingefügt werden. Die Suchzeiten können dadurch sehr schlecht werden. B-Bäume adressieren dieses Problem dadurch, daß der Baum balanciert wird.
2.4.1
Suche
Der Suchalgorithmus ist eine direkte Verallgemeinerung des Suchalgorithmus für binäre Bäume: bei binären Bäumen durchläuft man den
Baum von der Wurzel aus und wandert bei einem Knoten, der den
Schlüsselwert s enthält, in den linken bzw. rechten Teilbaum, wenn der
gesuchte Eintrag einen Schlüsselwert < s bzw. > s ist. Die Teilbäume
stehen für die Schlüsselbereichsintervalle [0,s) und (s,∞]. Anders
gesagt wandert man in dasjenige Intervall, in dem der gesuchte Eintrag
liegen muß. Analog geht man bei Vielweg-Suchbäumen vor, nur daß
hier mehrere (disjunkte) Intervalle zur Auswahl stehen.
2.4.2
Einfügung
Die grundlegende Vorgehensweise bei insert(v,s,i) ist:
– Knoten suchen, in dem Satz mit Schlüsselwert s sein müßte
– Satz mit Schlüsselwert s und Inhalt i dort einfügen
B-Bäume
65
– wenn 2m+1 Sätze in der Seite, dann Überlaufbehandlung
Das eigentliche Problem - insb. hinsichtlich der Balancierung des
Baums - ist also die Überlaufbehandlung. Bäume wachsen normalerweise nach unten10 . Der geniale Einfall bei B-Bäumen besteht darin,
den Baum zunächst in die Breite und ggf. oben an der Wurzel wachsen
zu lassen. Im einzelnen wird ein Überlauf wie folgt behandelt:
– Wir fügen den Satz gedanklich an der richtigen Stelle im Knoten ein
(in Wirklichkeit geht das nicht, weil der Knoten nur 2m Einträge
aufnehmen kann), so daß jetzt 2m+1 Sätze vorhanden sind.
– den übergelaufenen Knoten teilen wir in zwei neue, minimal gefüllte Knoten mit jeweils m Sätzen auf; der eine enthält die Sätze 1 bis
m, der andere die Sätze m+2 bis 2m+1 (s. Bild 2.2)
..... x
s 1 ..... s m
s m+1
übergelaufener
Knoten
y .....
s m+2 ..... s 2m+1
..... x
s 1 ..... s m
s m+1
y .....
s m+2 ..... s 2m+1
Abbildung 2.2: Überlaufbehandlung
– Im Elternknoten des übergelaufenen Knotens wird der bisher vorhandene Verweis auf den übergelaufenen Knoten ersetzt durch (a)
zwei Verweise auf die beiden neuen Knoten und (b) den mittleren
(m+1.) Satz, der den Trennschlüssel für die beiden neuen Teilbäume
enthält. Im Elternknoten ist danach die Zahl der Sätze um 1 erhöht.
10
Dies gilt natürlich nur in der Informatik, wo Bäume unnatürlicherweise die
Wurzel “oben” haben.
66
B-Bäume
– Falls auch der Knoten in der nächsthöheren Ebene überläuft, wird
auch dieser Überlauf nach dem gleichen Schema behandelt. Der
Überlauf kann sich so nach oben bis zur Wurzel fortsetzen.
Im Extremfall läuft die bisherige Wurzel über, und der Baum
wächst um eine Ebene. Er wächst also an der Wurzel!
2.4.3
Löschung
Die grundlegende Vorgehensweise in delete(v,s) ist:
– Knoten N suchen, in dem der Satz mit Schlüsselwert s enthalten ist
(Fehler, falls nicht vorhanden)
– sofern N ein Blatt ist, den Satz dort löschen. Andernfalls, also
wenn N ein innerer Knoten ist, den zu löschenden Satz dort mit
dem nächsten Satz überschreiben (der nächste Satz hat den nächstgrößeren nach s auftretenden Schlüsselwert; er steht im “rechts folgenden” Unterbaum im Blatt “unten links”); anschließend diesen
nächsten Satz löschen und Knoten N – nunmehr ein Blatt – entsprechend neu festlegen.
– sofern N nur noch m-1 Sätze enthält und nicht die Wurzel ist, Unterlaufbehandlung durchführen.
Das entscheidende Problem bei Löschungen ist natürlich, ein Degenerieren des Baums zu verhindern. Analog zur Überlaufbehandlung
gehen wir hier so vor, daß wir zunächst die Breite des Baumes reduzieren und ggf. sogar die Höhe. Ein Unterlauf wird nach folgendem
Verfahren behandelt:
– sofern es einen Nachbarknoten von N mit k + m, k ≥ 1, Sätzen gibt
(oBdA sei dies der rechte Nachbar; wir bezeichnen ihn i.f. mit R),
Ausgleich zwischen N und R durchführen
– andernfalls Verschmelzen von N und R
B-Bäume
67
Ausgleich zwischen N und R: Die naheliegende Idee ist hier, den
untergelaufenen Knoten aufzufüllen mit Sätzen, die einer der Nachbarn
entbehren kann11 . Konkret gehen wir wie folgt vor (s. Bild 2.3):
x
N
... m−1 ...
y
... s ...
R
... m ...
N
.. m−1 .. x .. s1 ..
R
.. s2 .. ... m ...
.. s1 .. y .. s2 ..
Abbildung 2.3: Unterlaufbehandlung
– Der Satz (mit Schlüsselwert x) im Elternknoten von N, der Verweise
auf N und R abgrenzt, wird nach N verschoben.
– Wenn R insg. k+m Sätze enthält, dann (k-1)/2 (ab- oder aufgerundet) Sätze aus R an das Ende in N verschieben
– nächsten Satz aus R im Elternknoten als neuen Trennsatz zwischen
N und R eintragen
Verschmelzen von N und R: In diesem Fall enthalten N und R m-1
bzw. m Sätze. Zusammen mit dem Satz im Elternknoten, der die
Einträge für N und R trennt, haben wir genau 2m Sätze. Diese Sätze
bilden einen neuen Knoten, der die bisherigen Knoten N und R ersetzt.
Im Elternknoten reduziert sich die Zahl der Einträge hierdurch um 1.
Sofern im Elternknoten ebenfalls ein Unterlauf eintritt, wird dieser
nach dem gleichen Schema wie der ursprüngliche Unterlauf behandelt.
Dies kann sich rekursiv bis zur Wurzel fortsetzen. Im Extremfall wird
die Wurzel gelöscht und die Höhe des Baums sinkt um eine Ebene.
11
Die Idee des Ausgleichs liegt auch beim Einfügen nahe, d.h. man könnte einen
übergelaufenen Knoten zunächst mit einem schlecht gefüllten Nachbarknoten ausgleichen. Dies führt aber zu vielen fast vollen Blöcken und macht Blocküberläufe
häufiger, speziell unter der meist zutreffenden Annahme, daß ein Datenbestand
tendenziell wächst. Blocküberläufe sind jedoch unerwünscht, da statt einem Block
mit einem Blattknoten zwei geschrieben werden müssen (sowohl beim Ausgleich als
auch bei einer Teilung); zusätzlich ist wenigstens ein innerer Knoten zu behandeln.
68
B-Bäume
x
N
... m−1 ...
R
... m ...
N
.. m−1 .. x ... m ...
R
(freigeben)
Abbildung 2.4: Verschmelzung
2.4.4
Beispiel
Als Beispiel betrachten wir einen B-Baum mit Ordnung 2. Ausgehend
von einem leeren Baum fügen wir wie folgt Sätze ein (angegeben sind
immer nur deren Schlüsselwerte).
– Einfügen von Sätzen mit den Schlüsselwerten 50, 102, 34, 19 und 5.
Bei der letzten Einfügung läuft der bisher einzige Knoten über (im
folgenden Bild ist links der zu große Knoten gezeigt) und muß geteilt werden. Die Mitte bildet der Schlüsselwert 34; dieser wandert
in die neu zu bildende Wurzel, die linke und rechte Hälfte bilden
jeweils neue Knoten.
34
[5] 19 34 50 102
5 19
50 102
– Nach dem Einfügen von Sätzen mit den Schlüsselwerten 76, 42, 2
und 83 tritt erneut ein Überlauf ein.
34
2 5 19
34
42 50 76 [83] 102
2 5 19
76
42 50
83 102
– Nach dem Einfügen von Sätzen mit den Schlüsselwerten 59, 70, 12
und 17 tritt erneut ein Überlauf ein.
B-Bäume
69
34
76
2 5 12 [17] 19
12
83 102
42 50 59 70
2 5
34
76
42 50 59 70
17 19
83 102
– Wenn nun der Satz mit Schlüsselwert 83 gelöscht wird, kann der betroffene Knoten mit seinem linken Nachbarn ausgeglichen werden.
12
2 5
34
76
12
42 50 59 70
17 19
83 102
34
2 5
70
42 50 59
17 19
76 102
– Wenn der Satz mit Schlüsselwert 2 gelöscht wird, muß der betroffene Knoten mit seinem rechten Nachbarn verschmolzen werden
12
2 5
34
70
42 50 59
17 19
2.5
34
76 102
70
42 50 59
5 12 17 19
76 102
B*-Bäume
Bei der Suche nach einem Satz müssen alle Ebenen eines B-Baums
durchlaufen werden. Für jede Ebene ist je ein Block zu übertragen.
Wie schon früher erwähnt ist die Reduktion der Zahl der Blockübertragungen das wichtigste Optimierungsziel.
Die Höhe des Baums können wir nur reduzieren, wenn wir den
Verzweigungsgrad (bzw. die Ordnung m) erhöhen. In B*-Bäumen
70
B-Bäume
erreicht man dies – unter Inkaufnahme eines geringen Ausmaßes an
Redundanz – dadurch, daß in den inneren Knoten der Baumstruktur nur die Schlüsselwerte gespeichert, der Satzinhalt also weggelassen
wird. Komplette Sätze (Schlüsselwert und Inhalt) stehen stehen nur
noch in den Blättern der Baumstruktur, also der untersten Ebene.
Alle Nicht-Blattknoten sind reine Indexknoten.
Der Satz, der zu einem Schlüsselwert gehört, der in einem NichtBlattknoten auftritt, kann z.B. jeweils im “rechts” anschließenden Unterbaum untergebracht werden. Der Unterbaum zwischen zwei Trennschlüsseln s1 und s2 enthält also alle auftretenden Schlüsselwerte im
halboffenen Intervall [s1,s2). Wenn bei der Suche ein Schlüsselwert
in einem Nicht-Blattknoten gefunden wird, muß dementsprechend im
“rechts” anschließenden Unterbaum weitergesucht werden.
Die Schlüsselwerte in den inneren Knoten werden in den Blättern
noch einmal gespeichert. Es liegt somit in geringem Ausmaß Redundanz vor (Schlüsselwerte sind i.a. kurz).
Der entscheidende Vorteil von B*-Bäumen liegt darin, daß wesentlich mehr Einträge in einen Block passen. Hierzu betrachten wir erneut
unser früheres Beispiel in Abschnitt 2.3.2. Mit i=0 (wegen des fehlenden Satzinhalts) und den unveränderten Werten b=2048, t=8 und k=8
und ergeben sich (b-t)/(k+i+t) = 127 Einträge pro Block.
Für die Höhe des Suchbaums aus
in Abschnitt 2.3.3
dem Beispiel
1000000+1
≈ 2.8, d.h. wir sparen
ergibt sich bei nunmehr h ≤ log128
2
rund die Hälfte der Blockübertragungen ein.
Bei B*-Bäumen wird ferner im Vergleich zu B-Bäumen die Zahl
der Nicht-Blattknoten erheblich reduziert, im vorstehenden Beispiel
ca. um den Faktor 8. Hierdurch ist es fast immer möglich, alle inneren
Knoten im Hauptspeicher zu puffern, d.h. bei einer Suche brauchen
keine Indexblöcke übertragen zu werden, sondern nur noch ein einziger (Daten-) Block! Dieser Wert kann nicht weiter verbessert werden.
Ein weiterer Vorteil von B*-Bäumen besteht darin, daß Sätze variabler Länge leicht handhabbar sind.
Aufgrund der diversen Vorteile werden in der Praxis nur B*-Bäume
eingesetzt.
B-Bäume
71
Glossar
B-Baum: entweder abstrakte Implementierung des generischen abstrakten
Datentyps Verzeichnis oder konkrete Implementierung für konkrete
Basisdatentypen
B*-Baum: Variante des B-Baums, bei der Nutzdaten nur auf der untersten
Baumebene gespeichert werden und alle oberen Ebenen reine Indexknoten enthalten
generischer abstrakter Datentyp: abstrakter Datentyp, in dessen
Schnittstelle, insb. bei den Parametern der Operationen, ein Basisdatentyp (ggf. auch mehrere) offenbleibt; durch Einsetzen eines
konkreten Basisdatentyps wird der generische abstrakte Datentyp zu
einem einfachen abstrakten Datentyp, von dem Instanzen gebildet
werden können
Ordnung (eines B-Baums): Minimalzahl der Trennschlüssel in einem Knoten; die Maximalzahl ist genau doppelt so hoch
Überlauf (beim Einfügen in einen B-Baum): Überschreiten der Maximalzahl an Einträgen in einem Knoten eines B-Baums
Unterlauf (beim Löschen in einem B-Baum): Unterschreiten der Minimalzahl an Einträgen in einem Knoten eines B-Baums
Verzeichnis (directory): generischer abstrakter Datentyp mit zwei Basisdatentypen, die den Schlüsselwertebereich bzw. den Inhalt eines Eintrags
definieren; grundlegende Operationen sind das Einfügen, Löschen und
Auslesen von Einträgen; optional sind Operationen für ein sequentielles Durchlaufen bzw. Auslesen mehrerer Einträge
Vielweg-Suchbaum: Suchbaum, der den binären Suchbaum insofern verallgemeinert, daß jeder Knoten nicht nur einen, sondern n Einträge
bzw. (Trenn-) Schlüsselwerte enthält, und nicht 2, sondern n+1 Unterbäume hat; die n+1 Unterbäume enthalten Einträge mit solchen
Schlüsselwerten, die vor dem ersten, zwischen dem i-ten und i+1-ten
bzw. nach dem letzten Trennschlüsselwert liegen
Lehrmodul 3:
Architektur von DBMS
Zusammenfassung dieses Lehrmoduls
Dieses Lehrmodul gibt eine erste Einführung in die Architektur
von DBMS. Einleitend betrachten wir ein DBMS aus einer Gesamtsicht und konzentrieren uns dann auf zwei wichtige Aspekte des
DBMS-Kerns: (a) wir zeigen, daß i.d.R. der Datenbankkern als eigener Hintergrundprozeß ausgeführt werden muß, und wir diskutieren
die Konsequenzen hinsichtlich der Performanceoptimierung. (b) Wir
skizzieren, in welchen Stufen die Datenobjekte, mit denen das Datenbankmodell operiert, auf Datenstrukturen im Hauptspeicher und
letztlich auf Magnetplatten oder anderen persistenten Speichermedien
abgebildet werden.
Vorausgesetzte Lehrmodule:
obligatorisch:
empfohlen:
– Datenverwaltungssysteme
– Schnittstellen zu Datenbankinhalten
Stoffumfang in Vorlesungsdoppelstunden:
Stand: 21.10.2005
1.0
c
2005
Udo Kelter
Architektur von DBMS
3.1
73
Einleitung
Dieses Lehrmodul gibt einen ersten Einblick in den Aufbau und die
Struktur eines DBMS.
Der Begriff Architektur ist mehrdeutig (eine allgemeinere Diskussion dieses Begriffs findet sich in [SAR]); wir werden hier primär
die Software-Komponenten betrachten, aus denen ein DBMS besteht.
Hierbei kann es sich sowohl um selbständig lauffähige Programme als
auch um Schichten innerhalb von Programmen, insb. dem Laufzeitkern, handeln. Wir werden hier ebenfalls auf die Prozeßarchitektur,
also die Struktur der Prozesse zur Laufzeit, eingehen.
Es gibt keine Einheitsarchitektur, die bei allen DBMS gleichartig
anzutreffen wäre, noch nicht einmal bei einer vergröberten Betrachtung. Die Architektur eines DBMS hängt ganz erheblich von mehreren
Faktoren ab:
– natürlich vom Datenbankmodell, hier insb. davon, ob ein navigierendes oder ein mengenorientiertes Datenbankmodell vorliegt
– von der Art, wie Applikationen an das DBMS angebunden werden
(s. Lehrmodul ??)
– von den ggf. vorhandenen Verteilungskonzepten
– von der “Größenklasse” und damit zusammenhängend den Optimierungszielen.
3.2
Produkt vs. Laufzeitkern
Wenn man ein DBMS-Produkt kauft, wird man auf der InstallationsCD eine (erschreckend) hohe Zahl von Programmen finden, die man
wie folgt gruppieren kann:
– Laufzeitkern: diese Programme und Programmteile (Bibliotheken)
werden während der “produktiven” Nutzung des DBMS ausgeführt.
– Administrations- und Dienstprogramme (s. auch Bild 1.3) für diverse Zwecke:
– Installation
74
Architektur von DBMS
– Überwachung des laufenden Betriebs und Gewinnung von statistischen Daten
– Performance-Tuning
– Sicherheitsüberwachung
– Backup der Datenbank, Verwaltung von Tertiärspeichermedien,
Prüfen und ggf. Reparieren der Datenbank
– Benutzeradministration
– Verwaltung registrierter Anwendungen
– Accounting
– Programme, die Entwicklung von Applikationen unterstützen; man
kann diese als eine angepaßte Software-Entwicklungsumgebung ansehen. Beispiele sind Präprozessoren, die in Quelltexte eingebettete
Anweisungen vorübersetzen, oder Editoren, mit denen man die Datenbankschemata spezifizieren und dokumentieren kann.
Die Abgrenzung zwischen den Dienstprogrammen und den Entwicklungswerkzeugen ist nicht ganz scharf. Wenn separate Entwicklungs- und “Produktions”rechner benutzt werden, sind die Entwicklungswerkzeuge typischerweise nur auf dem Entwicklungsrechner installiert.
Dienstprogramme und Entwicklungswerkzeuge sind zwar für die
praktische Nutzung von DBMS sehr wichtig, auf sie wird aber in Vorlesungen und Lehrbüchern über Datenbanken fast nicht eingegangen
– so auch hier. Allgemeine Kenntnisse über Datenmodelle und Kenntnisse über die Laufzeitkerne haben insofern höhere Priorität, als sie
bei der Behandlung der Dienstprogramme und Entwicklungswerkzeuge stets vorausgesetzt werden müssen.
3.3
Prozeßarchitektur von Informationssystemen
Informationssysteme kann man i.d.R. in 3 Softwareschichten strukturieren (s. Bild 1.1):
Architektur von DBMS
75
– GUI / Benutzerinteraktion
– Realisierung der Fachkonzepte, Applikationssemantik
– Datenverwaltung
Im einfachsten Fall kann man die zugehörigen Module zu einem
einzigen Programm zusammenbinden, d.h. diese Module würden in
den virtuellen Hauptspeicher eines Betriebssystemprozesses geladen
und dort gemeinsam ausgeführt. Hinsichtlich der Ziele, die durch den
Einsatz von DBMS angestrebt werden, hätte eine solche 1-ProzeßArchitektur aber gravierende Nachteile:
– Das DBMS kann aus Performancegründen nicht nur auf den persistenten Medien (also Platten) arbeiten, sondern muß große Teile der
Datenbank in Puffer in den Hauptspeicher laden und primär auf diesen Pufferinhalten arbeiten. Nun war es ein Ziel von DBMS, vielen
Benutzern und Applikationen gleichzeitig Zugriff auf die Datenbank
zu ermöglichen. Dies würde bei einer 1-Prozeß-Architektur bedeuten, daß jede Applikation eigene Puffer hätte und daß dort Teile der
Datenbank lägen, die ggf. schon gegenüber dem Zustand auf der
Platte verändert worden sind. Wollte eine andere Applikation jetzt
auf diese Teile der Datenbank zugreifen, müßte sie herausfinden, ob
eine und ggf. welche andere Applikation diese Teile der Datenbank
gerade puffert und sich an diese Applikation wenden. Jedes Applikationsprogramm müßte also gleichzeitig als Server für die zufällig
gerade in seinen Puffern befindlichen Teile der Datenbank arbeiten.
Dies ist völlig inpraktikabel.
– Ein weiteres Ziel von DBMS bestand darin, Zugriffskontrollen zu
realisieren, d.h. nicht autorisierten Benutzern den Zugang auf bestimmte Daten zu verwehren. Bei einer 1-Prozeß-Architektur können solche Dienste aber nicht sicher implementiert werden (zumindest bei allgemein verfügbaren Programmiersprachen und Betriebssystemen). In fast allen gängigen höheren Programmiersprachen
und erst recht in maschinennahen Sprachen können Zeiger manipuliert werden, und es kann im Prinzip auf beliebige Adressen im
(virtuellen) Hauptspeicher zugegriffen werden. Dies bedeutet, daß
die Applikation auch direkt auf die Inhalte der Datenbankpuffer
76
Architektur von DBMS
zugreifen und dort Daten auslesen und verändern könnte, d.h. die
Zugriffskontrollmechanismen sind umgehbar.
– Unkontrollierte Zugriffe des Applikationsprogramms könnten darüber hinaus interne Datenstrukturen des DBMS zerstören und so
zu Programmabstürzen führen.
Die einzige praktikable Alternative, das DBMS und die Datenbankpuffer vor direkten Zugriffen durch die Applikation zu schützen, besteht darin, diese Programme bzw. Daten in einen separaten Betriebssystemprozeß zu laden, s. Bild 3.1. Aus der Sicht von Applikationen ist diese Verlagerung des DBMS-Laufzeitkerns in einen anderen
Prozeß i.w. nicht sichtbar, denn das API zum DBMS bleibt völlig
unverändert. “Hinter dem API” liegt aber jetzt keine Implementierung mehr, sondern eine Bibliothek oder ein RPC- (remote procedure
call) Mechanismus, der die Operationsaufrufe i.w. unverarbeitet an
den Serverprozeß sendet, welcher die eigentliche Operation ausführt
und die Ergebnisse zurücksendet.
[G]UI der
Applikations-
DBMS-
Applikation
Server
Server
Appl-API
Bibliothek
DBMS-API
Bibliothek
Datenbank
Abbildung 3.1: Prozeßarchitektur von Informationssystemen
Aus Performance-Gründen kann es sinnvoll sein, auch das GUI und
die Applikationssemantik verschiedenen Prozessen zuzuordnen; es ergibt sich dann die in Bild 3.1 gezeigte Struktur mit 3 Prozessen.
Für die technische Realisierung eines solchen entfernten Operationsaufrufs gibt es diverse Alternativen, die nicht hier, sondern im
Architektur von DBMS
77
Rahmen von Vorlesungen über Rechnernetze behandelt werden. Die
Merkmale dieser Mechanismen sind für unsere Diskussion weitgehend
irrelevant bis auf die beiden folgenden Punkte:
– Wenn ein Applikationsprogramm gestartet wird, muß es herausfinden können, ob schon ein Serverprozeß für die Datenbank läuft und
wie es Kontakt zu diesem Serverprozeß aufnehmen kann. Hierzu
müssen Hilfssysteme verfügbar sein, die entsprechende Auskünfte
geben können und den Verbindungsaufbau teilweise automatisieren. Die Struktur dieser Hilfssysteme hängt stark von der Kommunikationstechnologie ab, die eingesetzt wird. Insgesamt ist die
Installation und Benutzung eines DBMS im Vergleich zu Dateien
dadurch wesentlich komplizierter und erfordert Kenntnisse in der
gewählten Kommunikationstechnologie.
– Ein entfernter Operationsaufruf ist deutlich ineffizienter als ein lokaler. Ein lokaler Operationsaufruf innerhalb eines Programms verursacht einen Aufwand, der je nach Umfang der Parameter in der
Größenordnung von einigen Dutzend oder hundert Maschineninstruktionen, bei heutigen Prozessoren also in der Größenordnung
von Mikrosekunden liegt. Bei einem entfernten Operationsaufruf
sind zwei Fälle zu unterscheiden:
1. Der Serverprozeß läuft auf dem gleichen Rechner: in diesem
Fall werden zuerst die Parameter geeignet codiert, der aufrufende Prozeß wird stillgelegt, der wartende Serverprozeß wird
aktiviert, er entpackt die Parameter und führt die gewünschte Operation aus. Nach Beendigung der Operationsausführung
werden umgekehrt die Ergebnisse an den aufrufenden Prozeß
zurücktransferiert. Die beiden Prozeßwechsel und die beiden
Datenübertragungen kosten typischerweise Rechenzeit in der
Größenordnung von 0.1 Millisekunden.
2. Der Serverprozeß läuft auf einem anderen Rechner. In diesem
Fall kommt bei beiden Kommunikationen der Kommunikationsaufwand hinzu; hier muß mit einem Mindestaufwand in der
Größenordnung von 1 Millisekunde (bei langsamen Netzen auch
mehr) gerechnet werden, ferner ist die Übertragungsbandbreite
78
Architektur von DBMS
signifikant kleiner.
Hieraus folgt bereits, daß ein entfernter Aufruf bedeutend teurer (Faktor: ca. 1000 bis 10000) ist als ein lokaler und daß man
sich in interaktiven Systemen, die gute Antwortzeiten haben sollen, nur wenige (Größenordnung 10 bis 100) Datenbankzugriffe pro
Interaktion leisten kann.
Sofern die Menge der als Eingabeparameter oder Rückgabewerte
übertragenen Daten in der Größenordnung von einigen kB liegt, hat
sie auf diese Zeiten praktisch keinen Einfluß, erst bei deutlich größeren Datenmengen oder sehr langsamen Netzwerken beeinflußt sie
die Gesamtzeit proportional zum Übertragungsvolumen. Hieraus
folgt als weitere Erkenntnis, daß es performanter ist, wenige umfangreichere Operationen aufzurufen als viele kleine.
3.4
3.4.1
Eine Abstraktionshierarchie von Datenbankobjekten
Übersicht
Jedes DBMS muß letztlich die Datenstrukturen seines Datenbankmodells auf Basis des unterliegenden Dateisystems oder, bei direktem Zugriff auf die Hardware, der Platten realisieren. Die Diskrepanz dieser
beiden Denkwelten ist erheblich, daher wird diese Realisierung typischerweise in mehrere Schritte eingeteilt, bei denen - von unten nach
oben gesehen - jeweils ein neuer Typ von internen Speichereinheiten
realisiert wird. Man kann sich diese Schichtung durch mehrere aufeinander aufbauende Pakete veranschaulichen (s. Bild 3.2)12 . Wir skizzieren i.f. ein derartiges Schichtenmodell für interne Speichereinheiten
bzw. Datenbankobjekte und gehen anschließend im Detail auf die
Schichten ein:
– Die unterste Ebene operiert mit Blöcken, die über Medienadressen
12
Reale DBMS-Kerne sind deutlich komplizierter, insofern ist dieses Bild keine
exakte, sondern allenfalls eine partielle und vereinfachende Darstellung der Architektur eines DBMS-Kerns.
Architektur von DBMS
79
Ebene 4: n-Tupel/Objekte
Ebene 3: 1-Tupel/Objekt
Ebene 2: Speichersätze
Ebene 1: Segmente/Seiten
Ebene 0: physische Blöcke
Abbildung 3.2: Abstraktionshierarchie von Datenbankobjekten
identifiziert werden und die zwischen den permanenten Medien und
dem Arbeitsspeicher übertragen werden.
– Auf Ebene 1 wird die durch die Hardware vorgegebene Menge der
Blöcke zu Segmenten gruppiert. Segmente ähneln insofern Dateien,
als sie angelegt und gelöscht werden können und ihre Größe (also
die Menge zu zugeordneten Blöcke) wachsen oder schrumpfen kann.
– In Ebene 2 wird der Inhalt einzelner Segmente, der sich auf Ebene 1 noch als Folge von Seiten darstellt, feinkörniger strukturiert,
typischerweise als Folge oder Verzeichnis von (Speicher-) Sätzen.
Integriert hierin sind (primäre) Indexe, z.B. B*-Bäume.
– In Ebene 3 wird der Inhalt einzelner Sätze, der sich auf Ebene 2
noch als unstrukturiertes Bytefeld darstellt, in Felder strukturiert,
die den Attributen von Tupeln oder Objekten entsprechen. Auf
dieser Ebene werden die konzeptuellen Schemata in konkrete Speicherstrukturen umgesetzt.
– Während Ebene 3 Operationen realisiert, die mit einzelnen Tupeln
oder Objekten arbeiten, realisiert Ebene 4 Operationen mit Mengen von Objekten. Dieser Ebene ist u.a. der Problemkomplex der
Optimierung zuzuordnen.
80
Architektur von DBMS
Wir betrachten i.f. die Ebenen detaillierter und beginnen bei der
Hardware als unterster Ebene.
3.4.2
Ebene 0: physische Blöcke
Ein physischer Block ist ein Datenbereich auf einem Permanentspeicher wie Magnetplatte, optische Platte, Band usw., dessen (Netto-)
Inhalt von der Hardware und den zugehörigen Treibern zwischen dem
Speichermedium und dem Hauptspeicher transportiert werden kann.
Normalerweise werden physische Blöcke nur durch das Dateimanagementsystem des Betriebssystems verwaltet, d.h. Anwendungsprogramme können überhaupt nicht direkt damit arbeiten, sondern arbeiten
nur mit Dateien, die bereits eine eigene Abstraktionsschicht oberhalb
der physischen Blöcke darstellen. Die von Betriebssystemen realisierten Dateisysteme sind allerdings nicht optimal angepaßt an den Bedarf
von DBMS, daher umgehen manche DBMS das Betriebssystem und
greifen “direkt” auf die Platte zu.
Für uns sind nur zwei Operationen mit physischen Blöcken relevant, nämlich den Transport vom Medium in einen Hauptspeicherbereich und umgekehrt. Für die Speicherung einer Datenbank eignen
sich nur solche Medien, bei denen man direkt, also schnell, auf jeden vorhandenen physischen Block zugreifen kann. Hierzu hat jeder
Block, der auf dem Medium vorhanden ist, eine eindeutige Medienadresse. Die Gesamtmenge der Blöcke auf einem Medium hängt
von dessen Hardware-Eigenschaften und ggf. von Parametern bei der
Formatierung des Mediums ab.
3.4.3
Ebene 1: DB-Segmente und DB-Seiten
Aus Sicht der höheren Schichten besteht der auf Ebene 1 realisierte
persistente Speicher aus mehreren Segmenten. Jedes Segment besteht
aus einer Folge von Seiten. Man kann Segmente anlegen und löschen.
Typischerweise wird z.B. beim Erzeugen einer Relation oder eines Index ein Segment angelegt, das die zugehörigen Daten aufnimmt.
Die Seiten haben eine feste Größe, z.B. 2 kB, diese Größe kann
ggf. beim Anlegen des Segments gewählt werden. Im einfachsten Fall
Architektur von DBMS
81
entspricht eine Seite einem Block, eine Seite kann aber auch mehrere
Blöcke groß sein. Innerhalb eines Segments wird eine Seite durch eine
laufende Nummer identifiziert (Medienadressen sind hier nicht mehr
sichtbar). Segmente können “hinten” seitenweise wachsen oder gekürzt
werden.
über die Seitenummer zusammen mit dem Segmentidentifizierer
kann direkt auf die Seite zugegriffen werden. Hierzu müssen die Blöcke,
die der Seite entsprechen, vorher geladen, d.h. in den Arbeitsspeicher
übertragen werden.
Ein Segment ähnelt einer Datei, wobei ganze Seiten statt einzelner Bytes oder Sätze Übertragungseinheiten sind. Im Gegensatz zu
Dateisystemen kann aber die Identifizierung in einem DBMS weitaus
einfacher gestaltet werden, d.h. wir benötigen hier keine Dateiverzeichnisse oder Zugriffskontrollen.
Zu jedem Segment verwaltet das DBMS einen Segmentdeskriptor,
der alle relevanten Administrationsdaten enthält. Innerhalb der derselben wird vermerkt, wie Seitennummern und Medienadressen einander
zugeordnet sind; diese Zuordnung kann sich dynamisch ändern. Ferner
werden die freien Blöcke auf den Medien verwaltet. Für die höheren
Schichten ist nicht mehr erkennbar, an welcher konkreten Medienadresse eine Seite steht.
Die vorstehend beschriebene Struktur nennt man auch Zugriffsmethode für Seiten13 .
3.4.4
Ebene 2: Zugriffsmethode für Sätze
Diese Schicht simuliert sozusagen die Speichereinheit Satz bzw. Zeichen auf der Speichereinheit Seite. Eine Seite enthält i.a. mehrere
Sätze.
Sätze sind als Speichereinheit in DBMS deutlich wichtiger als Zeichen (bei Zugriffsmethoden in Betriebssystemen ist es umgekehrt).
13
In manchen Betriebssystemen wird eine solche Zugriffsmethode direkt für Anwendungen nutzbar angeboten, in anderen Betriebssystemen existiert sie nur intern,
während auf ihrer Basis für Anwendungen Zugriffsmethoden für Zeichen oder Sätze
angeboten werden.
82
Architektur von DBMS
Aus Sicht der höheren Schichten besteht ein Segment nunmehr aus
einer Menge von Sätzen bzw. Zeichen und einer Zugriffsstruktur.
3.4.4.1
Zugriffsstrukturen
Eine Zugriffsstruktur bestimmt, wie einzelne Speichereinheiten identifiziert und lokalisiert werden können und wie die Menge der Speichereinheiten des Segments verändert werden kann. Eine Zugriffsstruktur
sollte man als generischen abstrakten Datentyp (ähnlich wie Liste,
Array, Baum, Hash-Tabelle usw.) ansehen. Eine konkrete Zugriffsmethode ist also ein abstrakter Datentyp, der aus einer generischen Zugriffsstruktur durch Wahl einer bestimmten Speichereinheit entsteht.
Unter einer Speichereinheit verstehen wir i.f. einen Satz oder ein Zeichen.
Zugriffsstrukturen verstehen wir hier nur als Spezifikationen; für
eine bestimmte Spezifikation kann es unterschiedliche Implementierungen geben. Die Literatur enthält eine unübersehbare Vielfalt konkreter Datenstrukturen und Algorithmen, die einzelne Zugriffsstrukturen
implementieren. Aus Platzgründen können wir hier nur Beispiele skizzieren.
Sequentielle Zugriffsstruktur: Diese Zugriffsstruktur entspricht
einer einfach verketteten Liste von Speichereinheiten. Sie ist auch auf
sequentiellen Medien (Bändern, Bandkassetten) realisierbar.
Nur eine einzige Speichereinheit des Segments ist “aktuell lokalisiert” und damit direkt les- oder schreibbar. Von dort aus kann nur
schrittweise zum nächsten (und ggf. vorigen) Element navigiert werden. Der (effiziente) Direktzugriff zum n-ten Satz ist nicht möglich.
Nur die erste Speichereinheit kann direkt lokalisiert werden, manchmal
auch das Ende, also die Position hinter der letzten Speichereinheit.
Die Folge der Speichereinheiten kann nur am Ende verlängert oder
gekürzt werden, Einfügen oder Löschen in der Mitte ist nicht möglich.
Die wesentlichen Operationen sind somit:
– beim Schreiben eines Segments:
– Überschreiben der aktuell lokalisierten Speichereinheit
Architektur von DBMS
83
– Anhängen einer Speichereinheit am Ende
– beim Lesen eines Segments:
– Abfrage, ob Segmentende erreicht
– Kopieren der lokalisierten Speichereinheit in einen Puffer
Direktzugriffsstrukturen: Bei Direktzugriffsstrukturen können
einzelne Speichereinheiten durch eine Nummer oder einen Schlüsselwert identifiziert werden und “direkt”, d.h. für beliebige Sätze in ungefähr gleicher Zeit, lokalisiert und dann gelesen oder überschrieben
werden, ferner ggf. erzeugt oder gelöscht werden.
Neben dem direkten Zugriff muß natürlich immer auch ein effizienter sequentieller Zugriff durch alle Sätze möglich sein, bei dem jede
Seite nur einmal übertragen werden muß; hier interessiert, ob hierbei
die Sätze in der Reihenfolge geliefert werden, die der aufsteigenden
Reihenfolge ihrer Schlüsselwerte entspricht.
Es gibt i.w. zwei Formen von Direktzugriffsstrukturen: die arrayartige Direktzugriffsstruktur und die Verzeichnisstruktur.
Arrayartige Direktzugriffsstruktur: Diese Zugriffsstruktur entspricht einem hinten dynamisch erweiterbaren Array. Speichereinheiten werden durch laufende Nummern identifiziert. Es gibt Operationen, mit denen man die aktuelle Länge des Arrays abfragen und diese
herauf- oder heruntersetzen kann. Nicht möglich ist das Einfügen einer Speichereinheit zwischen zwei vorhandenen Speichereinheiten. Da
laufende Nummern natürlicherweise sortiert sind, kann man zusätzlich
sehr leicht eine sequentielle Zugriffsstruktur anbieten.
Effizient realisiert werden kann eine arrayartige Direktzugriffsstruktur in Zugriffsmethoden für Zeichen oder Sätze fester Länge, bei
variabler Satzlänge treten Probleme auf. Zugriffsmethoden für Seiten
realisieren übrigens ebenfalls eine arrayartige Direktzugriffsstruktur.
Verzeichnisstruktur: Diese Zugriffsstruktur tritt nur bei Sätzen
als Speichereinheit auf. Jeder Satz hat hier einen zugeordneten
84
Architektur von DBMS
Schlüsselwert14 . Die Schlüsselwerte stammen aus einem Schlüsselwertbereich. Beispiele für Schlüsselwertbereiche sind die ganzen Zahlen von 0 bis 232 -1 oder alle Texte von 8 Zeichen Länge über einem gegebenen Alphabet. Der Schlüsselwertbereich ist i.a. in der Schnittstelle und in der Implementierung der Zugriffsmethode “hart verdrahtet”;
die Schlüsselwerte müssen ja in diversen Operationen als Parameter
übergeben werden. Die Verzeichnisstruktur wirkt auf den ersten Blick
sehr ähnlich wie die arrayartige Direktzugriffsstruktur, dieser Eindruck
täuscht aber. Der entscheidende Unterschied besteht darin,
– daß immer der gesamte, sehr große Schlüsselwertbereich verfügbar
ist, es gibt also keine variable Obergrenze für die gültigen Schlüsselwerte, und
– daß es sein kann, daß zu einem Schlüsselwert aktuell kein Satz
vorhanden ist. I.a. ist sogar nur für einen winzigen Bruchteil der
zulässigen Schlüsselwerte ein Satz vorhanden.
Ein Schlüsselwert identifiziert entweder keinen oder genau einen
Satz in einem Segment. Während bei einer arrayartigen Direktzugriffsstruktur die Nummern der aktuell vorhandenen Speichereinheiten ein
geschlossenes Intervall bilden, können die Schlüsselwerte der aktuell
vorhandenen Sätze bei einer Verzeichnisstruktur beliebig verstreut im
Schlüsselwertbereich liegen.
Daher kommen für Verzeichnisstrukturen keine Implementierungen
in Frage, bei denen sich der Schlüsselwert implizit durch die Position
des Satzes im Segment ergibt, sondern nur solche Implementierungen, bei denen der Schlüsselwert jedes Satzes explizit gespeichert wird.
Binäre Suchbäume und Hash-Tabellen sind bekannte Beispiele für derartige Datenstrukturen im Hauptspeicher. Von diesen grundlegenden
Datenstrukturen gibt es diverse angepaßte und erweiterte Varianten,
die auf die Besonderheiten einer seitenorientierten Speicherung abgestimmt sind, z.B. B-Bäume oder B*-Bäume.
Da B-Bäume auch ein effizientes sequentielles Durchlaufen aller
Sätze in aufsteigender Reihenfolge der vorhandenen Schlüsselwerte er14
Oft wird die Bezeichnung “Schlüssel” als Synonym zu Schlüsselwert benutzt;
dies vermeiden wir hier ganz bewußt.
Architektur von DBMS
85
lauben, spricht man hier auch von einer indexsequentiellen Zugriffsmethode (ISAM; index sequential access method).
Verzeichnisstruktur mit Intervallabfrage: Hier ist im Vergleich
zur normalen Verzeichnisstruktur eine zusätzliche (effizient realisierte) Operation vorhanden, die alle Speichereinheiten liefert, deren
Schlüsselwert zwischen einer unteren und einer oberen Schranke liegt.
3.4.4.2
Realisierung von Sätzen auf Seiten
Wir betrachten hier beispielhaft einige einfache Verfahren, wie die sequentielle Zugriffsstruktur und die arrayartige Direktzugriffsstruktur
auf Seiten effizient realisiert werden kann. Die Verzeichnisstruktur erfordert komplizierte Verfahren, auf die wir hier nicht eingehen.
Die Varianten der Zugriffsmethoden für Sätze unterscheiden sich
darin, ob alle Sätze des Segments gleiche bzw. unterschiedliche Länge
haben. Die zugehörigen Angaben, z.B. die feste Satzlänge oder die
maximale Satzlänge bei variabler Satzlänge, werden innerhalb des Segmentdeskriptors gespeichert.
Anordnung von Sätzen fester Länge. Bei fester Satzlänge
braucht die Länge eines Satzes nicht bei jedem Satz gespeichert zu
werden. Die Speicherabschnitte für je einen Satz können einfach hintereinandergelegt werden. Bild 3.3 zeigt zwei prinzipielle Alternativen:
Seite 1
Satz 1
Satz 2
Seite 2
Satz 3
Satz 4
Seite 1
Satz 1
Satz 2
Seite 3
Satz 5
Satz 6
Seite 2
Satz 3
Satz 4
Seite 3
Satz 5
Satz 6
Abbildung 3.3: Anordnung von Sätzen fester Länge auf Seiten
86
Architektur von DBMS
1. Man bildet gedanklich aus den Inhalten der Seiten einen durchgehenden Adreßraum und legt die Sätze dicht in diesen Adreßraum (s.
Bild 3.3 oben). Nachteilig ist hier, daß ein Satz ggf. nicht komplett
in einer Seite liegt und daß, um einen solchen Satz zu lesen oder zu
schreiben, zwei Blöcke übertragen werden müssen, sofern eine Seite
einem Block entspricht.
2. Man legt nur so viele Sätze in eine Seite, wie ganz hineinpassen.
Nachteil ist hier der ungenutzte Verschnitt am Ende der Seite.
Der Nachteil der doppelten Blockübertragung ist in den meisten
Fällen gravierender als der des Verschnitts.
Satzanordnung bei variabler Satzlänge. Bei allen Zugriffsmethoden für variable Satzlänge steht man (unabhängig von der Zugriffsstruktur) vor dem Problem, daß die Länge jedes einzelnen Satzes in
irgendeiner Form erkennbar sein muß. Am einfachsten ist ein Längenfeld vor dem Satz: Die ersten 2 oder 4 Bytes eines Satzes enthalten
dessen Länge als Binärzahl. Die tatsächliche Länge des Satzes wird
i.d.R. noch auf ein ganzes Vielfaches von 4 oder 8 aufgerundet.
Die Sätze können z.B. analog zu Sätzen fester Länge hintereinander
in der Seite stehen (s. Bild 3.3 unten).
Bei variabler Satzlänge entsteht prinzipiell das Problem, daß
– der noch freie Platz innerhalb der Seite verwaltet werden muß
– wenn Sätze verlängert oder neu eingefügt werden, eine Seite überlaufen kann
– wenn Sätze verkürzt oder gelöscht werden, der Füllungsgrad der
Seite schlecht werden kann
– die Zahl der Sätze pro Seite variabel ist und daher die Seite, in der
sich der i-te Satz eines Segments befindet, nicht berechnet werden
kann.
3.4.4.3
Indexe
Indexe sind generell Datenstrukturen, die einen effizienten Zugriff zu
Daten ermöglichen, die durch einen gegebenen Attributwert identifiziert werden. Bei manchen Zugriffsmethoden sind Indexe in die
Architektur von DBMS
87
Primärdaten integriert; einen solchen Index bezeichnet man auch als
Primärindex. Primärindexe sind also integraler Bestandteil einer
Zugriffsmethode für Sätze.
Indexe können auch unabhängig von den Primärdaten existieren
und heißen dann Sekundärindex. Ein Sekundärindex ist ein Verzeichnis, das zu jedem auftretenden Wert eines Attributs eine Liste
von Referenzen auf die Tupel bzw. Objekte, bei denen dieser Attributwert auftritt, enthält. Während pro Segment nur ein Primärindex
vorhanden sein kann, können beliebig viele Sekundärindexe angelegt
werden.
Naheliegend ist es, für einen Sekundärindex ein eigenes Segment
mit einer Direktzugriffsstruktur anzulegen. Für jeden auftretenden
Attributwert wird ein Satz angelegt,
– dessen Schlüsselwert der Attributwert ist (problematisch können
hier Text-Attribute sein, bei denen die Länge stark variiert) und
– dessen Inhalt die Liste der Referenzen auf die primären Daten ist.
Als Referenzen kommen Primärschlüsselwerte, Surrogate von Objekten oder sogenannte Tupel-Identifizierer in Frage. Wenn man Sekundärindexe auf diese Weise realisiert, bauen sie auf Primärindexen
auf, können also als eigene (Zwischen-) Schicht betrachtet werden.
3.4.5
Ebene 3: Einzelobjekt-Operationen
Diese Ebene exportiert Operationen, die mit einzelnen Tupeln oder
Objekten arbeiten. Ein Tupel oder Objekt wird i.d.R. als Inhalt eines
Satzes gespeichert, die Menge der Tupel einer Relation in den Sätzen
eines Segments.
Die Details (mögliche Attributtypen usw.) hängen vom Datenbankmodell ab. In navigierenden Datenbankmodellen wird insb. die
Navigation zwischen Objekten auf dieser Ebene realisiert, in relationalen Systemen die Behandlung von Cursors.
88
3.4.6
Architektur von DBMS
Ebene 4: Mengen-Schnittstelle
Diese Ebene entfällt weitgehend bei rein navigierenden Datenbankmodellen.
Bei textuellen Schnittstellen muß hier zunächst die textuelle Formulierung einer Anweisung in eine interne Darstellung übersetzt werden. Dies beinhaltet diverse Prüfungen, u.a. der Syntax, des Vorhandenseins von referenzierten Relationen oder Typen, der Zugriffsrechte usw. Im Erfolgsfall wird danach im Rahmen der Optimierung ein möglichst effizient ausführbarer Plan erstellt, der den Auftrag realisiert; entgegen der Bezeichnung “Optimierung” wird allerdings aus Aufwandsgründen nicht versucht, wirklich einen optimalen
Ausführungsplan zu finden, sondern nur anhand von Heuristiken einen
wahrscheinlich recht guten. Der erstellte Plan wird schließlich ausgeführt. Nach Abarbeitung müssen die Ergebnisse entweder in geeigneten Datenstrukturen bereitgestellt werden (bei einem API) oder für
eine externe Darstellung aufbereitet werden.
3.4.7
Beziehung zur 3-Ebenen-Schema-Architektur
In Abschnitt 1.5.2 wurde die 3-Ebenen-Schema-Architektur für DBMS
eingeführt. Diese korreliert lose mit der hier in Abschnitt 3.4 eingeführten Abstraktionshierarchie von Datenbankobjekten.
Bei der Abstraktionshierarchie von Datenbankobjekten hatten wir
unterstellt, daß es sich primär um Nutzdaten handelt. Schemadaten
müssen natürlich auch persistent verwaltet werden, und die Speicherungsoperationen können hierfür im Prinzip auch ausgenutzt werden
(z.B. auf der Ebene von Speichersätzen); auf dieses Thema wollen wir
aber hier nicht eingehen.
Vereinfachend kann man den Zusammenhang zwischen den Hierarchien wie folgt ausdrücken:
– Die beiden oberen Schichten der Schema-Architektur (Sichten und
konzeptionelles Schema) beeinflussen die Arbeitsweise der oberen Schichten der Datenbankobjekt-Hierarchie (1- und n-TupelSchicht).
Architektur von DBMS
89
– Das interne Schema beeinflußt die Arbeitsweise der drei unteren
Schichten der Datenbankobjekt-Hierarchie.
In der 1- bzw. n-Tupel-Schicht finden z.B. Prüfungen statt, ob angegebene Typnamen (z.B. Attribute oder Relationentypen) bekannt
sind; hierzu werden das externe und das konzeptuelle Schema herangezogen. Auf der Speichersatzebene muß z.B. eine gewünschte Sortierung
eingehalten werden, und es müssen Indexstrukturen bei Änderungen
an den indexierten Daten gewartet werden.
Glossar
Index: Datenstruktur, die einen effizienten Zugriff zu Speichereinheiten
ermöglicht, die durch einen Attributwert identifiziert werden
Laufzeitkern: Teil eines DVS, das als geladenes Programm die Funktionen
des API ausführt
Primärindex: in die Nutzdaten integrierter Index
Seite (Kontext: interne Architektur eines DBMS-Laufzeitkerns):
Speichereinheit der Seitenebene
Sekundärindex: Verzeichnis, das zu einzelnen Werten eine Liste von Referenzen auf die Speichereinheiten enthält, in denen dieser Attributwert
auftritt
Speichersatz: Speichereinheit der Speichersatzebene in der internen Architektur eines DBMS-Laufzeitkerns
Serverprozeß: im Betriebssystem selbständig oder sogar auf einem separaten Rechner laufender Prozeß, der die Funktionen einer Schicht eines
Informationssystems (z.B. Datenhaltungsschicht) ausführt
Zugriffsmethode (access method ): wird in Begriffen wie indexsequentielle
Zugriffsmethode (ISAM; index sequential access method) verwendet;
bezeichnet eine Methode, wie die Speichereinheiten (Sätze bzw. Seiten) einer bestimmten Ebene intern auf Basis der nächstieferen Ebene
organisiert werden und wie einzelne Einheiten lokalisiert und bearbeitet werden können; beinhaltet sowohl die (abstrakten) Schnittstellen
als auch die Hauptmerkmale der Implementierung
Zugriffsstruktur: abstrakte Schnittstelle, über die eine Menge von Speichereinheiten (i.d.R. Sätze) verwaltet wird
Lehrmodul 4:
Das relationale Datenbankmodell
Zusammenfassung dieses Lehrmoduls
Das relationale Datenbankmodell besteht im Kern aus Operationen
wie der Selektion, der Projektion und diversen Verbundoperationen.
Diese werden in der relationalen Algebra zusammengefaßt. Dieses
Lehrmodul stellt diese Operationen vor. Vorab wird die statische
Struktur einer relationalen Datenbank definiert. Aus der Vielzahl
denkbarer Integritätsbedingungen werden hier nur Schlüsselbegriffe
behandelt; wir unterscheiden u.a. Identifikations-, Super-, Fremd-,
Primär- und Sekundärschlüssel.
Vorausgesetzte Lehrmodule:
obligatorisch:
– Datenverwaltungssysteme
Stoffumfang in Vorlesungsdoppelstunden:
Stand: 09.12.2002
2.0
c
2002
Udo Kelter
Das relationale Datenbankmodell
91
Das relationale Datenbankmodell ist eines der drei “konventionellen”
Datenbankmodelle und, gemessen am Entwicklungstempo der Informatik, schon uralt. Es geht auf Arbeiten von E.F. Codd am IBM San
Jose Research Laboratory [Co70] zurück. Seine Entwicklung wurde
maßgeblich von mehreren Prototypen relationaler DBMS beeinflußt,
namentlich dem System R am IBM San Jose Research Laboratory, Ingres an der University of California at Berkeley und Query-by-Example
am IBM T.J. Watson Research Center.
Im Laufe der Jahre wurden sehr umfangreiche formale Grundlagen
des relationalen Datenbankmodells entwickelt, ferner wurden vielfältige Erweiterungen der ursprünglichen Konzepte vorgeschlagen.
In der Praxis ist das relationale Datenbankmodell heute dominierend. Eine Vielzahl kommerzieller oder kostenloser relationaler DBMS
ist verfügbar.
4.1
Datenbankmodelle vs. reale Datenbanksprachen
Das relationale Datenbankmodell legt zunächst nur zentrale, grundlegende Konzepte fest (s. Begriff Datenbankmodell in Lehrmodul 1),
nämlich die Struktur einer Datenbank und lesende Operationen auf
dieser Struktur. Ein praktisch benutzbares System muß zusätzlich
viele technische Details festlegen, angefangen bei der Syntax entsprechender Sprachen und Bedienschnittstellen. Zum Vergleich: das Konzept einer while-Schleife wird von allen normalen imperativen Programmiersprachen unterstützt, die konkrete Syntax und technische
Details können ganz erheblich differieren (for (..,..,..) { .. } in
C; WHILE ... BEGIN ... END in Modula-2). Neben den Abfragen und Datenänderungen müssen außerdem Funktionen bzw. Sprachkonstrukte zur Definition konzeptueller und interner Schemata, Rechteverwaltung, Administration usw. angeboten werden; das relationale
Datenbankmodell legt diese Bereiche nicht fest. Ähnlich wie Programmiersprachen sind daher die konkreten Abfragesprachen für relationale
Systeme äußerlich sehr verschieden und differieren auch außerhalb der
92
Das relationale Datenbankmodell
grundlegenden Konzepte in vielen technischen Details.
Für die Darstellung der grundlegenden Konzepte braucht man
natürlich dennoch Notationen, also eine Sprache. Die relationale Algebra und die relationalen Kalküle kann man in diesem Sinne als Sprachen ansehen, die nur den Kern des relationalen Datenbankmodells
abdecken und von jeglichem störenden Ballast befreit sind.
4.2
4.2.1
Die Struktur relationaler Datenbanken
Tabellen
Die statische Struktur einer relationalen Datenbank kann man informell wie folgt definieren (eine präzisere Definition folgt später):
1. Eine relationale Datenbank besteht aus mehreren Tabellen. Jede
Tabelle hat einen eindeutigen Namen.
2. Eine Tabelle hat eine Menge von Spalten.
3. Eine Spalte hat einen eindeutigen Namen, der im Tabellenkopf
steht, und einen zugeordneten Wertebereich. Statt von einer Spalte reden wir auch von einem Attribut.
4. Der Rumpf (oder “Inhalt”) einer Tabelle enthält beliebig viele Zeilen; jede Zeile enthält in jeder Spalte einen Wert entsprechend dem
Wertebereich der Spalte.
Tabelle: kunden
Kundennummer Kundenname
177177
Meier, Anne
177180
Büdenbender, Christa
185432
Stötzel, Gyula
167425
Schneider, Peter
171876
Litt, Michael
Wohnort
Weidenau
Siegen
Siegen
Netphen
Siegen
Abbildung 4.1: Beispieltabelle
Kreditlimit
2000.00
9000.00
4000.00
14000.00
0.00
Das relationale Datenbankmodell
93
Als Beispiel betrachten wir eine Tabelle kunden , in der Daten über
die Kunden eines Unternehmens verwaltet sein mögen (s. Bild 4.1). Die
Spalte Kreditlimit gibt an, wieviele Waren dem Kunden auf Kredit
geliefert werden. Der Sinn der restlichen Spalten ist offensichtlich. Die
Wertebereiche der Spalten sind (von links nach rechts): 1. ganze Zahl,
2. Text, 3. Text, 4. reelle Zahl. Über Längenbeschränkungen der Texte
oder die Genauigkeit der Zahlen machen wir uns an dieser Stelle keine
Gedanken.
Eine Zeile repräsentiert oft eine Entität in der realen Welt, in unserem Beispiel repräsentiert jede Zeile einen Kunden. Wenn die Tabelle
zwei völlig gleiche Zeilen enthalten würde, wäre der gleiche Sachverhalt
doppelt repräsentiert; dies wäre sinnlos, Duplikate von Zeilen werden
daher nicht erlaubt.
Die Spalten enthalten die Beschreibungsmerkmale der repräsentierten Entität. Interessant ist hier die Beobachtung, daß die Reihenfolge
der Spalten unwesentlich ist, die folgende Tabelle ist zu der vorstehenden offenbar äquivalent:
Tabelle: kunden
Wohnort
Kundennummer
Weidenau 177177
Siegen
177180
...
...
Kundenname
Meier, Anne
Büdenbender, Christa
...
Kreditlimit
2000.00
9000.00
...
Eine Zeile können wir daher auch als eine Menge von Attributzuweisungen auffassen, z.B. die erste Zeile als:
Kundennummer = 177177; Wohnort = Weidenau; Kundenname =
”Meier, Anne”; Kreditlimit = 2000.00
Während die Reihenfolge der Attribute aus einer konzeptuellen
Sichtweise irrelevant ist, ist sie für die physische Speicherung i.a. relevant. Beide Sichtweisen müssen aber strikt getrennt werden; Datenbankmodelle definieren nur konzeptuelle Aspekte, die physische Speicherung bleibt hier völlig außer Betracht.
94
Das relationale Datenbankmodell
4.2.2
Relationen
Die Bezeichnung “relational” stammt von mathematischen Begriff einer Relation ab. Eine Relation ist in der Mathematik bekanntlich
definiert als Teilmenge des Kreuzprodukts mehrerer Mengen, i.a.:
R ⊆ D1 × D2 × . . . × Dn
Ein Element einer Relation nennt man Tupel. Den Inhalt der letzten
Tabelle könnte man offenbar als folgende Relation ansehen:
kunden ⊆ string × integer × string × real
Tabellen werden oft als Relationen bezeichnet und umgekehrt, es
gibt aber einen signifikanten Unterschied: Relationen haben kein Äquivalent zum Tabellenkopf. Die “Spalten” einer Relation haben keinen
Namen, sie sind nur anhand ihrer Position benennbar, und ihre Bedeutung muß durch eine separate Definition angegeben werden. Letzteres
leistet ein Relationentyp.
Ein Relationentyp (auch als Relationenschema oder Relationenformat bezeichnet) besteht aus:
– einem Namen, der innerhalb einer Datenbank eindeutig ist
– einer Folge von Attributdefinitionen
Notieren werden wir Relationentypen nach folgendem Muster:
Relationentypname = ( . . . , Attributname, . . . )
wenn die Wertebereiche der Attribute schon anderweitig bekannt sind
oder im Moment nicht interessieren, und als
Relationentypname = ( . . . , Attributname: Wertebereich; . . . )
wenn die Wertebereiche angegeben werden sollen. Als Wertebereiche
der Attribute sind nur elementare Datentypen wie integer, real, date,
string usw. zugelassen, nicht hingegen strukturierte Datentypen wie
Arrays, Tupel, Mengen usw. oder gar Relationen15 .
Unsere erste Version der Kundentabelle führt also zu folgendem
Relationentyp:
15
In erweiterten relationalen Modellen, die wir hier nicht behandeln, können Attribute dagegen strukturierte Typen haben.
Das relationale Datenbankmodell
95
Kunden = ( Kundennummer: integer;
Kundenname: string;
Wohnort: string;
Kreditlimit: real )
Wir werden einen Relationentyp oft vereinfachend als Menge (und
nicht Folge) von Attributen ansehen und die Schreibweisen A ∈ R bzw.
R1 ⊆ R2 benutzen, um darzustellen, daß das Attribut A im Relationentyp R vorkommt bzw. daß im Relationentyp R1 nur Attribute aus
dem Relationentyp R2 vorkommen.
Da wir hier den Begriff Typ gebrauchen, sei ein Vergleich mit
den Typen in Programmiersprachen gestattet: ein Relationentyp entspricht in etwa einem Datentyp, der als Menge von Objekten (oder
Records) mit den Attributen gemäß dem Relationentyp definiert ist.
Eine Relation kann man in der Denkwelt von Programmiersprachen
als Variable dieses Typs ansehen.
In Datenbanken ist die strikte Trennung zwischen Typ und Variable wenig sinnvoll, weil es zu jedem Relationentyp immer nur eine
Relation gibt. Daher werden dort immer gleich Relationen definiert,
ihr Typ wird nur implizit mitdefiniert und hat keinen Namen. Für die
Erklärung des relationalen Datenbankmodells werden wir allerdings
wiederholt Relationentypen benötigen, so daß wir auf diesen Begriff
nicht verzichten können.
Bzgl. der Schreibweisen werden wir die Konvention einhalten,
– Namen von Relationen klein zu schreiben
– Namen von Relationentypen und Attributmengen groß zu schreiben
Wenn wir festlegen, daß eine Relation r von Relationentyp R sein
soll, ist wegen des Rückgriffs auf den mathematischen Relationsbegriff
implizit klar,
– daß alle Tupel von r insofern korrekt sind, daß die Werte der einzelnen Attribute aus den passenden Wertebereichen stammen, und
96
Das relationale Datenbankmodell
– daß keine Tupel in r doppelt vorhanden sind (eine Relation ist eine
Menge und keine Multimenge)16 .
Wir werden i.f. Tabellen als Darstellung von Relationen benutzen
und die beiden Begriffe in diesem Sinne synonym verwenden.
4.2.3
Integritätsbedingungen
Es gibt sehr viele Arten, Integritätsbedingungen in relationalen Datenbanken zu formulieren; es ist ein bißchen Geschmackssache, wieviele davon man zum “Kern” des relationalen Datenbankmodells zählt.
Man kann die Integritätsbedingungen grob wie folgt einteilen:
– Dynamische Integritätsbedingungen schränken die erlaubten
Zustandsübergänge bei Änderungen der Daten ein. Beispielsweise könnte bei einem Attribut Familienstand der Übergang von
verheiratet nach ledig verboten sein. Dynamische Integritätsbedingungen werden wir nicht weiter betrachten.
– Statische Integritätsbedingungen schränken den erlaubten Zustand einer Datenbank weiter ein. Das bekannteste Beispiel sind
(Identifizierungs-) Schlüssel.
Integritätsbedingungen können allenfalls bei Änderungen an den
Daten verletzt werden. Ein DBMS muß daher bei allen ändernden
Operationen entsprechende Prüfungen durchführen und die Operation
ggf. mit einem Fehlercode zurückweisen.
Lesende Operationen sind dagegen überhaupt nicht von Integritätsbedingungen betroffen: diese Operationen arbeiten auf beliebigen Datenbankinhalten, also erst recht auf der Teilmenge der “korrekten”
Datenbankinhalte. Aus diesem Grunde sind Integritätsbedingungen
für die nachfolgende Diskussion der relationalen Algebra nicht erforderlich.
16
Technisch wäre es kein Problem, auch Multimengen zuzulassen. In der Praxis erspart man sich aus Performancegründen oft die Eliminierung von Duplikaten.
Wie schon erwähnt sind aber Duplikate von Tupeln i.a. nicht sinnvoll.
Das relationale Datenbankmodell
4.3
97
Die relationale Algebra
Der Begriff Algebra stammt aus der Mathematik. Eine Algebra ist
definiert durch eine Wertemenge17 und i.a. mehrere Funktionen, die
mit Werten dieser Menge arbeiten. Beispiele für Algebren sind die
reellen Zahlen oder Matrizen zusammen mit den diversen Rechenoperationen. Die Funktionen können beliebig viele Argumente haben und
liefern stets einen Wert aus der Wertemenge zurück. Daher kann man
Funktionsaufrufe schachteln und Ausdrücke konstruieren.
Die relationale Algebra ist eine ganz normale Algebra im vorstehenden Sinn. Als Werte benutzen wir beliebige Relationen. Daß
die entstehende Wertemenge recht groß ist und ganze Relationen als
Argumente oder Resultate etwas schwergewichtig erscheinen mögen,
braucht uns nicht weiter zu stören.
Die relationale Algebra enthält keine Operationen, mit denen man
Relationen erzeugen bzw. löschen und in einer Relation Tupel einfügen,
löschen oder verändern kann. Derartige Operationen müssen in realen Sprachen natürlich vorhanden sein; die relationale Algebra konzentriert sich ausschließlich auf die “lesenden” Operationen und die
Frage, welche Daten man aus einer vorhandenen Datenbank extrahieren kann. Es wird vorausgesetzt, daß die Relationen der Datenbank
schon irgendwie existieren und mit Tupeln gefüllt worden sind. Analog gilt dies für die Relationentypen, also das konzeptuelle Schema der
Datenbank.
Die Operationen der relationalen Algebra entsprechen nicht unzufällig den typischen Aufgaben, die beim Umgang mit Datenbanken
in der Praxis auftreten. Wir stellen sie anschließend einzeln vor.
4.3.1
Die Selektion
Die Selektion erlaubt es, aus einer vorhandenen Relation r bestimmte
Tupel zu selektieren. Zurückgeliefert wird eine neue Relation, die nur
17
Dies gilt für eine einsortige Algebra. Mehrsortige Algebren arbeiten mit mehreren Wertemengen, die hier als Sorten bezeichnet werden.
98
Das relationale Datenbankmodell
die Tupel enthält, die das Selektionskriterium erfüllen. Notiert wird
die Selektion üblicherweise in der Form
σBedingung ( r )
Der griechische Buchstabe sigma (σ) erinnert an das S im Wort Selektion. Das Ergebnis einer Selektion hat den gleichen Relationentyp wie
die Argumentrelation.
Als Beispiel betrachten wir die Menge der Kunden aus der Relation kunden in Bild 4.1, deren Kreditlimit größer als 5000 DM ist.
Folgender Ausdruck liefert eine Relation mit genau diesen Kunden:
σKreditlimit>5000.00 ( kunden )
Die entstehende Tabelle ist
Tabelle: σKreditlimit>5000.00 ( kunden )
Kundennummer Kundenname
177180
Büdenbender, Christa
167425
Schneider, Peter
Wohnort
Siegen
Netphen
Kreditlimit
9000.00
14000.00
Im vorstehenden Beispiel trat nur eine sehr einfache Selektionsbedingung auf, die den Wert eines Attributs mit einer Konstanten
verglich. Neben > sind auch die Vergleichsoperatoren <, ≤, ≥, = und
6= möglich. Ferner können so geformte elementare Bedingungen mit
den Booleschen Operatoren (∧, ∨, ¬) und Klammern zu Ausdrücken
zusammengesetzt werden. Die Bedingungen dürfen sich natürlich nur
auf solche Attribute beziehen, die im Typ der Argumentrelation vorkommen.
Übungsaufgabe: Zeigen Sie, daß die und-Verküpfung von zwei Bedingungen durch eine Hintereinanderschaltung von zwei Selektionen
mit den einzelnen Bedingungen ersetzt werden kann, daß also für eine
beliebige Relation r und Bedingungen B1 und B2 gilt:
σB1∧B2 ( r ) = σB1 (σB2 ( r )) = σB2 (σB1 ( r ))
Das relationale Datenbankmodell
4.3.2
99
Die Projektion
Die Projektion löst das Problem, überflüssige Attribute in den Tupeln
einer Relation zu entfernen. Man projiziert eine Relation auf die Attribute, die man noch beibehalten möchte. Notiert wird die Projektion
üblicherweise in der Form
πAttributmenge ( r )
Der griechische Buchstabe pi (π) erinnert an das Wort Projektion.
Als Beispiel betrachten wir wieder die Relation kunden in Bild
4.1. Wir möchten jetzt nur noch Kundenname und Wohnort haben, die
beiden anderen Attribute bzw. Spalten sollen “wegprojiziert” werden.
Dies erreichen wir mit folgender Ausdruck:
πKundenname,Wohnort ( kunden )
Die entstehende Tabelle ist:
Tabelle: πKundenname,Wohnort ( kunden )
Kundenname
Wohnort
Meier, Anne
Weidenau
Büdenbender, Christa Siegen
Stötzel, Gyula
Siegen
Schneider, Peter
Netphen
Litt, Michael
Siegen
Das Ergebnis einer Projektion hat i.a. nicht den gleichen Relationentyp wie die Argumentrelation18 . Der Typ der Ergebnisrelation hat
genau die in der Projektion angegebenen Attribute.
Für die formale Definition der Projektion benötigen wir folgende
neue Notation: Sei r eine Relation mit Relationentyp R , t ein Tupel
in r , also t ∈ r , A ⊆ R eine nichtleere Teilmenge der Attribute in
R . Dann bezeichnet t[A] das Tupel, das die Attributwerte für die Attribute in A gemäß t enthält. Mit dieser Notation können wir das
Ergebnis einer Projektion wie folgt definieren:
18
Eine Ausnahme ist lediglich der wenig sinnvolle Sonderfall, daß man auf alle
Attribute der Argumentrelation projiziert.
100
Das relationale Datenbankmodell
πA (r) = { t[A] | t ∈ r }
Im vorigen Beispiel hat die Ergebnisrelation genausoviele Tupel
wie die Argumentrelation. Dies ist nicht immer der Fall, wie folgendes
Beispiel zeigt:
πWohnort ( kunden )
Die entstehende Tabelle ist:
Tabelle: πWohnort ( kunden )
Wohnort
Weidenau
Siegen
Netphen
Sie hat nur noch 3 Tupel, denn in der Spalte Wohnort treten nur
3 verschiedene Werte auf. Man betrachte noch einmal die obige Definition der Projektion: πA (r) ist als Menge, nicht als Multimenge
definiert. Zwei verschiedene Tupel t1 , t2 ∈ R , t1 6= t2 , können nach der
Projektion gleich sein und führen daher nur zu einem einzigen Tupel
in der Ergebnisrelation.
Übungsaufgabe: Seien P , Q und R Relationentypen, r eine Relation vom Typ R . Zeigen Sie, daß folgendes gilt:
P ⊆ Q ⊆ R
4.3.3
⇒
π P (π Q ( r )) = π P ( r )
Die Mengenoperationen
Da Relationen als Mengen von Tupeln definiert sind, sind automatisch
alle Mengenoperationen auf Relationen anwendbar. Voraussetzung ist
natürlich, daß die beteiligten Relationen den gleichen Relationentyp
haben.
Wenn also r1 und r2 Relation vom Typ R sind, dann ist
r1 ∪ r2 die Vereinigung
r1 ∩ r2 der Schnitt
r1 − r2 die Differenz
von r1 und r2 . Das Ergebnis hat wieder den Relationentyp R .
Das relationale Datenbankmodell
101
Als Beispiel betrachten wir wieder die Relation kunden in Bild
4.1. Wir suchen jetzt die Kunden, die in Weidenau wohnen oder ein
Kreditlimit > 10000 haben. Hierzu definieren wir die Relation k1 wie
folgt:
k1 = σWohnort=“W eidenau′′ ( kunden ) ∪ σKreditlimit=10000 ( kunden )
Das Ergebnis ist:
Tabelle: k1
Kundennummer
177177
167425
Kundenname
Meier, Anne
Schneider, Peter
Wohnort
Weidenau
Netphen
Kreditlimit
2000.00
14000.00
Wir hätten dieses Ergebnis natürlich auch mit der folgenden Definition erzielen können;
k1 = σWohnort=“W eidenau′′ ∨ Kreditlimit=10000 ( kunden )
Übungsaufgabe: Zeigen Sie, daß die oder-Verküpfung von zwei Bedingungen durch eine Vereinigung von zwei Selektionen mit den einzelnen Bedingungen ersetzt werden kann, daß also für eine beliebige
Relation r und Bedingungen B1 und B2 gilt:
σB1∨B2 ( r ) = σB1 ( r ) ∪ σB2 ( r )
4.3.4
Die Umbenennung
Aus technischen Gründen benötigen wir für die folgenden Operationen
eine Hilfsoperation, mit der man Attribute umbenennen kann. Sei r
eine Relation vom Typ R und A ∈ R , B ∈
/ R . Dann ist
ρA →B (r )
eine Relation mit dem gleichen “Inhalt” wie r , aber einem Typ, bei
den das Attribut A in B umbenannt worden ist19 . Der Buchstabe rho
19
Diese Definition ist formal nicht sauber, sollte aber dennoch präzise verständlich
sein. Eine formal saubere Definition bedingt einen wesentlich höheren notationellen
Aufwand; Tupel müssen dann als Abbildungen von Mengen von Attributnamen in
Mengen von Wertemengen definiert werden (wie z.B. in [Vo99]). Da dieser nota-
102
Das relationale Datenbankmodell
(ρ) erinnert an rename. Der Typ der Ergebnisrelation ist, als Attributmenge aufgefaßt, gleich ( R − { A }) ∪ { B }.
Wir wenden die Umbenennungsoperation auch auf Relationennamen an. Sei r eine Relation vom Typ R , s ein Name, der bisher keine
Relation benennt, dann ist
ρs (r )
eine Relation namens s mit Typ R und dem gleichen Inhalt wie r .
4.3.5
Das Kreuzprodukt
Eine sehr häufige praktische Aufgabe besteht darin, Tupel aus verschiedenen Relationen zu neuen Tupeln zu “verbinden”; Beispiele werden wir erst später besprechen.
Das Verbinden von Einzelelementen zu einem Tupel ist durch das
mathematische Kreuzprodukt hinlänglich bekannt und wurde bereits
beim Relationsbegriff ausgenutzt. Es liegt nahe, statt einzelner Wertebereiche auch ganze Relationen durch das mathematische Kreuzprodukt zu verbinden. Seien also r1 , . . . , rn Relationen, dann können
wir folgendes mathematische Kreuzprodukt bilden:
r1 × ... × rn
Dies ist aber leider keine Relation im Sinne der relationalen Algebra:
Ein Tupel in diesem Kreuzprodukt hat die Form
(t1 , . . . , tn )
wobei ti ein Tupel aus Ri ist; als Elemente relationaler Tupel sind
aber nur elementare Datentypen zugelassen. Wir hätten auch ein Problem, den Relationentyp dieses Kreuzprodukts zu benennen.
Ein Lösungsansatz besteht darin, die Tupel ti , ..., tn zu “konkatenieren”, also ein einziges neues Tupel zu bilden. Diese Idee funktioniert aber nur dann, wenn keine Attributnamen doppelt auftreten, also wenn die Typen der beteiligten Relationen paarweise disjunkt sind.
tionelle Aufwand keinen signifikanten Gewinn an Präzision bringt, andererseits der
intuitiven Verständlichkeit abträglich ist, wird er hier vermieden.
Das relationale Datenbankmodell
103
Unter dieser Annahme können wir das relationale Kreuzprodukt
folgendermaßen definieren:
r 1 × . . . × r n = { < t1 | . . . | tn > | t i ∈ r i }
Darin ist < t1 | . . . | tn > die Konkatenation der einzelnen Tupel. Der
Typ des Kreuzprodukts ist die Vereinigung der Ri , 1 ≤ i ≤ n.
Die Bildung eines Kreuzprodukts veranschaulicht Bild 4.2 am Beispiel zweier Relationen, die 3 bzw. 2 Tupel enthalten; der Aufbau der
Tupel interessiert hier nicht, der Inhalt ist mit “aa”, “bb” usw. nur
angedeutet.
aa
bb
cc
X
xx
yy
=
aa
aa
bb
bb
cc
cc
xx
yy
xx
yy
xx
yy
Abbildung 4.2: Beispiel eines Kreuzprodukts
Da jedes Tupel der ersten Relation mit jedem Tupel der zweiten
kombiniert wird, gilt folgende Formel:
| r×s |=| r | ∗| s |
worin | r | die Anzahl ihrer Tupel einer Relation r bezeichnet.
Die “Länge” der Ergebnistupel (gemessen in der Zahl der Attribute) ist gleich der Summe der Längen der Argumenttupel. Bei der
Kreuzproduktbildung entstehen also sehr viele und lange Tupel20 .
Wir hatten unser relationales Kreuzprodukt bisher nur unter der
Annahme definieren können, daß die Typen der beteiligten Relationen paarweise disjunkt sind; diese Annahme ist natürlich nicht immer
20
Deshalb wird das Kreuzprodukt in der Praxis auch fast nie wirklich berechnet.
Im Rahmen der Optimierung werden Kreuzprodukte, die in einer vorgegebenen
Abfrage auftreten, praktisch immer zu Verbundoperationen umgeformt; letztere
lassen sich meist effizient berechnen. Mit relationalen Abfragesprachen kann man
(bzw. sollte man oft sogar) Abfragen formulieren, die auf den ersten Blick extrem
ineffizient aussehen. Wir gehen hierauf in Abschnitt 4.3.9 noch näher ein.
104
Das relationale Datenbankmodell
erfüllt. Die Lösung besteht darin, die Attribute, die in mehr als einer
Relation auftreten, umzubenennen. Sei A ein solches Attribut; dann
wird A in jeder Relation ri , in deren Typ A vorkommt, zu ri . A umbenannt, d.h. wir führen vor der eigentlichen Bildung des Kreuzprodukts
die Umbenennung
ρ A → r i. A ( r i)
durch. Unter der Annahme, daß die Namen aller ri verschieden sind,
sind anschließend alle Attributnamen eindeutig.
Wenn die vorstehende automatische Umbenennung von Attributen
im Einzelfall unpassend ist, können natürlich die betroffenen Attribute
auch explizit vor der Bildung des Kreuzprodukts umbenannt werden.
Gelegentlich will man auch das Kreuzprodukt einer Relation mit
sich selbst bilden. Dies verbieten wir hier und verlangen, daß in solchen
Fällen zunächst explizit eine der Relationen umbenannt wird, so daß
letztlich alle involvierten Relationen eindeutige Namen bekommen.
4.3.6
4.3.6.1
Verbundoperationen
Beispiel
Wir betrachten nun das schon angekündigte Beispiel, bei dem Daten
zu einer Entität, die in verschiedenen Relationen stehen, zusammenzuführen sind. Wir führen hierzu eine weitere Relation lieferungen
ein, die folgenden Relationentyp hat:
Lieferungen = ( Datum: date;
Wert: real;
Lager: integer;
Kundennummer: string;
Lieferadresse: string )
Ein Tupel dieses Typs zeigt an, daß an den durch die Kundennummer
identifizierten Kunden am angegebenen Datum Waren im angegebenen Gesamtwert geliefert worden sind, und zwar vom angegebenen
Lager aus an die angegebene Lieferadresse. Der Inhalt der Relation
lieferungen sei wie in Bild 4.3 angegeben.
Das relationale Datenbankmodell
Tabelle: lieferungen
Datum
Wert
Kundennummer
00-08-12 2730.00
167425
00-08-14
427.50
167425
00-08-02 1233.00
171876
105
Lager
Mitte
Nord
West
Lieferadresse
Bahnhofstr. 5
Luisenstr. 13
Bergstr. 33
Abbildung 4.3: Beispieltabelle für Lieferungen
Nehmen wir nun an, wir wollten eine Relation erzeugen (und anzeigen oder ausdrucken), in der für alle Lieferungen Datum, Wert und
der Name des Kunden angezeigt werden. Den Namen der Kunden
mit einer gegebenen Kundennummer können wir anhand der Relation
kunden herausfinden. Wir können das gesuchte Resultat in mehreren
Schritten wie folgt konstruieren:
1. Wir bilden das Kreuzprodukt von lieferungen und kunden :
r1 = lieferungen × kunden
Die beiden Relationen haben das Attribut Kundennummer gemeinsam. Nach unseren früheren Festlegungen ist das Attribut in
lieferungen.Kundennummer bzw. kunden.Kundennummer umbenannt worden.
2. In r1 ist jedes Lieferungstupel mit jedem Kundentupel kombiniert worden. Die meisten dieser Kombinationen sind für unseren
Zweck unsinnig und daher überflüssig; wir interessieren uns nur für
die Kombinationen, bei denen lieferungen.Kundennummer und
kunden.Kundennummer den gleichen Wert haben, denn nur hier
sind die richtigen Kundendaten und Lieferungsdaten kombiniert.
Wir bilden also
r2 = σ lieferungen.Kundennummer = kunden.Kundennummer ( r1 )
3. In r2 sind die Spalten lieferungen.Kundennummer und kunden.Kundennummer identisch: dies war gerade die Selektionsbedingung. Eine der beiden Spalten ist offensichtlich entbehrlich und
kann entfernt werden. Der lange Attributname der verbliebenen
106
Das relationale Datenbankmodell
Spalte ist dann nicht mehr notwendig, wir können einfacher wieder
den ursprünglichen Namen verwenden. Wir gehen nun so vor, daß
wir zuerst eine der Spalten in den ursprünglichen Namen umbenennen:
r3 = ρlieferungen.Kundennummer→Kundennummer ( r2 )
4. Die überflüssige Spalte mit dem langen Namen können wir nun
entfernen, indem wir einfach auf die Vereinigung der beiden Relationentypen projizieren:
r4 = πLieferungen ∪ Kunden ( r3 )
5. Zum Schluß entfernen wir noch die nicht benötigten Attribute; gefragt war nur nach dem Datum, Wert und Kundennamen:
r5 = πDatum,Wert,Kundenname ( r4 )
Unser Endresultat sieht folgendermaßen aus:
Tabelle: r5
Datum
Wert
00-08-12 2730.00
00-08-14
427.50
00-08-02 1233.00
4.3.6.2
Kundenname
Schneider, Peter
Schneider, Peter
Litt, Michael
Der natürliche Verbund
Das vorige Beispiel weist eine sehr häufig auftretende Struktur auf:
die Werte in der Spalte Kundennummer in der Relation lieferungen
kann man als “Referenzen” auf Tupel in der Relation kunden ansehen. Wir unterstellen jetzt einmal, daß die Kundennummern eindeutig sind, daß also eine Kundennummer höchstens einmal in der Spalte
Kundennummer in der Relation kunden auftritt.
Unsere Absicht war es, zu jedem Tupel in lieferungen die dort
stehende Referenz auf ein Kundentupel zu verfolgen und Daten aus
diesem Kundentupel hinten an das Lieferungstupel anzuhängen - so
hätte man es auch von Hand gemacht (s. auch Bild 4.4). Letztlich
verbinden wir solche Paare von Lieferungstupel und Kundentupel, die
Das relationale Datenbankmodell
107
im gemeinsamen Attribut Kundennummer den gleichen Wert haben.
Solche Paare von Tupeln bilden Verbundpartner voneinander.
.....
177180 .....
.....
177180 .....
177180
11111
00000
00000
11111
1111
0000
0000
1111
Abbildung 4.4: Auflösung einer “Referenz”
Der natürliche Verbund (natural join) verallgemeinert diesen
Vorgang; er faßt die obigen Schritte 1 bis 4 zu einer einzigen Operation, die mit dem Zeichen 1 notiert wird, zusammen. Gegeben seien
zwei Relationen r und s mit den Relationentypen R bzw. S . Sei V
= R ∩ S . Dann ist 1 wie folgt definiert:
r 1 s = π R ∪ S (ρ r.V → V (σ r.V=s.V ( r × s )))
Die Attribute in V nennt man auch die Verbundattribute. In den
meisten Fällen hat man genau ein Verbundattribut, es kann i.a. beliebig viele Verbundattribute geben, also V = {v1 ,...,vn }.
Die Schreibweise ρ r.V → V (...) ist eine Kurzform für
ρr.v1 →v1 (. . . (ρr.vn →vn (...)) . . .)
Die Schreibweise σ r.V=s.V ist eine Kurzform von
σr.v1 =s.v1 ∧ ... ∧ r.vn =s.vn
Es werden also nur solche Tupel verbunden, die in allen Verbundattributen übereinstimmen. In dem Sonderfall, daß R und S disjunkt
sind, also V die leere Menge ist, ist auch die Selektionsbedingung leer,
d.h. die selektierten Tupel müssen keine Bedingung erfüllen, es wird
also nichts weggefiltert. Bei V = ∅ bilden auch die Projektion und die
Umbenennung ihre Argumente identisch ab, der natürliche Verbund
verhält sich dann also wie das Kreuzprodukt.
Mit Hilfe des natürlichen Verbunds können wir das Beispiel in Abschnitt 4.3.6.1 wesentlich einfacher lösen, und zwar in der Form
108
Das relationale Datenbankmodell
πDatum,Wert,Kundenname ( lieferungen 1 kunden )
Übungsaufgabe: Zeigen Sie, daß im Sonderfall R = S der Verbund
den Durchschnitt der beiden Relationen bildet, also:
R = S ⇒ r 1 s = r∩s
Übungsaufgabe: Zeigen Sie, daß der natürliche Verbund eine assoziative Operation ist, d.h. für beliebige Relationen r , s und t gilt:
(r 1 s ) 1 t = r 1 (s 1 t )
4.3.6.3
Der Theta-Verbund
Beim natürlichen Verbund wurden bei der Prüfung, ob ein Paar von
Tupeln verbunden werden soll,
– der Vergleichsoperator = benutzt, und
– es wurde jeweils das gleiche Attribut in beiden Tupeln für den Vergleich herangezogen.
Dies wird beim Θ- (Theta-) Verbund dahingehend verallgemeinert,
– daß irgendein Vergleichsoperator Θ ∈ {=, 6=, <, ≤, >, ≥} benutzt
wird und
– daß unterschiedliche Attribute in beiden Tupeln für den Vergleich
herangezogen werden.
Wenn r und s Relationen vom Typ R bzw. S sind und A ∈ R und B
∈ S Attribute mit gleichen Wertebereich, dann ist ein Theta-Verbund
wie folgt definiert:
r 1r.A Θ s.B s := σr.A Θ s.B ( r × s )
Man kann geteilter Meinung darüber sein, ob der Theta-Verbund viel
einbringt; eine wesentliche Ersparnis an Schreibarbeit und ein dementsprechender Gewinn an Übersichtlichkeit der Ausdrücke – die ein
großer Vorteil des natürlichen Verbundes sind – tritt hier jedenfalls
nicht ein.
Das relationale Datenbankmodell
109
Ein Gleichheitsverbund (equi-join) ist ein Theta-Verbund mit
dem Vergleichsoperator =.
4.3.6.4
Äußere Verbunde
Wir betrachten noch einmal das Beispiel in Abschnitt 4.3.6.1 und nehmen an, in der Relation kunden sei das Tupel mit der Kundennummer
167425 gelöscht worden. Wenn wir jetzt wieder den Verbund
lieferungen 1 kunden
bilden, würden die beiden ersten Tupel in der Relation lieferungen
(s. Bild 4.3) keinen Verbundpartner mehr finden und dementsprechend
herausfallen. Dies ist aber oft nicht erwünscht. Wenn der Kundenname nicht ermittelt werden kann, sollte der Sachverhalt, daß der Wert
unbekannt ist, angezeigt werden, etwa in folgender Form:
Datum
Wert
00-08-12
00-08-14
00-08-02
2730.00
427.50
1233.00
Kundennummer
167425
167425
171876
Lieferadresse
Kundenname
Bahnhofstr. 5
Luisenstr. 13
Bergstr. 33
NULL
NULL
Litt, Michael
Der Text NULL soll einen Nullwert darstellen; dieser drückt aus,
daß der tatsächliche Attributwert unbekannt ist.
In der vorstehende Tabelle haben wir bei den Tupeln aus
lieferungen (also dem linken Verbundargument), die keinen Verbundpartner gefunden haben, einen künstlichen Verbundpartner benutzt. Diese Art von Verbund nennt man linken äußeren Verbund.
Analog wird beim rechten äußeren Verbund für Tupel des rechten
Verbundarguments ggf. ein künstlicher Verbundpartner benutzt. Der
äußere Verbund ist die Vereinigung von linkem und rechtem äußeren
Verbund.
4.3.7
Die Division
Das Kreuzprodukt ist in gewisser Weise vergleichbar mit einer Multiplikation; im Kreuzprodukt r × s wird jedes Tupel aus r mit jedem
110
Das relationale Datenbankmodell
Tupel aus s kombiniert (s. auch Bild 4.2). Die relationale Division
kann man sich als eine Art inverse Operation zum Kreuzprodukt vorstellen.
Hierzu betrachten wir das Beispiel in Bild 4.2 noch einmal genauer. Jedes der Tupel “aa”, “bb” und “cc” der linken Relation führt zu
einem eigenen Abschnitt im Ergebnis (in Bild 4.2 jeweils durch einen
kleinen Zwischenraum abgesetzt): die linken Hälften der Tupel eines
Abschnitts enthalten alle das gleiche, z.B. “aa”, die schattiert dargestellten rechten Hälften bilden eine Kopie der rechten Argumentrelation. Diese rechte Hälfte eines Abschnitts wiederholt sich wie ein
Stempelabdruck immer wieder.
Bei der Umkehrung der Kreuzproduktbildung suchen wir sozusagen nach Stempelabdrücken (s. Bild 4.5):
aa
aa
bb
bb
cc
cc
cc
dd
xx
yy
xx
zz
xx
yy
zz
xx
:
xx
yy
=
aa
cc
Abbildung 4.5: relationale Division
– Dividend ist eine Relation x vom Typ X ;
– Divisor ist eine Tupelmenge in einer Teilmenge der Spalten, aufgefaßt als Relation s vom Typ S (der “Stempel”)
– im Quotienten enthalten sind solche Tupel aus den restlichen Spalten von x , die mit allen Tupeln des Divisors kombiniert auftreten
Im Beispiel in Bild 4.5 ist für “aa” ein kompletter Stempelabdruck vorhanden, für “bb” und “dd” nur ein unvollständiger, “bb”
und “dd” sind daher nicht im Ergebnis enthalten. Die Tupel “bb/xx”
und “dd/xx” tragen somit nicht zum Ergebnis bei, ebenfalls nicht das
Tupel “bb/zz”, da “zz” nicht im Divisor auftritt. Die relationale Division ähnelt insofern der ganzzahligen Division ohne Rest. Wegen
Das relationale Datenbankmodell
111
dieses Rests erhält man, wenn man den Quotienten wieder mit dem
Divisor multipliziert, i.a. nur noch eine Teilmenge des ursprünglichen
Dividenden:
(x ÷ s ) × s ⊆ x
Formal definiert ist die Division wie folgt: Gegeben sei
– eine Relation x vom Typ X (der Dividend)
– eine Relation s vom Typ S (der Divisor),
wobei ∅ =
6 S und S ⊂ X sein muß. Sei R = X − S . Dann ist
x ÷ s = { t | t ∈ π R ( x ) ∧ {t} × s ⊆ x }
Das Ergebnis ist eine Relation vom Typ R . Ein Tupel t ist genau
dann im Ergebnis enthalten, wenn {t} × s ⊆ x , also wenn für alle
t’ ∈ s gilt: < t | t′ > ∈ x . Bildlich gesprochen enthält das Ergebnis
diejenigen “linken Hälften” von Tupeln aus x , die mit allen “rechten
Hälften” aus s kombiniert in x auftreten.
Anwendungsbeispiel. Als Anwendungsbeispiel für die Division betrachten wir eine Relation konten , die Angaben zu den Konten einer
Bank enthält und die folgenden Relationentyp hat:
Konten = ( Kontonummer: integer;
Kundennummer: integer;
Filialenname: string )
Der Filialenname gibt den Namen der Filiale an, bei der das Konto geführt wird. Ein Kunde kann bei jeder Filiale eine oder mehrere
Konten haben. Gesucht sind nun die Kunden, die bei allen Filialen
wenigstens ein Konto haben. Für die Lösung unserer Aufgabe bilden
wir zunächst die Relation
kundeFiliale = πKundennummer,Filialenname ( konten )
Diese enthält genau dann ein Tupel < k, f >, wenn der Kunde k wenigstens ein Konto in der Filiale f hat. Die Liste aller Filialen erhalten
wir als eine 1-spaltige Tabelle mittels:
filialen = πFilialenname ( kundeFiliale )
112
Das relationale Datenbankmodell
Die Kunden, die in jeder Filiale ein Konto haben, erhalten wir nunmehr durch:
kundeFiliale ÷ filialen
Das Typische an unserem Anwendungsbeispiel war, daß ein allQuantor bei der Beschreibung der gesuchten Daten benutzt wurde (...
Kunden, die bei allen Filialen ein Konto haben). Für derart spezifizierte Suchergebnisse kann man generell die Division einsetzen. In
den Selektionsbedingungen einer Selektion ist ein all-Quantor nicht
erlaubt; die Division bietet daher einen Ersatz. Ein Ersatz für den
Existenz-Quantor ist nicht notwendig, denn dieser wird implizit durch
die Selektion realisiert.
Berechnung von x ÷ s : x ÷ s kann direkt durch Ausnutzung der
Definition berechnet werden:
– Man bildet π R ( x ) als die Menge der Kandidaten, die im Ergebnis
enthalten sein könnten
– Für jedes t ∈ π R ( x ) prüft man, ob {t} × s ⊆ x .
Die Division ist aber auch, was man spontan vielleicht nicht erwarten würde, zurückführbar auf die früher definierten Operationen. Zu
berechnen sei also x ÷ s . Sei R = X − S und
r = πR (x )
r enthält i.a. eine Obermenge von x ÷ s , r kann Tupel enthalten,
für die {t} × s ⊆ x nicht gilt. Um diese Tupel zu finden, benutzen
wir einen Trick: Wir bilden zunächst die Relation r × s . Sei nun
inv = ( r × s ) − x
inv ist die Invertierung von x in r × s . Wir betrachten den Inhalt
von inv an einem Auszug unseres Beispiels aus Bild 4.5. inv enthält
kein Tupel der Form “aa/...”, weil alle derartigen Tupel in r × s auch
in x vorhanden sind und somit abgezogen wurden. Für Tupel der
Form “bb/...” gilt dies nicht: es bleibt eines übrig. Beide Fälle sind
in Bild 4.6 veranschaulicht.
Das relationale Datenbankmodell
(r x s)
aa
aa
bb
bb
xx
yy
xx
yy
113
x
(r x s) − x
aa
aa
bb
xx
yy
xx
bb
zz
bb
yy
Abbildung 4.6: relationale Division
Die Tupel in π R ( inv ) sind somit gerade diejenigen, die in r zuviel
sind. Unser Endresultat ist also
x ÷ s = r − π R ( inv )
bzw.
4.3.8
x ÷ s = π R ( x ) − π R ((π R ( x ) × s ) − x )
Relationale Vollständigkeit
Wir haben inzwischen eine Reihe von Operationen mit Relationen
kennengelernt und schon bei den relativ komplizierten Verbundoperationen und der Division bemerkt, daß wir sie auf die einfacheren
Operationen
σ, π, ρ, ∪, −, ×
zurückführen konnten. Die Verbundoperationen und die Division
mögen zwar die Formulierung mancher Abfragen erleichtern, sie erweitern die Fähigkeiten der relationalen Algebra aber nicht wirklich,
d.h. es gibt kein Suchproblem, das nur mit ihrer Hilfe lösbar wäre.
Dieser Effekt ist auch bei diversen weiteren Operationen, die man sich
noch ausdenken kann, zu beobachten.
Hieraus schlußfolgert man, daß die Ausdruckskraft, die durch die
vorstehende Operationenmenge erreicht wird, einerseits ausreichend
für eine große Klasse von Problemen, andererseits ein Minimum an
Ausdruckskraft ist, das von jeder Abfragesprache für relationale Datenbanken erreicht werden sollte; solche Sprachen nennt man daher
114
Das relationale Datenbankmodell
relational vollständig21 .
Die Operationenmenge {σ, π, ρ, ∪, −, ×} ist übrigens minimal in
dem Sinne, daß keine der Operationen auf die anderen zurückführbar ist, jede echte Teilmenge wäre nicht mehr relational vollständig.
Wir hätten alternativ statt des Kreuzprodukts zuerst den natürlichen Verbund einführen können und hätten dann das Kreuzprodukt
auf den natürlichen Verbund zurückgeführt; die Operationenmenge
{σ, π, ρ, ∪, −, 1} ist also eine andere minimale, relational vollständige
Operationenmenge.
4.3.9
Ausdrücke in der relationalen Algebra
Wie schon einleitend erwähnt setzen wir bei der relationalen Algebra
eine existierende Datenbank, also ein konzeptuelles Schema und dazu
passende existierende Relationen, voraus. Hierdurch ist eine Menge
von Namen von Relationen und Attributen vorgegeben. Diese Namen
können wir nun an passender Stelle in den Operationen der relationalen Algebra einsetzen. Überall dort, wo eine relationale Operation
eine Relation als Argument benötigt, kann natürlich wiederum ein relationaler Ausdruck eingesetzt werden.
Syntaktisch korrekte Ausdrücke sind analog zu arithmetischen Ausdrücken in gängigen Programmiersprachen definiert. Details der Syntaxdefinition und -prüfung und Übersetzung interessieren uns an dieser
Stelle nicht, und wir setzen i.f. syntaktisch korrekte Ausdrücke voraus.
Ausdrücke werden klassischerweise von innen nach außen ausgewertet. Die entstehenden Zwischenresultate müssen gepuffert werden.
Diese Zwischenresultate können, wenn Verbunde oder Kreuzprodukte
auftreten, extrem groß werden, d.h. man kann erhebliche PerformanceProbleme bekommen, wenn man einen relationalen Ausdruck in kanonischer Weise auswertet.
Man kann das Ergebnis eines relationalen Ausdrucks oft effizienter
21
Diese Bezeichnung ist insofern irreführend, als eine praxisgerechte Sprache viele
über die zentralen Abfrageoperationen hinausgehende Funktionen anbieten muß, s.
Abschnitt 4.1. So gesehen sind die Operationen der relationalen Algebra ziemlich
unvollständig.
Das relationale Datenbankmodell
115
berechnen als durch eine kanonische Auszuwertung; die Bestimmung
eines effizienteren Rechenverfahrens bezeichnet man als Optimierung.
Durch die Optimierung ist es vielfach möglich, auch äußerlich “ineffiziente” Ausdrücke recht effizient auszuwerten. Die entscheidende
Konsequenz hieraus ist, daß man bei der Formulierung relationaler
Abfragen zunächst keine Rücksicht auf Ineffizienz bei der kanonischen
Auswertung nehmen sollte und sich stattdessen besser auf die inhaltliche Korrektkeit des Ausdrucks konzentieren sollte. Lösungen, die klar
und korrekt, aber “ineffizient” sind, sind vielfach kompakter und deswegen leichter für Optimierer behandelbar als “effiziente” komplizierte
(und schlimmstenfalls inkorrekte) Lösungen.
Wenn der Optimierer der Datenbank wider Erwarten doch keine effiziente Ausführung findet – Wunder wirken können Optimierer nicht,
und nicht jedes DBMS hat einen guten Optimierer – , kann man in
einem zweiten Schritt immer noch versuchen, durch Umformung der
Anfrage die eigentliche Arbeit des Optimierers doch selbst von Hand
zu erledigen.
4.4
Schlüssel
Wir hatten schon in Abschnitt 4.2.3 Identifizierungsschlüssel als eine
typische Integritätsbedingung erwähnt; nachdem wir nun die Operationen der relationalen Algebra kennen, können wir einige Schlüsselbegriffe leichter exakt definieren.
4.4.1
Superschlüssel und Identifizierungsschlüssel
Wir betrachten noch einmal die Relation kunden in Bild 4.1. Von
dem Attribut Kundennummer verlangten wir schon früher, daß es “eindeutig” sein sollte, m.a.W. daß zu jeder Kundennummer höchstens
ein Tupel vorhanden sein sollte. Eine Kundennummer identifiziert
also, sofern vorhanden, genau ein Tupel. Formal läßt sich dies so ausdrücken:
kn ∈ πKundennummer (kunden)
⇒
| σKundennummer=kn (kunden) | = 1
116
Das relationale Datenbankmodell
Die vorstehende Bedingung ist äquivalent zu der folgenden kompakteren Bedingung (Beweis: Übungsaufgabe):
| πKundennummer (kunden) | =
| kunden |
Das Attribut Wohnort hat diese Eigenschaft offensichtlich nicht. Es
könnte aber sein, daß die beiden Attribute Wohnort und Kundenname
zusammen die Identifizierungseigenschaft haben. Genereller kann eine
beliebige Menge von Attributen zur Identifikation von Tupeln verwendet werden. Eine derartige Menge von Attributen nennen wir einen
Superschlüssel. Die formale Definition lautet:
Sei R ein Relationentyp, K ⊆ R eine Attributmenge. Wenn K ein
Superschlüssel für R ist, dann gilt für jede korrekte Relation r mit
dem Relationentyp R stets folgendes:
| πK (r) | =
| r |
Die Attribute in K nennen wir auch Schlüsselattribute. Bildlich gesprochen gehen beim Projizieren auf einen Superschlüssel keine Tupel
verloren, weil eben keine Kombination der Werte der Schlüsselattribute doppelt auftritt.
Der seltsam klingende Name Superschlüssel rührt daher, daß die
Attributmenge gemäß der vorstehenden Definition auch “überflüssige”
Attribute enthalten kann, die für die Identifikation eigentlich nicht gebraucht werden. Ein extremes Beispiel ist die Attributmenge R; R ist
immer ein Superschlüssel für R , sofern die Relation eine Menge ist
(also keine Duplikate erlaubt sind).
Ein Identifizierungsschlüssel ist eine minimale Menge von Attributen, die Superschlüssel ist.
Für unsere Relation kunden sind {Kundennummer} und {Kundenname, Wohnort} Identifizierungsschlüssel. Wenn zusätzlich die Personalausweisnummer zu jedem Kunden vorhanden wäre, wäre {Personalausweisnummer} ein weiterer Identifizierungsschlüssel. Dieses Beispiel
zeigt, daß es für einen Relationentyp mehrere Identifizierungsschlüssel
geben kann.
Die Bezeichnung Schlüssel wird meist als Synonym zu Identifizierungsschlüssel verstanden. Unter einem Schlüsselwert bei einem
Das relationale Datenbankmodell
117
Tupel t verstehen wir die Menge der Attributwerte von t bei den Attributen des Identifizierungsschlüssels.
Es sei noch einmal daran erinnert, daß Schlüsseleigenschaften Integritätsbedingungen, also vom Anwender definierte Anforderungen
sind. Zu der Erkenntnis, daß eine Attributmenge K ein Identifizierungsschlüssel ist, kommt man nicht etwa dadurch, daß man den
Zustand der Datenbank eine Zeitlang beobachtet und währenddessen
dauernd kontrolliert, ob die Identifizierungseigenschaft erfüllt ist. Es
ist genau umgekehrt: die Identifizierungseigenschaft wird vorgegeben,
und das DBMS hat dafür zu sorgen, daß unerwünschte Zustände verhindert werden.
Das DBMS muß bei jedem Einfügen eines neuen Tupels oder
Ändern eines vorhandenen Tupels für jeden Identifizierungsschlüssel
prüfen, ob der neue Schlüsselwert schon in der Relation auftritt. Diese Prüfung kann so implementiert werden, daß die ganze Relation
linear durchsucht wird. Dies ist i.a. (außer bei kleinen Relationen)
zu ineffizient, daher muß praktisch immer für einen Identifizierungsschlüssel ein Verzeichnis angelegt werden, in dem die aktuell vorhandenen Schlüsselwerte verzeichnet sind und das effizient durchsuchbar ist
(z.B. als Baumstruktur oder Hash-Tabelle)22 . Dieses Verzeichnis muß
bei allen Datenänderungen entsprechend aktualisiert werden. Sofern
eine Relation mehrere Identifizierungsschlüssel hat, muß für jeden ein
eigenes Verzeichnis der vorhandenen Schlüsselwerte angelegt werden.
Viele DBMS erlauben es, Relationen zu definieren, die keinen einzigen Identifizierungsschlüssel haben. Eine derartige Relation kann
Tupelduplikate enthalten. Auch die Gesamtmenge aller Attribute bildet hier keinen Schlüssel, denn dann wären keine Duplikate erlaubt.
22
Eine effiziente Suche wird z.B. auch durch die sortierte Speicherung nach
dem Identifizierungsschlüssel ermöglicht; allerdings machen hier Einfügungen und
Löschungen Probleme. Derartige Implementierungstechniken sind kein Thema dieses Lehrmoduls.
118
4.4.2
Das relationale Datenbankmodell
Primärschlüssel
Die Verzeichnisse für die Identifizierungsschlüssel kosten Platz und Rechenzeit, man würde sie daher lieber vermeiden. Dies ist in der Tat
bei vielen internen Speicherstrukturen möglich. Bei den folgenden Annahmen und Implementierungsentscheidungen:
1. jedes Tupel wird in einem Speichersatz gespeichert (vgl. Lehrmodul
3),
2. die Relation wird in einem B*-Baum gespeichert,
3. der Identifizierungsschlüssel ist einelementig (enthält also nur ein
Attribut),
4. man verwendet die Schlüsselwerte der Tupel als Schlüsselwerte im
B*-Baum
bekommt man die Eindeutigkeitsprüfung praktisch gratis! Diese sehr
effiziente Prüfung der Schlüsseleigenschaft ist aber nur bei einem einzigen Identifizierungsschlüssel möglich; wenn man mehrere Identifizierungsschlüssel hat, muß man für die übrigen nach wie vor separate
Verzeichnisse anlegen.
Als Primärschlüssel bezeichnet man denjenigen Identifizierungsschlüssel, für den die Möglichkeit der sehr effizienten Prüfung der
Schlüsseleigenschaft ausgenutzt werden soll. Welche Implementierungstechniken hierzu verwendet werden, bleibt eine Entscheidung des
DBMS-Herstellers.
Neben der Prüfung der Schlüsseleigenschaft ist natürlich bei einem
Primärschlüssel auch die Suche nach dem Tupel, das einen bestimmten
Wert bei diesem Attribut hat, besonders effizient möglich. Derartige
Suchvorgänge sind z.B. bei der Verbundbildung nötig; s. das Beispiel in
Abschnitt 4.3.6.1. Daher wird man, sofern mehrere Identifizierungsschlüssel vorhanden sind, denjenigen als Primärschlüssel auswählen,
mit dem häufig Verbunde gebildet werden. In den meisten Fällen
hat man aber ohnehin nur einen einzigen Identifizierungsschlüssel, der
dann automatisch als Primärschlüssel zu wählen ist.
Die vorstehenden Beobachtungen zeigen, daß die Festlegung des
Primärschlüssels eine Implementierungsentscheidung ist, die für die
Das relationale Datenbankmodell
119
konzeptionelle Struktur der Datenbank unerheblich ist. Im Sinne der
3-Ebenen-Schema-Architektur (s. Abschnitt 1.5.2) gehört die Festlegung des Primärschlüssels also zum internen Schema. Im Gegensatz
dazu gehören Identifizierungsschlüssel zum konzeptuellen Schema.
Leider wird zwischen den Ebenen oft nicht sauber getrennt. Die
Bezeichnung Schlüssel wird vielfach auch als Synonym zu Primärschlüssel verstanden.
Eine wesentliche Ursache für diese Vermischung von Begriffen liegt
darin, daß man beim Entwurf der konzeptuellen Schemata durchaus
Rücksicht auf deren Implementierung nehmen muß; dies steht etwas
im Widerspruch zu der Idealvorstellung, wonach die konzeptuellen und
implementierungsbezogenen Aspekte völlig getrennt voneinander auf
den beiden unteren Ebenen der 3-Ebenen-Schema-Architektur behandelt werden können. Betrachten wir hierzu wieder das Beispiel in Bild
4.1. Einer der Identifizierungsschlüssel war {Kundenname, Wohnort}.
Dieser Identifizierungsschlüssel ist i.a. als Primärschlüssel ungeeignet,
weil hier die internen Schlüsselwerte als Konkatenation der beiden Attributwerte gebildeten werden müßten und weil diese Zeichenketten
relativ lang werden können. Aus Effizienzgründen erlauben Implementierungen von B*-Bäumen und ähnlichen internen Strukturen ggf.
nur relativ kurze Schlüsselwerte fester Länge, z.B. ganze Zahlen mit 4
oder 8 Bytes Länge oder Zeichenketten mit 8 Zeichen.
Sofern die “natürlichen” Identifizierungsschlüssel alle als Primärschlüssel ungeeignet sind, muß man ein künstliches Schlüsselattribut
erfinden; hierauf gehen wir in Abschnitt 4.4.4 ausführlicher ein.
4.4.3
Fremdschlüssel
Identifizierungsschlüssel einer Relation werden oft von einer anderen
Relation aus “referenziert”. In unserer Relation lieferungen kam
z.B. das Attribut Kundennummer vor, das Identifizierungsschlüssel in
kunden ist. Es sollte offensichtlich keine Lieferung geben, bei der die
Kundennummer “ins Leere zeigt”, weil sie in kunden nicht auftritt.
Die Abwesenheit solcher Datenfehler bezeichnet man auch als referentielle Integrität. Formal formuliert fordern wir folgende Men-
120
Das relationale Datenbankmodell
geninklusion:
πKundennummer (lieferungen) ⊆ πKundennummer (kunden)
Kundennummer bezeichnen wir als Fremdschlüssel in der Relation lieferungen. Alle Werte, die im Attribut Kundennummer in
lieferungen auftreten, müssen auch im Attribut Kundennummer in
kunden auftreten.
Die allgemeine Definition ist: sei K eine Attributmenge, r eine Relation mit dem Relationentyp R, K ⊆ R, s eine andere Relation mit dem
Relationentyp S und K der Primärschlüssel in S. Wenn K Fremdschlüssel in r (mit Bezug auf s) ist, dann gilt stets
πK (r) ⊆ πK (s)
Das DBMS muß hier verhindern,
1. daß Tupel in s, auf die noch Referenzen in r existieren, gelöscht
werden, und
2. daß Tupel in r erzeugt werden, bei denen der Wert der Fremdschlüsselattribute kein Tupel in s referenziert.
Nullwerte sollten in Fremdschlüsseln vermieden werden. Wenn man
sie zuläßt, bedeutet ein Nullwert, daß unbekannt ist, welches andere
Tupel referenziert wird.
4.4.4
Kriterien für die Festlegung von Identifizierungsund Primärschlüsseln
Identifizierungsschlüssel werden häufig als Fremdschlüssel in anderen
Relationen benutzt; hieraus ergeben sich mehrere Kriterien, die bei
der Festlegung von Identifizierungsschlüsseln beachtet werden sollten:
– Können die Werte beim Eintragen immer sofort bestimmt werden?
Man kann theoretisch auch Nullwerte bei Schlüsselattributen zulassen, praktisch stört dies aber sehr. U.a. können keine Fremdschlüssel-Referenzen auf dieses Tupel in anderen erzeugt werden.
– Sind die Werte kurz und schreibbar? Dies betrifft wieder den Fall,
daß in anderen Relationen Fremdschlüssel-Referenzen von Hand
eingetragen werden müssen.
Das relationale Datenbankmodell
121
– Sind die Werte “sprechend”, d.h. ist den Systembenutzern intuitiv
verständlich, welche reale Entität durch ein Tupel dargestellt wird?
Diese Anforderung steht oft im Widerspruch zu den beiden ersten.
Ein weiteres Kriterium betrifft die zeitliche Entwicklung des Datenbankinhalts. Die aktuell in einem Identifizierungsschlüssel auftretenden Werte müssen natürlich eindeutig sein; zusätzlich kann es sinnvoll
sein, die Eindeutigkeit über die Zeit hinweg zu verlangen. Beispielsweise könnte Kundenname ein Identifizierungsschlüssel sein und derzeit
eine Kundin “Meier, Anna” vorhanden sein. Diese wird irgendwann
gelöscht, und ein Jahr später wird eine andere, neue Kundin eingetragen, die zufällig genauso heißt. Wenn man derartiges vermeiden will,
dürfen einmal benutzte Identifizierungsschlüsselwerte nicht wiederverwendet werden. Hierzu müßte ein Verzeichnis aller jemals verwendeten
Identifizierungsschlüsselwerte geführt werden, was sehr aufwendig und
platzraubend sein kann.
Die vorstehenden Anforderungen werden oft von “natürlichen”
Identifizierungsschlüsseln, die sich aus einer von Implementationsaspekten unbeeinflußten Datenmodellierung ergeben, nicht erfüllt. Beispielsweise sind textuelle Namen zwar oft gut verständlich, aber zu
lang und wiederverwendbar.
Im Endergebnis entscheidet man sich daher oft dazu, ein künstliches Schlüsselattribut, meist eine laufende Nummer, zu erfinden. Das
Attribut Kundennummer ist ein Beispiel hierfür, denn “von Natur aus”
haben Kunden keine Nummer.
4.4.5
Weitere Schlüsselbegriffe
Sofern mehrere Identifizierungsschlüssel vorhanden sind, werden sie
oft auch als Schlüsselkandidaten bezeichnet. Jeder Identifizierungsschlüssel ist ein Kandidat dafür, Primärschlüssel zu werden, nur einer
schafft es. Diese Bezeichnung vermengt die konzeptuelle und interne
Begriffs- und Denkwelt besonders stark, weshalb wir sie weitgehend
vermeiden werden.
Ein Sortierschlüssel (sort key) bestimmt die Reihenfolge, in der
122
Das relationale Datenbankmodell
die Speichersätze in einem DB-Segment gespeichert werden. Hierdurch kann die Verarbeitung kompletter Relationen beschleunigt werden. Ein Sortierschlüssel muß nicht unbedingt identifizierend sein.
Ein Sekundärschlüssel (secondary key) ist eine Menge von Attributen, für die ein Sekundärindex vorhanden ist. Ein Sekundärschlüssel
ist i.a. nicht identifizierend. Der Sekundärindex ist eine Datenstruktur, die jedem Sekundärschlüsselwert eine Liste der Sätze bzw. Tupel
zuordnet, bei denen die entsprechenden Attributwerte auftreten. Beispielsweise könnte es sinnvoll sein, bei der Relation konten einen Sekundärindex für das Attribut Kundenname einzurichten; dies beschleunigt die Suche nach den Kunden mit einem bestimmten Namen erheblich.
Die folgende Tabelle stellt noch einmal alle Schlüsselbegriffe zusammen und gibt jeweils an, ob es sich um einen Begriff der konzeptuellen
oder internen Ebene in der 3-Ebenen-Schema-Architektur handelt und
ob die Attribute identifizierend sind.
Begriff
Identifizierungsschlüssel
Superschlüssel
Schlüsselkandidat
Fremdschlüssel
Primärschlüssel
Sekundärschlüssel
Sortierschlüssel
Ebene
logisch
logisch
logisch
logisch
intern
intern
intern
identifizierend
ja
ja
ja
nein
meist
nein
nein
Implementierungen für Primärschlüssel sind meist so gestaltet,
daß die Eindeutigkeit der Schlüsselwerte erzwungen wird. Man kann
aber auch leicht Varianten dieser Implementierungen bilden, bei denen mehrere Sätze mit dem gleichen Primärschlüsselwert vorhanden
sein dürfen, die dann beim Lesen als Gruppe behandelt werden. Bei
solchen Implementierungen ist ein Primärschlüssel nicht automatisch
auch Identifizierungsschlüssel.
Das relationale Datenbankmodell
123
Glossar
Division: Operation der relationalen Algebra, die in gewisser Weise invers zum Kreuzprodukt ist und mit der Suchaufgaben gelöst werden
können, die All-Quantoren enthalten
Fremdschlüssel: (Kontext: Attributmenge F in Relation R1 ist Fremdschlüssel auf eine Relation R2) Menge von Attributen, die Tupel in
einer anderen Relation identifizieren sollen; ist eine Integritätsbedingung, wonach die Projektion von R1 auf F komplett in der Projektion
von R2 auf F enthalten ist
Identifizierungsschlüssel: minimale Menge von Attributen, die ein Superschlüssel ist
Primärschlüssel: Attribut (-kombination),
terstützt
die der Primärindex un-
Projektion: Operation der relationalen Algebra, mit der in den Tupeln einer Eingaberelation Attribute entfernt werden können; entstehende
Duplikate werden eliminiert
relationale Algebra: Algebra mit den Kernfunktionen relationaler Datenbanksysteme im Bereich der Abfragedienste, insb. Selektion, Projektion, Mengenoperationen, Kreuzprodukt, natürlicher bzw. ThetaVerbund und Division
Relationenschema: Namen und Typen der Attribute einer Relation; Synonyme: Relationentyp, Relationenformat
Schlüssel: Oberbegriff für mehrere spezielle Schlüsselbegriffe; oft als Synonym für Identifizierungsschlüssel benutzt
Schlüsselkandidat: Synonym für Identifizierungsschlüssel
Sekundärschlüssel: Attribut (-kombination), für die ein Sekundärindex
vorhanden ist
Selektion: Operation der relationalen Algebra, mit der Tupel einer Eingaberelation anhand einer Bedingung selektiert werden können
Sortierschlüssel: Attribut (-kombination), nach der intern sortiert gespeichert wird
Spalte (column): einer Tabelle; Synonym: Attribut
Superschlüssel: Menge von Attributen, deren Werte die Tupel einer Relation eindeutig identifizieren
124
Das relationale Datenbankmodell
Tabelle (table): Hauptbestandteile einer relationalen Datenbank; wird oft
als Synonym zu Relation benutzt
Verbund: Operation der relationalen Algebra, mit der die Tupel zweier Eingaberelationen paarweise verbunden werden, sofern Sie eine Verbundbedingung erfüllen; beim Theta-Verbund wird die Verbundbedingung
explizit vorgegeben, beim Gleichheitsverbund werden Attribute der
zu verbindenden Tupel auf Gleichheit getestet, beim natürlichen Verbund werden nur Tupel verbunden, die in allen Attributen, die beiden
Relationen gemeinsam sind, jeweils die gleichen Werte haben
Verbund, äußerer: der linke (rechte) äußere Verbund ist eine Variante der
normalen Verbunde, bei denen Tupel der linken (rechten) Eingaberelation, die keinen Verbundpartner in der rechten (linken) Eingaberelation finden, ergänzt um Nullwerte bei den fehlenden Attributen,
zum Ergebnis hinzugenommen werden; der beidseitige äußere Verbund
liefert die Vereinigung des rechten und linken äußeren Verbunds
Zeile (row ): einer Tabelle; Synonym: Tupel
Lehrmodul 5:
Der relationale Tupel-Kalkül
Zusammenfassung dieses Lehrmoduls
Die relationalen Kalküle sind neben der relationalen Algebra ein
alternativer Formalismus, mit dem sich die grundlegenden Möglichkeiten zur Abfrage von Daten in relationalen Datenbanken definieren
lassen. Dieses Lehrmodul stellt den relationalen Tupel-Kalkül an
Beispielen vor. In der Grundform des Tupel-Kalküls sind Abfragen
möglich, die zu “unendlich” großen Ergebnissen führen. Daher erlaubt
man nur sogenannte sichere Abfragen. Wir diskutieren abschließend
die relationale Vollständigkeit der Kalküle.
Vorausgesetzte Lehrmodule:
obligatorisch:
– Datenverwaltungssysteme
– Das relationale Datenbankmodell
Stoffumfang in Vorlesungsdoppelstunden:
c
2001
Udo Kelter
0.5
Stand: 24.11.2001
126
5.1
Der relationale Tupel-Kalkül
Die relationalen Kalküle
Wenn ein Benutzer bestimmte Daten aus einer relationalen Datenbank
extrahieren will, muß er, wenn er die relationale Algebra (s. Lehrmodul
4) verwendet, einen Ausdruck finden, der die gesuchte Menge konstruiert. Der Benutzer muß also zu seinem Suchproblem eine konstruktive,
prozedurale Lösung finden.
Schöner wäre es, wenn man dem DBMS nur die gesuchten Daten
beschreiben müßte und wenn dann das DBMS selbst einen Weg fände,
das Suchergebnis zu konstruieren. Dies ist gerade die Grundidee der
relationalen Kalküle. Die Frage ist nun, wie der Benutzer dem DBMS
die gesuchten Daten beschreibt. Der grundlegende Ansatz besteht darin, hierbei elementare Vergleichsbedingungen zu verwenden - wie wir
sie schon bei der relationalen Algebra kennengelernt haben -, und auf
dieser Basis aussagenlogische Ausdrücke zu bilden. Man verwendet
hier den Prädikatenkalkül 1. Ordnung mit Quantoren. Letztlich bildet man also ein Prädikat, das die gesuchten Daten beschreibt. Es
gibt nun zwei grundlegende Alternativen, wie man die Parameter für
das Prädikat gestaltet:
– Tupelvariablen: Eine Abfrage hat hier folgende Grundform:
{ t | P (t) }
Das Prädikat P(t) entscheidet für ein Tupel t, ob es zu den gesuchten Daten gehört.
Man spricht hier vom relationalen Tupel-Kalkül (RTK).
– Bereichsvariablen: Eine Abfrage hat hier folgende Grundform:
{ < x1 , x2 , ..., xn > | P (x1 , x2 , ..., xn ) }
Jedes der xi stellt einen Attributwert dar.
Das Prädikat
P (x1 , x2 , ..., xn ) entscheidet für eine Kombination von Attributwerten, ob sie ein Tupel bilden, das zu den gesuchten Daten gehört.
Man spricht hier vom relationalen Bereichskalkül.
Die beiden Varianten sind für unsere Zwecke gleichwertig; wir werden i.f. nur den relationalen Tupel-Kalkül vorstellen.
Der relationale Tupel-Kalkül
5.2
127
Der relationale Tupel-Kalkül
Wir illustrieren den relationalen Tupel-Kalkül an den gleichen BeispielRelationen wie in Lehrmodul 4, s. Bild 5.1.
Tabelle: kunden
Kundennummer Kundenname
177177
Meier, Anne
177180
Büdenbender, Christa
185432
Stötzel, Gyula
167425
Schneider, Peter
171876
Litt, Michael
Tabelle: lieferungen
Datum
Wert
Kundennummer
00-08-12 2730.00
167425
00-08-14
427.50
167425
00-08-02 1233.00
171876
Wohnort
Weidenau
Siegen
Siegen
Netphen
Siegen
Lager
Mitte
Nord
West
Kreditlimit
2000.00
9000.00
4000.00
14000.00
0.00
Lieferadresse
Bahnhofstr. 5
Luisenstr. 13
Bergstr. 33
Abbildung 5.1: Beispieltabellen
Wir werden i.f. folgende Schreibweise benutzen: Wenn A ein Attribut ist und t ein Tupel, dann ist t[A] der Wert des Attributs A in t (auch
als die Projektion des Tupels t auf A bezeichnet). Hierbei unterstellen
wir natürlich A ∈ R, wobei R der Relationentyp von t ist.
5.2.1
Beispiel 1 (Selektion)
Wir suchen hier Kundennummer, Kundenname, Wohnort und
Kreditlimit derjenigen Kunden, deren Kreditlimit über 10000 DM
liegt. Dies liefert uns die folgendermaßen definierte Menge:
{ t | t ∈ kunden ∧ t[Kreditlimit] > 10000 }
Die Bedingung t[Kreditlimit] > 10000 stellt hier eine Selektionsbedingung dar. Statt der hier vorliegenden elementaren Bedingung
128
Der relationale Tupel-Kalkül
sind i.a. natürlich auch komplexe Ausdrücke möglich. Das Beispiel
zeigt, daß Selektionen in den relationalen Kalkülen sehr einfach formulierbar sind. In der relationalen Algebra sieht die Selektion wie
folgt aus:
σKreditlimit>10000 (Kunden)
Im folgenden gehen wir die wichtigsten Operatoren der relationalen
Algebra durch und zeigen beispielhaft, daß auch sie durch entsprechende aussagenlogische Konstrukte nachbildbar sind.
5.2.2
Beispiel 2 (Projektion)
Wir ändern unser voriges Beispiel dahingehend ab, daß wir nur noch
die Namen der Kunden haben wollen. In der relationalen Algebra
würden wir auf dieses Attribut projizieren:
πKundenname (σKreditlimit>10000 (Kunden))
Die Projektion können wir in den aussagenlogischen Ausdrücken
nicht direkt nachbilden. Wir müssen hier die Definition der Projektion direkt einsetzen. Die Projektion einer Relation r auf eine Attributmenge A ist wie folgt definiert:
t ∈ πA (r) ⇔ ∃s ∈ r ∧ s[A] = t[A]
Die vorstehende Definition einer Projektion integrieren wir nun in den
Ausdruck, der unsere gesuchte Menge definiert:
{ t | ∃s ∈ kunden ∧ s[Kreditlimit] > 10000
∧ s[Kundenname] = t[Kundenname]
}
Der Typ des Ergebnisses ist in diesem Beispiel nur implizit definiert. (In Beispiel 1 war er durch die Bedingung t ∈ Kunden explizit definiert.) Dadurch, daß der aussagenlogische Ausdruck den Term
t[Kundenname] enthält, ist implizit festgelegt, daß die Ergebnistupel ein
Attribut namens Kundenname haben. Der Ergebnistyp enthält genau
alle so vorgegebenen Attribute.
Der relationale Tupel-Kalkül
5.2.3
129
Beispiel 3 (Mengenoperationen)
Gesucht sind nun die Nummern aller Kunden, deren Kreditlimit über
10000 DM liegt und die eine Lieferung im Wert von über 1000 DM
bekommen haben. Den hier auftretenden Mengendurchschnitt bilden
wir direkt auf die und-Verknüpfung ab:
{ t | (∃s ∈ kunden ∧ s[Kreditlimit] > 10000
∧ s[Kundennummer] = t[Kundennummer] ) ∧
(∃u ∈ lieferungen ∧ u[Wert] > 1000
∧ u[Kundennummer] = t[Kundennummer] ) }
Analog können wir die Mengenvereinigung durch die oder-Verknüpfung nachbilden und die Mengendifferenz durch eine “und-nicht”Verknüpfung.
5.2.4
Beispiel 4 (natürlicher Verbund)
Gesucht sind nun die Lieferungen im Wert von über 1000 DM, anzugeben ist der Wert und der Name des Kunden. Bei Verwendung der
relationale Algebra würden wir hier einen Verbund bilden:
πKundenname,Wert (σWert>1000 (lieferungen) 1 kunden)
Den Verbund simulieren wir, indem wir in einem aussagenlogischen
Ausdruck die Gleichheit der Werte der Verbundattribute verlangen:
{ t | ∃u ∈ lieferungen ∧ u[Wert] > 1000
∧ t[Wert] = u[Wert]
∧ (∃s ∈ kunden
∧ s[Kundennummer] = u[Kundennummer]
∧ t[Kundenname] = s[Kundenname] )
}
Der eigentliche Test auf Gleichheit der Verbundattribute ist in dem
Teilausdruck s[Kundennummer] = u[Kundennummer] enthalten.
130
5.2.5
Der relationale Tupel-Kalkül
Beispiel 5 (Division)
Wir suchen jetzt die Kundennummern derjenigen Kunden, die schon
von allen Lagern Lieferungen bekommen haben. In der relationalen
Algebra sieht die Lösung wie folgt aus:
πKundennummer,Lager (lieferungen) ÷ πLager (lieferungen)
In den relationalen Kalkülen können wir den all-Quantor direkt einsetzen, ein Umweg über eine Operation wie die Division ist nicht mehr
nötig. Informell ausgedrückt hat die gesuchte Menge folgende Spezifikation:
{ t | ∀ Lager l gilt :
∃ Lief erung f ür Kunde t von Lager l aus }
Konkret ist die Lösung wie folgt:
{ t | ∀ l ( l ∈ lieferungen
⇒ ∃ lf ( lf ∈ lieferungen
∧ l[Lager] = lf [Lager]
∧ t[Kundennummer] = lf [Kundennummer] ) ) }
Die Ergebnistupel haben den Typ {Kundennummer}. Die allquantifizierte Variable l durchläuft die ganze Relation lieferungen
und projiziert diese, da wir im Rest des Ausdrucks nur l[Lager] benutzen, praktisch auf das Attribut Lager. Eine Kundennummer t ist
nur dann im Ergebnis, wenn für alle Lager ein Lieferungstupel lf vorhanden ist, das die Kundennummer t und das Lager l aufweist.
5.3
Syntax von Ausdrücken im RTK
Wie schon erwähnt ist { t | P (t) } die Grundform einer Abfrage im
RTK. Für das darin enthaltene Prädikat gelten die folgenden syntaktischen Regeln:
Erlaubte atomare Ausdrücke sind:
1. s ∈ r falls s eine Tupelvariable und r eine Relation ist
Der relationale Tupel-Kalkül
131
2. s[A] Θ u[B] falls
– s und u Tupelvariable sind
– A und B Attribute gleichen Typs, die bei s bzw. u definiert sind
– Θ ein Vergleichsoperator ist
3. s[A] Θ c falls
– s eine Tupelvariable ist
– A ein Attribut, das bei s definiert ist
– Θ ein Vergleichsoperator ist
– c eine Konstante aus dem Wertebereich von A ist
RTK-Ausdrücke sind generell wie folgt aufgebaut:
1. Atomare Ausdrücke sind RTK-Ausdrücke.
2. Ist P ein RTK-Ausdruck, so sind auch ¬P und (P ) RTK-Ausdrücke.
3. Sind P und Q RTK-Ausdrücke, so sind auch P ∧ Q und P ∨ Q
RTK-Ausdrücke.
4. Ist P (s) ein RTK-Ausdruck mit der freien Tupelvariablen s, so sind
auch ∃s (P (s)) und ∀s (P (s)) RTK-Ausdrücke.
Eine Variable v in einem Ausdruck P heißt frei, wenn P keinen
Quantor über v enthält.
5.4
Sichere RTK-Ausdrücke
Wir hatten bisher noch völlig offengelassen, wie ein DBMS zu einem
gegebenen RTK-Ausdruck die Lösung dieser Suchaufgabe findet. Ein
einfaches Auswertungsverfahren besteht darin, alle involvierten Relationen zu durchlaufen und das Prädikat auszuwerten. Dummerweise
sind auch RTK-Ausdrücke folgender Form möglich:
{ t | ¬(t ∈ kunden)}
Wir verstehen diese Abfrage so, daß die enthaltenen Tupel den Typ
Kunden haben. Verlangt wären hier alle denkbaren Tupel außer denen,
die sich gerade in der Datenbank befinden. Die Anzahl dieser Tupel
ist extrem groß, das Ergebnis kann in der Praxis nicht konstruiert
132
Der relationale Tupel-Kalkül
werden. Derartige “unendliche” Mengen23 sind auch innerhalb von
verschachtelten RTK-Ausdrücken möglich.
Generell können RTK-Ausdrücke, die unendliche Zwischen- oder
Endergebnisse enthalten, nicht ausgewertet werden. RTK-Ausdrücke,
bei denen dieses Problem nicht auftritt, bei denen also beim Arbeiten
auf beliebigen Datenbankinhalten nur “endliche” Resultate auftreten,
bezeichnen wir als sicher.
Ein DBMS würde also dann, wenn der Benutzer einen unsicheren
Ausdruck auswerten lassen will, dies ablehnen. Dazu muß vor Auswertung des Ausdrucks entschieden werden, ob er nun sicher ist oder
nicht. Diese Entscheidung ist nicht immer einfach, weshalb man zwei
Arten von Sicherheit unterscheidet:
– semantische Sicherheit: Dies ist die Sicherheit im allgemeinen
Sinn. Leider ist sie i.a. nicht entscheidbar, d.h. dieser Begriff nützt
uns in der Praxis nichts.
– syntaktische Sicherheit: Hier werden syntaktische Restriktionen
definiert, die hinreichend, aber nicht unbedingt notwendig für die
semantische Sicherheit sind.
Die Grundidee besteht hier darin zu verlangen, daß jede freie
Variable t überall durch Teilausdrücke wie t[A] = c oder t ∈ r an
endliche Wertebereiche gebunden wird, die dann “gefahrlos” durchlaufen werden können. Auf Details wollen wir hier nicht eingehen.
In der Praxis kann man nur mit der syntaktischen Sicherheit arbeiten, d.h. das DBMS wird bestimmte Ausdrücke als unsicher ablehnen,
obwohl sie es inhaltlich nicht sind.
Die Menge der sicheren RTK-Ausdrücke bezeichnen wir mit
SRTK.
Relationale Vollständigkeit. Wir hatten oben bereits beispielhaft
gezeigt, daß man alle Operationen der relationalen Algebra durch
23
Wegen der Endlichkeit der Wertebereiche der Attribute ist natürlich auch die
Zahl der damit konstruierbaren Tupel endlich; praktisch sind die Mengen dennoch
viel zu groß, um mit Rechnern verarbeitet werden zu können.
Der relationale Tupel-Kalkül
133
RTK-Ausdrücke nachbilden kann. Die Frage ist, ob auch die Umkehrung gilt.
Für die allgemeinen RTK-Ausdrücke gilt sie nicht. Dies macht man
sich leicht klar, weil es in der relationalen Algebra kein Äquivalent zu
den unsicheren Ausdrücken gibt: Eine Menge wie { t | ¬(t ∈ kunden)}
kann in der relationalen Algebra nicht konstruiert werden; hierzu
bräuchte man einen “Konstruktor”, der alle Tupel zu einem Relationentyp liefert; von dieser “unendlichen” Menge wäre dann die vorhandene Relation abzuziehen.
Anders verhält es sich beim sicheren RTK: Man kann zeigen, daß
man zu jedem SRTK-Ausdruck einen Ausdruck in der relationalen Algebra finden kann, der das gleiche Ergebnis berechnet. Die relationale
Algebra und der SRTK sind daher gleichmächtig; insb. ist somit auch
der SRTK relational vollständig.
Vergleich von (S)RTK und relationaler Algebra. Nachdem
sich der SRTK und die relationale Algebra bzgl. ihrer Ausdrucksfähigkeit nicht unterscheiden, liegt die Frage nahe, für welche der beiden
Denkwelten man sich entscheiden sollte.
– Wie die obigen Beispiele zeigen, sind viele einfache Beispiele mit
dem RTK umständlicher zu formulieren als mit der relationalen
Algebra.
– Denk- und Schreibweisen mit Quantoren sind für mathematisch ungeübte Benutzer nicht geeignet.
– Der RTK ist leichter als die relationale Algebra um Ausgabeanweisungen und Standardfunktionen (Summe, Maximalwert etc.) erweiterbar.
In der Praxis benutzte Sprachen enthalten stets eine Mischung
aus beiden Denkwelten, also sowohl prozedurale als auch deskriptive
Sprachelemente.
134
Der relationale Tupel-Kalkül
Glossar
relationaler Bereichskalkül: auf Prädikaten basierende Abfragesprache
für relationale Datenbanken, in der einzelne Attribute als Variable
benutzt werden
relationaler Tupel-Kalkül (RTK): auf Prädikaten basierende Abfragesprache für relationale Datenbanken, in der ganze Tupel als Variable
benutzt werden
Sicherheit (von RTK-Ausdrücken): ein RTK-Ausdruck ist sicher, wenn
er ausgewertet werden kann, ohne daß dabei unbeschränkt große
Zwischen- oder Endergebnisse auftreten
Lehrmodul 6:
Einführung in SQL
Zusammenfassung dieses Lehrmoduls
Dieses Lehrmodul führt in die elementaren Kommandos von SQL ein.
Ein Schwerpunkt liegt auf den Möglichkeiten zur Formulierung von
Abfragen. Weiter werden Möglichkeiten zur Definition und Änderung
von Schema gezeigt. Einleitend wird ein Abriß der historischen
Entwicklung und der wichtigsten Varianten von SQL gegeben.
Vorausgesetzte Lehrmodule:
obligatorisch:
– Datenverwaltungssysteme
– Das relationale Datenbankmodell
Stoffumfang in Vorlesungsdoppelstunden:
c
2005
Udo Kelter
1.3
Stand: 16.10.2005
136
6.1
Einführung in SQL
Einführung
SQL ist die mit Abstand wichtigste Sprache für relationale Systeme.
SQL umfaßt Kommandos zur Abfrage und Manipulation von Daten
und Schemata, ferner diverse Administrationsfunktionen. Im Laufe
der Zeit ist der Funktionsumfang von SQL ganz erheblich angewachsen, und es existieren mehrere Varianten der Standards.
Historie. Der Ursprung von SQL geht auf das System/R zurück. System/R war ein Prototyp eines relationalen DBMS, das im Zeitraum
von 1971 - 1981 bei der IBM für deren Mainframes entwickelt wurde. Der Name der Sprache war seinerzeit noch SEQUEL (“Structured
English Query Language”). Später wurde sie umgetauft in “Structured Query Language”, heute liest man die Abkürzung SQL meist als
“Standard Query Language”. 1981 war eine erste kommerzielle Implementierung von SQL durch die IBM verfügbar (SQL/Data System).
Später folgten weitere Implementierungen, einerseits durch die IBM
(DB2, QMF), andererseits durch mehrere konkurrierende Unternehmen, u.a. Oracle, Informix und Sybase.
Aus Sicht von Anwendern ist eine Standardisierung der Sprache
sehr wünschenswert, denn nur dann, wenn unterschiedliche Hersteller Implementierungen der gleichen Sprachdefinition anbieten, ist ein
Wechsel zwischen konkurrierenden Produkten möglich und kann ein
offener Markt entstehen. Dementsprechend wurden zunächst durch
das ANSI bzw. später die ISO mehrere Versionen von SQL standardisiert. Die erste Version wurde unter den Namen SQL1 bzw. SQL86 im
Jahre 1986 verabschiedet. 1989 folgte ein sogenanntes Addendum-1;
der neue Standard wird auch als SQL89 bezeichnet. 1992 folgte die
Version SQL2 bzw. SQL92. Die ersten Standards deckten nur einen
Kern an Funktionen ab; Folge hiervon war, daß in der Praxis viele implementierungsspezifische Erweiterungen notwendig waren, so daß die
unterschiedlichen Implementierungen doch nicht wirklich kompatibel
bzw. austauschbar waren. Erst SQL92 hatte einen relativ vollständigen Funktionsumfang, dieser wurde allerdings von praktisch keinem
Produkt exakt implementiert.
Einführung in SQL
137
Ende der 90er Jahre ist eine neue Version namens SQL3 durch die
ISO publiziert worden. Der Funktionsumfang von SQL3 kann in erster Näherung als unendlich bezeichnet werden, möglicherweise gibt es
keine einzelne Person, die die Spezifikationen komplett gelesen hat.
In diesem einführenden Lehrmodul beschränken wir uns natürlich
auf die wichtigsten Funktionalitäten.
Daß SQL sich als wichtigste relationale Sprache durchgesetzt hat,
liegt übrigens weniger an seinen sprachlichen bzw. technischen Qualitäten, sondern eher an der Macht seiner Anbieter. In der Tat wurde
SQL wegen diverser Mängel von bekannten Datenbankforschern heftig
kritisiert. Dies hat jedoch nichts am Erfolg von SQL ändern können.
SQL definiert sowohl eine “interaktive” Sprache (durch Kommandos wie CREATE TABLE oder SELECT ) als auch ein Programm-API
(durch Kommandos wie DECLARE CURSOR , OPEN , FETCH usw.) Wir
gehen in diesem Lehrmodul nur auf die interaktive Sprache ein.
Bei den folgenden Beispielen verwenden wir Großbuchstaben für
die Schlüsselworte (Kleinbuchstaben sind auch zulässig).
6.2
6.2.1
Abfragen
Grundform
Eine Abfrage in SQL hat folgende Grundstruktur:
SELECT A1, ...., An
FROM r1, ...., rm
WHERE P
Man fängt beim Lesen am besten mit der 2. Klausel, der FROM -Klausel
an. Dort ist angegeben, welche Relationen die Grundlage der Abfrage bilden. In der Begriffswelt der relationalen Algebra bedeutet die
Angabe mehrerer Relationen, daß deren Kreuzprodukt gebildet wird.
Als nächstes sollte man die WHERE -Klausel lesen, sofern sie vorhanden ist (sie ist optional). Sie enthält ein Prädikat, das sich auf die
Relationen beziehen muß, die in der FROM -Klausel angegeben sind. In
der Begriffswelt der relationalen Algebra spezifiziert die WHERE -Klausel
138
Einführung in SQL
eine Selektion. Wenn die WHERE -Klausel fehlt, wird nicht selektiert,
der Vorgabewert für P ist sozusagen true .
Die SELECT -Klausel sollte man zum Schluß lesen. Angegeben ist
dort eine Liste von Attributen, die im Resultat auftreten. Die SELECT Klausel gibt also den Relationentyp des Ergebnisses an. Sie entspricht
einer Projektion auf die angegebenen Attribute; entgegen ihrem Namen stellt sie keine Selektion dar24 . Durch Angabe von * werden alle
Attribute der angegebenen Relationen ausgegeben, d.h. es findet keine
echte Projektion statt.
Übersetzt man die obige Grundform einer SQL-Abfrage also in die
relationale Algebra, ergibt sich folgender Ausdruck:
π A1,....,An (σP ( r1 × . . . × rm ))
Mit anderen Worten kombiniert die Grundform einer SQL-Abfrage
ein Kreuzprodukt, eine Selektion und eine Projektion.
Duplikateliminierung. Der vorstehende Ausdruck in der relationalen Algebra ist in einem Punkt allerdings nicht äquivalent zur SQLAbfrage: bei der SQL-Abfrage werden Duplikate normalerweise nicht
eliminiert. In der relationalen Algebra findet wegen des Rückgriffs
auf die Mengenlehre immer implizit eine Duplikateliminierung statt.
Wenn eine Duplikateliminierung gewünscht wird, muß zusätzlich das
Schlüsselwort DISTINCT in der SELECT -Klausel angegeben werden.
Die Duplikate werden nach der Projektion eliminiert.
Wir verwenden i.f. die schon aus Lehrmodul 4 bekannten Tabellen
kunden und lieferungen (s. Bild 6.1). Die Abfrage
SELECT DISTINCT Wohnort
FROM
kunden
gibt dann drei Tupel aus, und zwar gerade die drei verschiedenen auftretenden Ortsnamen. Ohne DISTINCT würden 5 Tupel ausgegeben.
Es gibt gute Gründe, Duplikate nicht automatisch zu eliminieren. Die Eliminierung erfordert praktisch eine Sortierung, also eine
24
Die bisher erwähnten erheblichen linguistischen Mängel sollten schon ein gewisses Maß an Evidenz für die erwähnte massive Kritik an SQL liefern.
Einführung in SQL
139
bei großen Datenmengen sehr aufwendige Operation. Ferner werden
durch die Duplikateliminierung bestimmte Zähl- und Aggregationsoperatoren beeinflußt.
Tabelle: kunden
Kundennummer Kundenname
177177
Meier, Anne
177180
Büdenbender, Christa
185432
Stötzel, Gyula
167425
Schneider, Peter
171876
Litt, Michael
Tabelle: lieferungen
Datum
Wert
Kundennummer
00-08-12 2730.00
167425
00-08-14
427.50
167425
00-08-02 1233.00
171876
Wohnort
Weidenau
Siegen
Siegen
Netphen
Siegen
Lager
Mitte
Nord
West
Kreditlimit
2000.00
9000.00
4000.00
14000.00
0.00
Lieferadresse
Bahnhofstr. 5
Luisenstr. 13
Bergstr. 33
Abbildung 6.1: Beispieltabellen
6.2.2
Nachbildung der Operationen der relationalen Algebra in SQL
Wie wir oben schon gesehen haben, stellt die Grundform einer Abfrage
in SQL eine Kombination mehrerer Operationen der relationalen Algebra dar. Umgekehrt können alle Operationen der relationalen Algebra
wie in Tabelle 6.2 angegeben in SQL nachgebildet werden. Zu Tabelle
6.2 ist anzumerken:
In der Selektion können die einfachen Vergleichsoperatoren = , <>
(ungleich), < , > , <= und >= sowie diverse andere Vergleichsoperatoren verwendet werden. Bei den Vergleichen mit numerischen Werten
können auch arithmetische Ausdrücke gebildet werden, bei Zeichenketten können in Konstanten folgende Sonderzeichen benutzt werden:
für ein beliebiges Zeichen
140
Einführung in SQL
σA=a (r)
σA=B (r)
πA1 ,...,An (r)
r∪s
r∩s
r−s
r×s
r1s
r[AΘB]s
SELECT DISTINCT
SELECT DISTINCT
SELECT DISTINCT
SELECT DISTINCT
UNION
SELECT DISTINCT
SELECT DISTINCT
INTERSECT
SELECT DISTINCT
SELECT DISTINCT
EXCEPT
SELECT DISTINCT
SELECT DISTINCT
SELECT DISTINCT
SELECT DISTINCT
* FROM r WHERE A = a
* FROM r WHERE A = B
A1 , ..., An FROM r
* FROM r
* FROM s
* FROM r
* FROM s
* FROM r
*
*
*
*
FROM
FROM
FROM
FROM
s
r, s
r NATURAL JOIN s
r, s WHERE r.A Θ s.B
oder
SELECT DISTINCT * FROM r JOIN s ON r.A Θ s.B
Abbildung 6.2: Umsetzung von Operationen der relationalen Algebra
in SQL
%
für mehrere beliebige Zeichen
Als Vergleichsoperator ist dabei LIKE bzw. NOT LIKE zu benutzen.
Elementare Vergleiche können mit den Booleschen Operatoren
AND , OR und NOT verknüpft werden.
Bei den Mengenoperatoren ist bei der in der Tabelle angegebenen
Form Voraussetzung, daß beide Relationen die gleiche Zahl von Attributen haben und die Folge der Wertebereiche der Attribute gleich ist
(die Namen der Attribute spielen dagegen keine Rolle). Es gibt Varianten der Mengenoperationen, bei denen die Felder nicht anhand ihrer
Position, sondern ihres Namens verglichen werden. Anzugeben ist hier
eine Sequenz von Attributnamen; beide Relationen werden dann zuerst
auf diesen Relationentyp projiziert, danach wird die Mengenoperation
ausgeführt.
Einführung in SQL
141
Bei der Vereinigung werden Duplikate eliminiert; will man dies verhindern, muß man den Operator UNION ALL verwenden.
Der Operator NATURAL JOIN für den natürlichen Verbund ist erst
seit SQL2 verfügbar. Ansonsten kann der natürliche Verbund natürlich
auch “von Hand” wie folgt nachgebildet werden:
SELECT DISTINCT r.A1, .., r.Ak, B1, .., Bm, C1, .., Cn
FROM r, s
WHERE r.A1=s.A1 AND ... AND r.Ak=s.Ak
wenn r die Attribute A1, ..., Ak, B1, ..., Bm und s die Attribute A1,
..., Ak, C1, ..., Cn hat. In der WHERE -Klausel werden die gemeinsamen Attribute durch lange Attributnamen identifiziert. Auch in der
SELECT -Klausel müssen die langen Namen verwendet werden, obwohl
die Werte in beiden Relationen gleich sind.
Äußere Verbunde. Der linke, rechte bzw. beidseitige äußere Verbund kann in den folgenden Notationen aufgerufen werden:
SELECT * FROM r LEFT JOIN s ON verbundbedingung
SELECT * FROM r RIGHT JOIN s ON verbundbedingung
SELECT * FROM r FULL JOIN s ON verbundbedingung
Tupelvariablen. Schon bei der relationalen Algebra haben wir das
Problem identifiziert, daß bei Abfragen, die ein Kreuzprodukt einer
Relation mit sich selbst erfordern, die Attribute einer der Relationen
oder diese Relation insgesamt umbenannt werden muß. SQL bietet als
entsprechendes Konstrukt Tupelvariablen an.
Als Beispiel betrachten wir die Suche nach denjenigen Kunden, die
ein größeres Kreditlimit als der Kunde mit Nummer 185432 haben.
Die Lösung ist:
SELECT T.Kundenname
FROM
kunden S, kunden T
WHERE S.Kundennummer = 185432
AND T.Kreditlimit > S.Kreditlimit
142
Einführung in SQL
Umbenennung von ausgegebenen Attributen. In der SELECT Klausel kann jedes ausgegebene Attribut umbenannt werden. Beispiel:
SELECT Kundenname AS Name, Wohnort AS Ort
FROM
kunden
Genutzt werden kann diese Möglichkeit z.B. dazu, die Anzeige von
Tabellen durch Standardanzeigewerkzeuge zu beeinflussen oder um
ähnliche Tabellen in Mengenoperationen verarbeiten zu können. Aggregierte Werte (s.u.), die zunächst keinen Namen haben, können so
benannt werden.
Geschachtelte Abfragen. Die Abarbeitung einer SQL-Abfrage
kann man sich so vorstellen, daß für jede Kombination der Tupel in
den Eingaberelationen die Bedingung in der WHERE -Klausel geprüft
wird; falls die Kombination der Eingabetupel die Bedingung erfüllt,
werden die in der SELECT -Klausel angegebenen Attribute ausgegeben.
Für eine bestimmte Kombination der Eingabetupel kann auch eine
innere Abfrage gebildet werden wie im folgenden Beispiel:
SELECT *
FROM
kunden
WHERE Kreditlimit > 10000 AND
Kundennummer IN
(SELECT Kundennummer
FROM
lieferungen
WHERE
Betrag > 2000)
Es werden hier diejenigen Kunden angezeigt, deren Kreditlimit größer
als 10000 ist und die schon einmal eine Lieferung im Wert von über
2000 Euro bekommen haben. Der Operator IN prüft dabei, ob ein
angegebenes Tupel in der angegebenen Relation enthalten ist. Das
Attribut Kundennummer steht dabei für ein Tupel mit einem Attribut.
Der Operator NOT IN steht für den Test auf Nicht-Enthaltensein.
Es sind auch längere Tupel möglich, dann sind die Attribute in spitzen Klammern durch Komma getrennt aufzulisten, wie in folgendem
Schema:
Einführung in SQL
143
WHERE < A1, A2, ... > IN (SELECT A1, A2, ....
FROM .... WHERE .... )
SOME- und ALL-Operatoren. Ein allgemeinere Version des Enthaltenseinstests stellen die SOME-Operatoren dar. Der Operator > SOME
testet, ob der angegebene Wert größer als irgendein Tupel in der angegebenen Relation ist. Analog arbeiten weitere SOME-Operatoren für
≥, <, ≤, =, 6=.
Analog zu den SOME-Operatoren gibt es entsprechende ALL-Operatoren, bei denen geprüft wird, ob alle Werte in der angegebenen
Relation größer, kleiner usw. als der Vergleichswert sind.
Sortierung der Ausgabetabelle. Mithilfe der ORDER BY -Klausel
kann die Ausgabetabelle nach einem oder mehreren Attributen sortiert
werden. Pro Attribut kann eine aufsteigende (Schlüsselwort ASC ; Vorgabe) oder fallende (Schlüsselwort DESC ) Sortierreihenfolge gewählt
werden. Beispiel:
SELECT * FROM lieferungen
ORDER BY Kundennummer ASC, Datum DESC
Die Attribute, nach denen sortiert wird, müssen ausgegebene Attribute gemäß der SELECT -Klausel sein.
6.2.3
Gruppierungen und Aggregationen
Vielfach will man die Tupel einer Relation anhand bestimmter Attributwerte gruppieren und die so entstehenden Gruppen zählen oder
bestimmte Attributewerte innerhalb der Gruppe aufsummieren. Hierzu ein Beispiel: wir möchten für unsere Beispieldatenbank für jeden
Kunden folgendes wissen:
– die Anzahl der Lieferungen, die an ihn gegangen sind, und
– den Gesamtwert der Lieferungen
Gesucht ist also eine Abfrage, die eine Relation mit drei Spalten liefert:
dem Kundennamen (oder die Nummer) und die beiden vorstehenden
Angaben.
144
Einführung in SQL
Die Zahl der Lieferungen an einen bestimmten Kunden ist gerade
die Zahl der lieferungen-Tupel, die sich auf diesen Kunden beziehen.
Wenn X die Kundennummer eines Kunden ist, dann könnten wir diese Tupelmenge mit der Abfrage SELECT * FROM lieferungen WHERE
Kundennummer = X bestimmen.
Man könnte nun auf die Idee kommen, irgendwie in einer Schleife
alle auftretenden Kundennummern zu durchlaufen, jedesmal diese Abfrage zu starten und die Ergebnismenge zu zählen bzw. die Werte im
Attribut Betrag aufzusummieren und die Ergebnistabelle zeilenweisen irgendwie zusammenzusetzen. Das ist eine typische prodedurale
Denkweise; würden die Daten als Java-Laufzeitobjekte vorliegen und
müßten wir ein imperatives Programm schreiben, das die gewünschten Angaben berechnet, wäre diese Denkweise durchaus in Ordnung.
In relationalen Sprachen ist diese Denkweise ein typischer Anfängerfehler und zum Scheitern verurteilt: relationale Sprachen sind nichtprozedural, Schleifen sind nicht vorgesehen und werden sinngemäß
durch andere Konstrukte ersetzt.
In der Tat können die oben erwähnten Zählungen und Summierungen überhaupt nicht mit den Mitteln der relationalen Algebra oder
äquivalenter Sprachkonstrukte in SQL realisiert werden. SQL bietet
aber mit der GROUP BY-Klausel und weiteren Sprachkonstrukten eine
Lösungsmöglichkeit. Unsere Aufgabe können wir in SQL wie folgt
lösen:
SELECT
Kundennummer, COUNT(*), SUM(Betrag)
FROM
lieferungen
GROUP BY Kundennummer
Die GROUP BY-Klausel verändert die Bedeutung der SELECTAnweisung wie folgt:
1. Zunächst werden wie üblich Kreuzprodukte bzw. Verbunde gebildet, sofern mehrere Relationen in der FROM-Klausel angegeben sind,
und die resultierenden Tupel gemäß der WHERE-Klausel, sofern vorhanden, selektiert.
2. Die verbleibenden Tupel werden in Gruppen eingeteilt. Das Attribut, das in der GROUP BY-Klausel angegeben wird, wird i.f. Grup-
Einführung in SQL
145
pierungsattribut genannt. Für jeden Wert X, der im Gruppierungsattribut auftritt, wird eine Gruppe gebildet. Zu dieser Gruppe gehören alle Tupel, die den Wert X im Gruppierungsattribut
haben. In unserem Beispiel wird also für jede auftretende Kundennummer eine Gruppe gebildet, die gerade die Lieferungstupel mit
dieser Kundennummer enthält.
Wenn mehrere Gruppierungsattribute angegeben werden, wird
analog zu jeder Kombination von Werten in den Gruppierungsattributen eine Gruppe gebildet.
3. Für jede Gruppe (und nicht etwa für jedes Eingabetupel!) wird genau ein Tupel ausgegeben. Als Ausgabeattribute bzw. -Werte sind
erlaubt:
– Gruppierungsattribute - deren Wert ist nach Konstruktion bei
allen Tupeln in der Gruppe gleich; Attribute, die keine Gruppierungsattribute sind, sind dagegen nicht zulässig, denn deren
Wert kann in der Gruppe verschieden sein, d.h. es ist unklar,
welcher der auftretenden Werte ausgegeben werden soll;
– Aggregationsoperatoren
Die Liste der Aggregationsoperatoren ist:
COUNT: Anzahl
AVG: Durchschnitt
MIN: Minimum
MAX: Maximum
SUM: Summe
Bei den numerischen Aggregationsoperatoren (alle außer COUNT) ist
als Argument ein numerisches Attribut anzugeben. In die angegebene
Operation werden alle Attributwerte einbezogen, die nicht NULL sind.
Der Operator COUNT zählt die Tupel; als Argument muß entweder
ein Attribut angegeben werden, dann zählt COUNT die Tupel, bei denen
dieses Attribut nicht NULL ist, oder * , dann zählt COUNT alle Tupel.
In unserer obigen Musterlösung erzeugt also COUNT (*) die Zahl der
Lieferungen eines Kunden und SUM(Betrag) den Gesamtwert aller
Lieferungen.
146
Einführung in SQL
Sofern die GROUP BY -Klausel fehlt und trotzdem in der SELECTKlausel ein Aggregationsoperator benutzt wird, bildet die ganze Relation eine einzige Gruppe. So kann man z.B. durch die Abfrage
SELECT count(*) FROM r
die Zahl der Tupel der Relation r gezählt werden. Da pro Gruppe nur
ein Tupel ausgegeben wird, wird hier nur eine einzige Zahl ausgegeben.
Aggregation und Verbunde. Wenn wir im obigen Beispiel nicht
nur die Kundennummer, sondern auch die Kundennamen ausgeben
wollen, müssen wir einen Verbund mit der Relation kunden bilden
und die Lösung wie folgt modifizieren:
SELECT
lieferungen.Kundennummer, Kundenname,
COUNT(*), SUM(Betrag)
FROM
lieferungen NATURAL JOIN kunden
GROUP BY lieferungen.Kundennummer, Kundenname
Zunächst unmotiviert wirkt hier, daß auch das Attribut Kundenname
als Gruppierungsattribut angegeben wird. Die Gruppen werden durch
dieses zusätzliche Attribut nicht kleiner, weil innerhalb jeder Gruppe
der Kundenname gleich ist. Dieses Wissen fehlt dem SQL-Prozessor
aber im allgemeinen Fall, daher müssen alle auszugebenden Attribute
in der GROUP BY -Klausel angegeben werden.
Es sei noch darauf hingewiesen, daß die obige Musterlösung für diejenigen Kunden, die noch keine Lieferung bekommen haben, gar kein
Tupel enthält, also auch kein Tupel, das in der 3. und 4. Spalte eine
Null enthält. Sind derartige Aufgabetupel für die “leeren Gruppen”
gewünscht, muß der natürliche Verbund durch einen äußeren Verbund
(im vorliegenden Fall reicht der rechte äußere Verbund) ersetzt werden, ferner COUNT(*) durch COUNT(Kundenname) , damit die Tupel,
die durch den äußeren Verbund mit Nullerwerten erzeugt werden, nicht
mitgezählt werden.
Bedingungen mit aggregierten Werten. Angenommen, wir suchen die Kunden, die schon im Wert von über 10.000 Euro gekauft haben. Die Summe der bisherigen Käufe können wird zwar in
Einführung in SQL
147
der SELECT -Klausel mit SUM(Betrag) ausgeben, nicht hingegen in
der WHERE -Klausel für Selektionsbedingungen ausnutzen. Wie schon
erwähnt wird die WHERE -Klausel vor der Gruppierung ausgewertet;
Aggregationsoperatoren können daher in der WHERE -Klausel nie auftreten.
Um die ausgegebenen Tupel, die jeweils einer Gruppe entsprechen, zu selektieren (und nicht etwa die Eingabetupel), bietet SQL
die HAVING -Klausel an:
SELECT
Kundennummer, SUM(Betrag)
FROM
lieferungen
GROUP BY Kundennummer
HAVING
SUM(Betrag) > 10000
Schachtelungen von Aggregationsoperatoren. Diese sind nicht
erlaubt, stattdessen muß auf eine Ersatzkonstruktion ausgewichen
werden. Wenn wir z.B. den oder die Kunden mit dem maximalen Gesamtumsatz suchen, können wir nicht HAVING SUM(Betrag) =
MAX(SUM(Betrag)) als Bedingung angeben. Stattdessen muß eine eingeschachtelte Abfrage benutzt werden:
SELECT
Kundennummer, SUM(Betrag)
FROM
lieferungen
GROUP BY Kundennummer
HAVING
SUM(Betrag) >= ALL
(SELECT SUM(Betrag)
FROM
lieferungen
GROUP BY Kundennummer)
6.3
6.3.1
Änderungsoperationen
Erzeugen von Tupeln
Tupel können mit dem INSERT-Kommando erzeugt werden, z.B.:
INSERT INTO kunden
VALUES (131415, "Groll, Renate", "Bamberg", 12000)
148
Einführung in SQL
In der VALUES-Klausel müssen die Attributwerte des zu erzeugenden
Tupels in der Reihenfolge gemäß der Definition des Relationentyps
angeordnet sein. Alternativ kann die Reihenfolge der Attribute auch
explizit bestimmt werden:
INSERT INTO kunden
(Kundenname, Wohnort, Kundennummer, Kreditlimit)
VALUES ("Groll, Renate", "Bamberg", 131415, 12000 )
Es ist auch möglich, nur eine Teilmenge der Attribute anzugeben. Für
die fehlenden Attribute werden Nullwerte oder Vorgabewerte eingesetzt; dies kann bei der Definition des Relationentyps festgelegt werden.
Eine Variante des INSERT-Kommandos ermöglicht es, Tupel, die
aus anderen Relationen als Ergebnis einer Abfrage bestimmt worden
sind, einzufügen, also zu kopieren. Beispiel:
INSERT INTO lieferungen (Kundennummer, Lieferadresse,
Betrag, Datum)
SELECT Kundennummer, Wohnort, 100, 24.12.2000
FROM
kunden
WHERE Kreditlimit > 10000
Dieses Kommando fügt in die Relation lieferungen für alle Kunden,
die ein Kreditlimit von über 10000 Euro haben, eine Weihnachtslieferung im Wert von 100 Euro ein.
6.3.2
Löschen von Tupeln
Die Grundform des Löschkommandos ist
DELETE FROM r
WHERE B
Dabei ist B eine Bedingung wie bei der SELECT-Anweisung. Der Effekt der Anweisung besteht darin, daß die Tupel, die die Bedingung B
erfüllen, in der Relation r gelöscht werden. Wenn die WHERE-Klausel
fehlt, werden alle Tupel gelöscht, die anschließend leere Relation besteht weiter. In der FROM-Klausel kann immer nur eine Relation ange-
Einführung in SQL
149
geben werden. Wenn man in mehreren Relationen Tupel löschen will,
muß man pro Relation ein eigenes Löschkommando abgeben. Einige
Beispiele:
– Löschen des Kunden mit Kundennummer 131415:
DELETE FROM kunden
WHERE Kundennummer = 131415
– Löschen aller Lieferungen an den Kunden mit Kundennummer
131415
DELETE FROM lieferungen
WHERE Kundennummer = 131415
– Löschen aller Kunden, die noch keine Lieferung bekommen haben
DELETE FROM kunden
WHERE 0 = (SELECT COUNT (*) FROM lieferungen
WHERE kunden.Kundennummer =
lieferungen.Kundennummer
)
Probleme können bei eingeschachtelten SELECT-Anweisungen auftreten. Betrachten wir hierzu folgendes Beispiel:
DELETE FROM kunden
WHERE Kreditlimit < (SELECT AVG(Kreditlimit)
FROM
kunden
)
Dieses Kommando soll diejenigen Kunden löschen, deren Kreditlimit
unter dem durchschnittlichen Kreditlimit liegt. Wenn man nun alle
Tupel der Relation der Reihe nach durchläuft und jedesmal die innere SELECT-Anweisung neu berechnet, werden zu viele Tupel gelöscht:
wenn die ersten Tupel mit kleinem Kreditlimit gelöscht worden sind,
steigt das durchschnittliche Kreditlimit an, so daß bei späteren Auswertungen der Löschbedingung ein höherer Vergleichswert benutzt
wird.
Eine Lösung des Problems kann darin bestehen, Tupel während
der Abarbeitung des DELETE-Kommandos nicht wirklich zu löschen,
150
Einführung in SQL
sondern nur als zu löschend zu markieren und die tatsächliche
Löschung erst am Ende, also nach Auswertung aller inneren SELECTAnweisungen, vorzunehmen. Eine andere, einfachere Lösung besteht
darin, solche Löschkommandos gar nicht zuzulassen.
6.3.3
Ändern von Tupeln
Mit Hilfe des UPDATE-Kommandos kann man einzelne Attributwerte
ändern. Die restlichen Attribute der betroffenen Tupel bleiben unverändert. Als Beispiel betrachten wir die Erhöhung der Kreditlimits
aller Siegener Kunden um 50 %:
UPDATE kunden
SET
Kreditlimit = Kreditlimit * 1.5
WHERE Wohnort = "Siegen"
In der WHERE-Klausel sind eingeschachtelte SELECT-Anweisungen
erlaubt, allerdings dürfen sich diese nicht auf die geändert werdende
Relation beziehen.
6.4
Nullwerte
Wenn man beim Einfügen von Tupeln nur eine Teilmenge aller Attribute angibt und bei den übrigen Attributen keine Vorgabewerte
definiert sind, erhalten diese als Wert den Nullwert. Das gleiche passiert, wenn Tupel über Sichten, die als Projektion definiert sind (s. Abschnitt 6.5.3), eingefügt werden. Neben diesen technischen Gründen
ist eine weitere Ursache für Nullwerte, daß die tatsächlichen Werte
(noch) nicht bekannt oder anwendbar sind. Betrachten wir hierzu das
Attribut Kreditlimit der Relation kunden:
– Manche unserer Kunden sind Laufkundschaft; sie bezahlen immer
bar. Das Attribut Kreditlimit ist für sie sinnlos.
– Für Kunden, die beantragen, bei uns auf Kredit kaufen zu können,
holen wir zuerst eine Bankauskunft ein. Solange die Bankauskunft
nicht vorliegt, kann das Kreditlimit nicht festgelegt werden. Angenommen, wir hätten ein weiteres Attribut DatumBankauskunft,
Einführung in SQL
151
das das Datum der Bankauskunft enthält. Solange hier kein Datum
steht, wäre das Attribut Kreditlimit nicht anwendbar.
– Selbst nach Vorliegen der (positiven) Bankauskunft muß erst der
Chef das Kreditlimit konkret festlegen; solange er dies nicht getan
hat, ist der Kunde zwar kreditwürdig, aber sein Kreditlimit noch
unbekannt.
Man könnte in allen vorstehenden Fällen den Wert des Attributs
Kreditlimit auf 0,00 setzen, allerdings wären die drei vorstehenden
Fälle und der vierte Fall, daß bei dem Kunden trotz positiver Bankauskunft das Kreditlimit vorerst auf 0,00 gesetzt wird, nicht unterscheidbar.
Um die vorstehenden Fälle sauber unterscheiden zu können,
bräuchte man eigentlich drei verschiedene Nullwerte. Eigentlich müßte
man eher von Nichtanwendbarkeits- oder Unbekannt-Werten (oder
-Anzeigen) reden, dies sind keine wirklichen Werte aus den Wertebereich der Attribute.
SQL unterstützt genau einen Nullwert. Man muß somit alle eigentlich unterschiedlichen Nichtanwendbarkeits- oder Unbekannt-Werte
auf diesen einen Nullwert abbilden, verliert also Information. Nullwerte sind daher und aus anderen Gründen problematisch. Der Nullwert
kann mit dem Schlüsselwort NULL explizit gesetzt werden. Beispiel:
INSERT INTO kunden
VALUES (131415, "Groll, Renate", "Bamberg", NULL)
Wenn zwei Tupel in einem Attribut beide den Wert NULL haben,
bedeutet das nicht, daß beide den gleichen Wert in diesem Attribut
haben. Der Wert ist in diesem Fall schlicht unbekannt, mit sehr hoher
Wahrscheinlichkeit aber verschieden. Das gleiche gilt bei einem Vergleich mit einer Konstanten. Das Resultat eines Vergleichs mit einem
Nullwert wird daher so definiert, daß immer ein negatives Ergebnis geliefert wird. Eigentlich ist das falsch, eigentlich kann man das Resultat
gar nicht exakt bestimmen, weil man den oder die Vergleichswerte gar
nicht kennt. Die negativen Vergleichsresultate führen zu unerwarteten
Effekten. Bei der folgenden Abfrage
152
Einführung in SQL
SELECT * FROM r
WHERE A > 0 OR A =< 0
ist die Bedingung in der WHERE-Klausel mathematisch gesehen eine
Tautologie, und man könnte glauben, es würde somit die gesamte Relation r zurückgeliefert. Dies trifft nicht zu, die Tupel, bei denen der
Wert von A NULL ist, fehlen im Ergebnis. Ob der Nullwert vorliegt,
kann wie folgt getestet werden:
SELECT * FROM r
WHERE A IS NULL
Analog testet IS NOT NULL , ob kein Nullwert vorliegt.
Bei den Aggregationsoperatoren außer COUNT zählen Tupel, die bei
dem relevanten Attribut den Wert NULL haben, überhaupt nicht mit,
d.h. der aggregierte Wert wird auf Basis der übrigen Tupel gebildet.
Der wirkliche aggregierte Wert ist natürlich unbekannt, der angegebene ist wahrscheinlich der richtige oder er liegt nahe beim richtigen
Wert. Wenn man sich dieses Sachverhalts oder der Anwesenheit der
Nullwerte nicht bewußt ist, können die ausgegebenen Zahlen falsch
interpretiert werden.
6.5
Schema-Operationen
Ein Schema in SQL umfaßt Angaben aus mehreren Bereichen, neben
der Definition von Relationen und Sichten z.B. auch Angaben zur Autorisierung. Wir gehen hier nur auf die Definition von Relationen und
Sichten ein.
Eine Relation wird in SQL als Tabelle (table) bezeichnet, ein Attribut als (Tabellen-) Spalte (column) und ein Tupel als Zeile (row).
In einer Datenbank kann es mehrere Schemata geben; diese werden
im Katalog verwaltet. Bestimmte Teile der Schemata, z.B. Bereichsdefinitionen, können in mehreren Schemata eines Katalogs wiederverwendet werden.
Bei den folgenden Syntaxdefinitionen verwenden wir Großbuchstaben für die Schlüsselworte (Kleinschreibung ist auch zulässig) und
Kleinbuchstaben für die nichtterminalen Bezeichner.
Einführung in SQL
6.5.1
153
Definition von Relationen
Tabellen werden mit dem Kommando CREATE TABLE erzeugt. Vereinfacht (ohne Berücksichtigung diverser Optionen) hat es folgenden
Aufbau:
CREATE TABLE table-name
( list-of-table-elements )
Als Beispiel betrachten wir die Definition unserer Relation kunden:
CREATE TABLE kunden (
Kundennummer DECIMAL(6) NOT NULL,
Kundenname
CHAR(20),
Wohnort
CHAR(15),
Kreditlimit DECIMAL(9,2),
PRIMARY KEY (Kundennummer)
)
Ein Element der Tabellendefinition ist eine Attributdefinition oder eine
Integritätsbedingung. Die Definition unserer Relation kunden enthält
vier Attributdefinitionen und eine Integritätsbedingung. Die einzelnen
Elemente werden durch ein Komma voneinander getrennt.
6.5.1.1
Attributdefinitionen
Im obigen Beispiel ist zu jedem Attributnamen ein Wertebereich angegeben. Die Denkwelt für diese Wertebereichs- bzw. Typangaben
orientiert sich eher an Programmiersprachen wie COBOL als an Pascal oder C. Dies ist kein Zufall, da diese Sprachen bei betrieblichen
Anwendungen als Gastsprachen nach wie vor dominieren. Als Datentypen stehen u.a. zur Verfügung:
CHAR(l ) oder CHARACTER (l ): Zeichenkette mit der festen Länge l
VARCHAR(l ) oder CHARACTER VARYING (l ): Zeichenkette mit einer
variablen Länge, maximal aber l Zeichen
DEC(l,m) oder DECIMAL (l,m): Dezimalzahlen mit l Stellen vor dem
Komma und m Stellen hinter dem Komma
154
Einführung in SQL
INT oder INTEGER, SMALLINT
FLOAT, REAL, DOUBLE PRECISION: diverse Fließkomma-Formate
DATE, TIME, INTERVAL u.a.: diverse Formate für Datum und Uhrzeit
Die Angabe NOT NULL schließt Nullwerte bei diesem Attribut aus.
Durch eine Angabe DEFAULT wert kann ein Vorgabewert spezifiziert werden. Als Vorgabewert kann auch NULL spezifiziert werden.
Ein einzelner Wertebereich kann auch explizit mit einem Namen
versehen werden und dann in verschiedenen Relationen benutzt werden. Als Beispiel führen wir dies für das Attribut Kundennummer durch:
CREATE DOMAIN Kundennummertyp AS DECIMAL(6) NOT NULL;
CREATE TABLE kunden (
Kundennummer
Kundennummertyp,
.....
)
Die Definition eines Attributs innerhalb der Definition einer Tabelle hat insg. folgende Struktur:
column-name { data-type | domain }
[ DEFAULT { wert | NULL } ]
[ list-of-column-constraints ]
6.5.1.2
Definition von Integritätsbedingungen
SQL bietet sehr umfangreiche Konzepte zur Integritätssicherung. Wir
stellen hier nur Möglichkeiten zur Definition von Schlüsseln vor.
Identifizierungsschlüssel.
gabe
Eine Attributmenge kann durch die An-
UNIQUE ( list-of-column-names )
als Identifizierungsschlüssel definiert werden. Sofern diese Attributmenge einelementig ist, kann die Schlüsseleigenschaft auch direkt bei
Einführung in SQL
155
der Attributdefinition durch das Schlüsselwort UNIQUE angegeben werden. Sofern ein Identifizierungsschlüssel angegeben ist, muß auch ein
Primärschlüssel angegeben werden.
Nullwerte sind in Identifizierungsschlüsseln erlaubt. Es kann sogar
mehrere Tupel geben, die den Wert NULL in einem oder mehreren Attributen des Identifizierungsschlüssels haben. Es wird hier unterstellt,
daß die wirklichen Werte alle verschieden sind.
Primärschlüssel.
Eine Attributmenge kann durch die Angabe
PRIMARY KEY ( list-of-column-names )
als Primärschlüssel definiert werden; implizit wird die Attributmenge damit gleichzeitig als Identifizierungsschlüssel definiert. Es kann
mehrere Identifizierungsschlüssel, aber nur einen Primärschlüssel geben (vgl. Lehrmodul 4). Wie schon erwähnt ist die Spezifikation eines
Primärschlüssels eine Frage, die in der 3-Ebenen-Schema-Architektur
dem internen Schema zuzuordnen ist. M.a.W. werden hier Angaben zum konzeptuellen und zum internen Schema der Datenbank vermengt.
In den Attributen eines Primärschlüssels sind Nullwerte nicht erlaubt.
Fremdschlüssel. Ein Fremdschlüssel wird wie folgt angegeben:
FOREIGN KEY ( list-of-column-names )
REFERENCES table-name [ ( list-of-column-names ) ]
In unserer Relation lieferungen war z.B. das Attribut Kundennummer
ein Fremdschlüssel für das Attribut Kundennummer in der Relation
kunden. In SQL wird dies wie folgt notiert:
CREATE TABLE lieferungen (
Kundennummer
Kundennummertyp,
.....
FOREIGN KEY ( Kundennummer ) REFERENCES kunden;
);
156
Einführung in SQL
Die Liste der Attributnamen hinter dem Schlüsselwort REFERENCES
braucht nur dann angegeben zu werden, wenn dort Attribute mit anderen Namen referenziert werden sollen. Bei einer einelementigen Attributmenge kann die Fremdschlüsseleigenschaft auch innerhalb der
Attributdefinition angegeben werden, z.B.:
CREATE TABLE lieferungen (
Kundennummer
Kundennummertyp REFERENCES kunden,
.....
);
Nach dem Einrichten eines Fremdschlüssels verhindert das DBMS
“defekte Referenzen”, also Wertekombinationen in den Fremdschlüsselattributen in der referenzierenden Relation, die in der referenzierten
Relation nicht auftreten.
Eine Einfüge- oder Änderungsoperation in der referenzierenden Relation, die zu einer defekten Referenz führen würde, wird vom DBMS
mit einer Fehlermeldung abgebrochen.
Defekte Referenzen können auch durch Löschungen oder Änderungen in der referenzierten Relation entstehen; hier sind verschiedene
Reaktionen sinnvoll und durch zusätzliche Optionen in der FOREIGN
KEY-Klausel wählbar. Bei einer Löschung gibt es folgende Optionen:
1. NO ACTION: Der Löschversuch wird abgelehnt, das Tupel nicht gelöscht. Dies ist die Voreinstellung. Bei allen folgenden Alternativen
wird das zu löschende Tupel tatsächlich gelöscht.
2. CASCADE: Alle Tupel in der referenzierenden Tabelle, die das gelöschte Tupel referenzieren, werden ebenfalls gelöscht. Würde man
also in der Relation kunden ein Kundentupel löschen, würden implizit auch alle Lieferungstupel für diesen Kunden in der Relation
lieferungen gelöscht.
Die implizit gelöschten Tupel könnten ihrerseits Ziel von Referenzen aus einer dritten Relation sein. Beispielsweise könnten wir
eine weitere Relation haben, die zu jeder Lieferung die einzelnen
gelieferten Posten angibt und die einen Fremdschlüssel auf ein zusätzliches Attribut Lieferscheinnummer in lieferungen enthält.
Wenn dieser Fremdschlüssel ebenfalls mit der Option CASCADE an-
Einführung in SQL
157
gegeben wäre, würden beim Löschen eines Kunden auch alle Lieferposten aller seiner Lieferungen gelöscht werden.
3. SET NULL: In der referenzierenden Tabelle werden die entstehenden defekten Referenzen auf NULL gesetzt. Diese Option ist nur
zulässig, wenn die Attribute des Fremdschlüssels nicht als NOT NULL
definiert sind.
4. SET DEFAULT: In der referenzierenden Tabelle werden die Attribute
in den entstehenden defekten Referenzen auf ihren jeweiligen Vorgabewert gesetzt. Diese Option ist nur zulässig, wenn für diese
Attribute Vorgabewerte definiert worden sind.
Mit dem Schlüsselwort ON DELETE kann das gewünschte Verhalten
bei Löschungen angegeben werden. Beispiel:
CREATE TABLE lieferungen (
Kundennummer
Kundennummertyp,
.....
FOREIGN KEY ( Kundennummer ) REFERENCES kunden
ON DELETE CASCADE
);
Das Verhalten bei Änderungen muß separat angegeben werden, und
zwar mit dem Schlüsselwort ON UPDATE. Die wählbaren Alternativen
sind die gleichen wie bei Löschungen, allerdings bekommt CASCADE eine
andere Bedeutung: Alle Tupel in der referenzierenden Tabelle, die das
geänderte Tupel referenzieren, werden passend mitgeändert, so daß die
damit ausgedrückte Beziehung erhalten bleibt.
6.5.2
Änderung der Definition einer Relation
Nachdem eine Relation einmal erzeugt und mit Daten gefüllt worden
ist, können auch noch nachträglich Details der Definition geändert
werden. Hierzu dient das ALTER -Kommando:
ALTER TABLE table-name
{ ADD [column] column-name data-type
| ALTER [column] column-name
{ DROP DEFAULT | SET default-definition }
158
Einführung in SQL
| ADD [CONSTRAINT constraint-name]
{ UNIQUE ( list-of-column-names )
| PRIMARY KEY ( list-of-column-names )
| FOREIGN KEY ( list-of-column-names )
REFERENCES table-name [ ( .... ) ]
| ..... }
| DROP CONSTRAINT constraint-name
}
Mit dem DROP -Kommando können Domänen, Tabellen, Sichten
und ganze Schemata gelöscht werden.
6.5.3
Sichten
Eine Sicht (view) (s. Lehrmodul 1) ist eine virtuelle Tabelle, die aus
anderen Tabellen abgeleitet ist. Tabellen, die keine Sichten sind, nennen wir auch Basistabellen. Im Gegensatz zu einer Basistabelle ist
eine Sicht nicht physisch gespeichert, sondern wird bei jeder Benutzung dynamisch berechnet. Definiert wird eine Sicht mit dem CREATE
VIEW -Kommando:
CREATE VIEW view-name [ ( list-of-column-names ) ]
AS select-expression
Die Sicht wird hauptsächlich durch eine Abfrage (die SELECT-expression ) bestimmt. In dieser Abfrage können wiederum Sichten in der
FROM-Klausel benutzt werden.
Glossar
Aggregation (im Kontext von SQL): Ausgabe auf Basis von Gruppen von
Tupeln; je eine Gruppe bilden die Tupel, die in den sog. Gruppierungsattributen gleiche Werte haben; ausgegeben wird pro Gruppe
nur ein Tupel, dessen Attribute können sein: a. Gruppierungsattribute, b. über die Gruppe aggregierte Werte, insb. Zählungen und für ein
bestimmtes Attribut Summe, Minimum, Maximum und Durchschnitt
der Werte, die in der Gruppe auftreten
Einführung in SQL
159
Katalog: Teil der Datenbank, in dem die Schemata repräsentiert werden
Nullwert: spezieller Wert eines Attributs, der ausdrückt, daß der Wert nicht
angegeben werden kann, z.B. weil der wirkliche Wert (noch) nicht bekannt ist, das Attribut bei diesem Tupel nicht sinnvoll anwendbar ist
oder sonstige Gründe vorliegen
Sicht (im Kontext von SQL) (view ): virtuelle Tabelle, die mittels einer Abfrage definiert wird
SQL: von der ISO und anderen Standardisierungsinstitutionen in mehreren
Varianten definierte Sprache für relationale Datenbanken
Lehrmodul 7:
Implementierung relationaler
Operationen
Zusammenfassung dieses Lehrmoduls
Aus der formalen Definition der relationalen Operationen ergeben sich unmittelbar triviale Implementierungen. Diese sind in vielen
Fällen sehr ineffizient, besonders bei Selektionen und Verbunden.
Dieses Lehrmodul stellt effizientere Implementierungen vor; meist
werden hierbei Primär- oder Sekundärindexe ausgenutzt.
Vorausgesetzte Lehrmodule:
obligatorisch:
– Das relationale Datenbankmodell
Stoffumfang in Vorlesungsdoppelstunden:
Stand: 30.11.2002
0.8
c
2002
Udo Kelter
Implementierung relationaler Operationen
7.1
161
Einleitung
Die Bedeutung der relationalen Operationen kann in sehr präziser,
aber dennoch abstrakter Weise unter Benutzung mathematischer Begriffe (insb. der Mengenlehre) definiert werden, s. Lehrmodul 4. Diese Definitionen kann man auch direkt in triviale Implementierungen
umsetzen. Man erkennt aber leicht, daß diese trivialen Implementierungen teilweise extrem ineffizient und daher inpraktikabel sind. In
diesem Lehrmodul betrachten wir effizientere Implementierungen; diese beruhen teilweise auf Indexen.
Wir betrachten hier nur die Implementierung einzelner relationaler Operationen; die Abarbeitung komplexer algebraischer Ausdrücke
wird in einem separaten Lehrmodul behandelt Lehrmodul 8.
Ferner betrachten wir nur die wichtigsten Operationen der relationalen Algebra, wir konzentrieren uns auf Selektionen und Verbunde.
Dieses Lehrmodul erhebt nicht den Anspruch, die enorme Vielfalt an Optimierungsmöglichkeiten und Indexstrukturen auch nur
annähernd zu repräsentieren. Ziel ist es vielmehr, anhand der simplen
Optimierungstechniken zu zeigen, welche Größenordnung des Rechenaufwands für die relationalen Operationen erreichbar ist.
7.2
Triviale Implementierungen
Die mathematischen Definitionen der relationalen Operationen können
unmittelbar in die folgenden “trivialen” Implementierungen umgesetzt
werden. Wir bestimmen noch jeweils den Aufwand unter der Annahme, daß die betroffenen Relationen n bzw. m Tupel enthalten.
Selektion: Man durchläuft alle Tupel einer Relation, wertet jedesmal
das Selektionsprädikat aus und gibt ggf. das Tupel aus. Der
Aufwand hat die Größenordnung O(n). Wenn A Identifikationsschlüssel ist, muß bei einer Selektionsbedingung der Form σA=x
im Durchschnitt die halbe Relation durchlaufen werden, bis das
gesuchte Tupel gefunden ist, sofern alle vorhandenen Schlüsselwerte gleichhäufig gesucht werden. Bei großen Relationen ist
162
Implementierung relationaler Operationen
dies sehr ineffizient.
Projektion: Man durchläuft alle Tupel einer Relation und gibt die
gewünschten Attribute aus. Der Aufwand hierfür ist exakt n,
die Relation muß komplett durchlaufen werden.
Wenn zusätzlich eine Duplikateliminierung verlangt ist, muß
die Ergebnismenge sortiert werden (zusätzlicher, insg. dominierender Aufwand in der Größenordnung O(n*log(n))). Wenn
die Projektionsattribute einen Identifizierungsschlüssel enthalten, können natürlich keine Duplikate auftreten, und eine Duplikateliminierung ist überflüssig.
Mengenoperationen: Die Algorithmen für die Mengenoperationen sind
ebenfalls trivial. Sofern die Mengen schon geeignet sortiert sind,
ist der Aufwand linear, ansonsten kommt der Aufwand für die
Sortierung hinzu.
Kreuzprodukt: Man durchläuft geschachtelt beide Relationen und gibt
jeweils die Konkatenation der beiden aktuellen Tupel aus. Der
Aufwand hat die Größenordnung O(n*m), wenn n bzw. m die
Zahl der Tupel in den beiden Relationen ist.
Verbunde: Man kann den Verbund auf ein Kreuzprodukt, gefolgt von
einer Selektion und einer Projektion zurückführen (s. Abschnitt
4.3.6.2). Den größten Aufwand darin wird i.a. das Kreuzprodukt
verursachen.
Diese trivialen Implementierungen sind, wie die vorstehenden Größenordnungsangaben für den Aufwand zeigen, oft sehr ineffizient. Dies gilt
vor allem für die Verbundbildung. I.f. besprechen wir daher diverse
Optimierungsmaßnahmen für die einzelnen Operationen.
Optimierungsziele. Vorrangiges Optimierungsziel bei der Implementierung der elementaren Operationen ist eine möglichst geringe
Zahl von Plattenzugriffen. Die CPU-Belastung spielt nur eine sekundäre Rolle.
Implementierung relationaler Operationen
7.3
163
Exkurs: Indexstrukturen
Indexe spielen für effiziente Implementierungen der Selektion und des
Verbunds eine große Rolle. Die Optimierungsmöglichkeiten hängen dabei stark von den Strukturen innerhalb der Indexe ab; wir geben daher
vorab einen Überblick über die wichtigsten Indexstrukturen und deren
Eigenschaften.
7.3.1
Primärindexe
Primärindexe sind Datenstrukturen, die in die “Nutzdaten” eingebettet sind und die Primärschlüssel realisieren. Bis auf wenige Ausnahmen kann ein Datenbestand nur einen Primärindex haben.
B*-Bäume. B- bzw. B*-Bäume sind bekanntlicherweise Baumstrukturen, die auf die Besonderheiten einer blockorientierten Speicherung
adaptiert sind. Ihre wesentlichen Eigenschaften sind:
– Die Struktur der Indexblöcke hat einen sehr hohen Verzweigungsgrad (typischerweise >10), d.h. die Zahl der Indexblöcke ist signifikant kleiner als die Zahl der Primärdatenblöcke. Die Baumstruktur
hat meist nur 3 - 4 Ebenen.
– Bei der Suche nach einem Satz mit gegebenem Primärschlüsselwert
müssen zunächst die Indexblöcke durchlaufen werden. Wegen der
geringen Anzahl können aber meist die oberen Ebenen der Struktur
im Hauptspeicher gepuffert werden, d.h. hierdurch werden nur sehr
wenige oder keine Blockübertragungen verursacht.
– B*-Bäume ermöglichen effiziente Implementierungen von Intervallabfragen und von sequentiellen Durchläufen in steigender oder fallender Reihenfolge der Primärschlüsselwerte.
– Verarbeitet man eine Menge von Sätzen in steigender oder fallender
Reihenfolge ihrer Primärschlüsselwerte, so wird jeder Index- oder
Primärdatenblock nur einmal von der Platte gelesen.
164
Implementierung relationaler Operationen
Hash-Verfahren. Die Grundidee des Hash-Verfahrens, die zu speichernden Einheiten in einem Array zu verwalten, läßt sich direkt
auf die Verhältnisse bei eine Speicherung auf Platte adaptieren: Als
Array-Elemente wählt man Blöcke (bzw. Seiten), die ja ebenfalls direkt
adressierbar sind. In der Regel passen mehrere Sätze in einen Block;
man benötigt also noch interne Verwaltungsstrukturen innerhalb eines
Blocks.
Die grundlegenden Hash-Verfahren sehen bei einem Tabellenüberlauf ein komplettes Rehashing vor; im Hauptspeicher und bei kleinen
Datenbeständen mag das gehen, bei großen Datenbeständen auf Platte
ist dieses Vorgehen völlig unrealistisch. Beim offenen Hashing können
sehr lange Überlaufketten entstehen, was ebenfalls unattraktiv ist.
Eine praktikable Lösung dieses Problems besteht darin, in zwei
Schritten über eine Blockadreßtabelle auf Blöcke zuzugreifen:
Schlüsselwert
k
Hashfunktion
hash(k)
Blockadreßtabelle
Seiten/Blöcke
Abbildung 7.1: Erweiterbares Hashing
1. Schritt: Berechnung einer Position in der Blockadreßtabelle
2. Schritt: Zugriff auf den Datenblock und Durchsuchen desselben
Die Blockadreßtabelle sollte ca. 100 bis 1000 Mal kleiner als die
Datenbank gewählt werden und möglichst im Hauptspeicher gehalten werden. Verschiedene Einträge in der Blockadreßtabelle können
auf den gleichen Datenblock verweisen, d.h. in einem Block befinden
sich Sätze mit unterschiedlichem Hash-Wert. Schlecht gefüllt Datenblöcke können so vermieden werden. Die Blockadreßtabelle kann mit
vertretbarem Aufwand reorganisiert werden, ohne alle Datenblöcke zu
kopieren; daher nennt man dieses Verfahren auch erweiterbares Ha-
Implementierung relationaler Operationen
165
shing. Auf die möglichen Varianten von Reorganisationen und die
Behandlung von Blocküberläufe gehen wir hier nicht weiter ein.
Der prinzipielle Vorteil von Hash-Verfahren gegenüber Suchbäumen, daß keine Indexknoten durchlaufen werden müssen, bleibt erhalten: Im Idealfall wird über den Hashwert eines vorgegebenen
Primärschlüsselwerts sofort der Block gefunden, der den zugehörigen Satz enthält. Je nach der Überlaufbehandlung und der Änderungshäufigkeit im Datenbestand geht dieser Vorteil aber teilweise wieder verloren; auf Details gehen wir hier nicht ein.
Hash-Verfahren unterstützen keine Intervallabfragen.
7.3.2
Sekundärindexe
Sekundärindexe existieren separat vom Primärdatenbestand und unterstützen insb. auch die Suche nach nicht-identifizierenden Attributen
und Attributkombinationen.
Ein Sekundärindex unterstützt die Suche für eine Attributmenge A
(meist ist A einelementig); A wird auch als zugehöriger Suchschlüssel
bezeichnet. Konzeptuell ist der Sekundärindex eine Datenstruktur, die
für jede Wertekombination der Attribute aus A eine Trefferliste liefert.
Die Trefferliste enthält in irgendeiner Form Referenzen auf die Sätze,
bei denen die Wertekombination der Attribute auftritt. Beispielsweise
könnte es zu der Relation lieferungen einen Sekundärindex für das
Attribut Kundennummer geben; der Sekundärindex würde dann die Suche nach den Lieferungen an einen Kunden unterstützen.
Sekundärindexe stellen die Originaldaten in gewisser Weise umgekehrt (invertiert) dar; ein normales Tupel t enthält die Information,
daß ein Attribut A den Wert x hat, ein Index zum Attribut A enthält die
Information, daß der Wert x u.a. im Tupel t auftritt. Datenbestände
mit Index werden daher auch invertiert genannt.
Eine naheliegende Wahl für die Referenzen in den Trefferlisten sind
Primärschlüsselwerte. Die Trefferliste ist dann zu durchlaufen, und für
jeden Eintrag kann über den Primärindex auf den entsprechenden Satz
zugegriffen werden.
166
Implementierung relationaler Operationen
Aktualisierung von Sekundärindexen. Wie schon erwähnt enthalten Sekundärindexe im Prinzip redundante Daten; werden die
Primärdaten geändert, müssen die Sekundärindexe entsprechend angepaßt werden. Wird z.B. beim Tupel t der Wert des Attributs A von
x1 nach x2 geändert, muß im Sekundärindex für den Suchschlüssel A
im Eintrag für x1 die Referenz auf t gelöscht und im Eintrag für x2
die Referenz auf t eingefügt werden. Wenn die beiden Einträge nicht
zufällig in der gleichen Seite liegen, müssen also wenigstens 2 Seiten
geschrieben25 und, falls sie nicht schon gepuffert waren, vorher gelesen
werden.
Änderungsoperationen werden also durch Sekundärindexe deutlich
teurer. Bei einer hinreichend hohen Änderungshäufigkeit können sich
(zu viele) Sekundärindexe daher insgesamt negativ auf die Systemleistung auswirken.
7.4
Optimierungen der Selektion
Bei der Selektion können Indexe unter bestimmten Umständen vorteilhaft ausgenutzt werden. Wir müssen hierzu verschiedene Formen
von Selektionsbedingungen unterscheiden:
Selektionsbedingung der Form σA=x . Wenn das Attribut A der
Primärschlüssel ist, kann sehr effizient mit konstantem Aufwand (also
O(1)) auf den einen Treffer zugegriffen werden.
Sofern ein Sekundärindex für das Attribut A vorliegt, hängt es von
bestimmten Umständen ab, ob es sich lohnt, den Index auszunutzen.
Der Einsatz lohnt nicht bei einer geringen Selektivität des Attributs.
Um dies präziser zu fassen, benötigen wir einige Größen; sei
sr
der durchschnittliche Speicherplatzbedarf eines Tupels
(incl. Hilfsdaten) der Relation r
25
Das Schreiben kann eine Zeitlang aufgeschoben werden, da die Indexdaten
aus den Primärdaten rekonstruiert werden können. Hier bestehen komplexe Zusammenhänge mit der Transaktionsverarbeitung, auf die wir hier nicht eingehen
können.
Implementierung relationaler Operationen
167
b
die Größe eines Blocks
bf
= ⌊b / sr ⌋ der Blockungsfaktor, also die Zahl der Sätze,
die in einen Block passen
Beispiel: mit b=4096 Bytes und sr =200 ist bf=20.
|r|
die Zahl der Tupel in der Relation r
V(A,r)
die Zahl der verschiedenen Werte, die Attribut A in Relation r annimmt
Wenn man vereinfachend annimmt, daß jeder Wert des Attributs A
gleichhäufig auftritt, dann liefert eine Selektion der Form σA=x ungefähr | r | / V(A,r) Tupel zurück, oder anders gesagt den V(A,r)-ten
Teil der Relation r. Diesen “Verkleinerungsfaktor” bezeichnet man
auch als die Selektivität des Attributs A. Wenn nun
V(A,r) ≤ bf
ist, die Selektivität also kleinergleich dem Blockungsfaktor ist, ist unter
der Annahme, daß die Treffertupel gleichmäßig über die Blöcke verstreut liegen, in jedem Block wenigstens ein Treffertupel vorhanden,
d.h. praktisch alle Blöcke müssen übertragen werden. Durch den Einsatz des Sekundärindex können dann also keine Blockübertragungen
eingespart werden. Im Gegenteil führt die Benutzung des Sekundärindex zu zusätzlichen Blockübertragungen für Blöcke des Sekundärindex.
Hieraus folgt - insb. wenn man zusätzlich den Änderungsaufwand für
den Sekundärindex berücksichtigt -, daß Sekundärindexe für Attribute
mit geringer Selektivität nicht sinnvoll sind.
Selektionsbedingung der Form σA>x ∧ A<y (Intervallabfrage
zum Attribut A). Sofern die internen Zugriffsmethoden auch Intervallabfragen unterstützen (z.B. bei B-Bäumen), können auch diese
effizient bearbeitet werden, wobei hier der Aufwand linear von der
Größe der Treffermenge abhängt. Entscheidend ist hier die kompakte
(clusternde) Speicherung von Sätzen bzw. Tupeln mit aufeinanderfolgenden Schlüsselwerten innerhalb eines Blocks. Hierdurch braucht für
jeweils bf Sätze nur ein Block übertragen zu werden (mit Ausnahme
der “Randblöcke”).
168
Implementierung relationaler Operationen
Selektionsbedingung der Form σA>x . Bei Selektionskriterien, in
denen Vergleichsoperatoren wie > verwendet werden, wird unter bestimmten Gleichverteilungsannahmen im Schnitt die halbe Relation
zurückgeliefert, d.h. im Sinne der vorstehenden Bemerkungen liegt eine
extrem schlechte Selektivität vor. Eine wesentliche Aufwandsreduktion gegenüber dem sequentiellen Durchsuchen der Relation ist also bei
>-Vergleichen durch Indexe nicht möglich.
Selektionsbedingung mit mehreren Attributen und einem
Index. Wenn das Selektionskriterium die Form σA=x ∧X hat und
für A ein Primär- oder Sekundärindex vorhanden ist, kann die undVerknüpfung in der Selektion konzeptionell auf die Schachtelung
σX (σA=x (...)) zurückgeführt werden, d.h. unter Ausnutzung des Index werden nur relativ wenige Tupel von der Platte gelesen; für diese
Tupel werden dann die weiteren Bedingungen direkt überprüft.
Vorteilhaft ist es in diesem Zusammenhang, wenn Tupel, die im
gleichen Block liegen, hintereinander verarbeitet werden und so letztlich jeder Block nur einmal übertragen werden muß. Werden die Tupel
in einem B*-Baum gespeichert, so kann man dies erreichen, indem man
die Tupel nach ihren Primärschlüsselwerten sortiert verarbeitet.
Selektionsbedingung mit mehreren Attributen und mehreren
Indexen. Sind mehrere elementare Bedingungen vorhanden, bei denen jeweils ein Sekundärindex für das auftretende Attribut vorhanden
ist, so können ggf. zunächst, bevor auf die eigentlichen Daten zugegriffen wird, Trefferlisten für die einzelnen Elementarbedingungen erstellt
und die logischen Verknüpfungen zwischen den Elementarbedingungen
durch entsprechende Mengenoperationen realisiert werden. Speziell
bei und-Verknüpfungen kann es sein, daß die Treffermenge auf diese
Weise deutlich verkleinert wird und weniger Blöcke übertragen werden
müssen
Implementierung relationaler Operationen
7.5
169
Optimierungen der Projektion
Bei der Projektion läßt sich der Aufwand, die komplette Eingaberelation zu verarbeiten und ggf. Duplikate zu eliminieren, im Prinzip nicht
reduzieren.
Der Aufwand für das Lesen der Eingaberelation kann allerdings
komplett vermieden werden, wenn es sich bei der Eingaberelation um
ein Zwischenergebnis einer vorherigen Operation handelt, z.B. einer
Selektion oder einem Verbund, indem man die Projektion in die vorgeschaltete Operation integriert und gleich bei der Generierung des Zwischenergebnisses berücksichtigt. Konzeptionell handelt es sich dann
um neue, kombinierte Operationen. Die Annahme, daß eine Projektion nach einer anderen Operation erfolgt, ist sehr häufig schon bei
der Formulierung einer Abfrage erfüllt und kann oft vom Optimierer
durch Umstellung der Anfrage erreicht werden.
7.6
Optimierungen der Verbundberechnung
Verbunde sind häufig, da infolge der Normalisierung vielfach Daten,
die für eine Anwendung benötigt werden, auf mehrere Relationen verteilt werden. Die Ineffizienz des Grundalgorithmus für den Verbund
ist daher äußerst nachteilig, und es sind diverse Varianten und Optimierungsmaßnahmen entwickelt worden.
Einfaches Iterieren. Die oben skizzierte Implementierung wird
auch als Einfaches Iterieren oder nested loop join bezeichnet und
ist in Varianten für den natürlichen Verbund, den Θ-Verbund, die
äußeren Verbunde und das Kreuzprodukt anwendbar. In vereinfachter
Form handelt es sich um folgende geschachtelte Schleife:
for each tuple t1 in r1
for each tuple t2 in r2
pruefe, ob <t1|t2> in Ergebnismenge kommt
170
Implementierung relationaler Operationen
Wenn z.B. | r1 | = 10.000 und | r2 | = 200 ist, dann wird die innere
Anweisung 2.000.000 Mal durchlaufen.
Eine wichtige Frage ist, ob die Relation r2 immer wieder neu von
der Platte gelesen werden muß und somit Blockübertragungen notwendig werden. Bei den heute üblichen Hauptspeichergrößen kann man
erhebliche Datenmengen im Hauptspeicher puffern. Wenn wir wenigstens eine Relation (also die kleinere) komplett im Hauptspeicher puffern können, tun wir das und brauchen somit beide Relationen nur
einmal zu lesen.
Relationen können aber trotzdem zu groß sein, um komplett gepuffert werden zu können. Die folgenden Überlegungen gehen zur Vereinfachung davon aus, daß immer nur ein Block gepuffert werden kann.
Sofern die Tupel der Relation r2 in zufälliger Reihenfolge, also
gestreut im entsprechenden DB-Segment, verarbeitet werden, muß
i.a. für jedes Tupel ein Block übertragen werden. Dies ist extrem
ungünstig, in unserem obigen Beispiel kommen wir auf 2.000.000
Blockübertragungen.
Eine offensichtliche Verbesserung liegt darin, die Relation r2 geblockt zu speichern - falls sie es nicht sowieso ist, lohnt es sich, eine
temporäre Kopie anzulegen - und sie bei jedem Durchlauf in physischer Reihenfolge zu lesen. Die Zahl der Blockübertragungen reduziert sich dann um den Blockungsfaktor. In unserem Beispiel würde
r2 bei einem Blockungsfaktor 20 nur 10 Blöcke belegen, bei 10.000
Schleifendurchläufen wären 100.000 Blockübertragungen nötig.
Blockorientiertes Iterieren. Eine weitere deutliche Verbesserungsmöglichkeit ergibt sich, wenn auch r1 einen hohen Blockungsfaktor hat. Anstatt nun für jedes Tupel in r1 jeweils die ganze Relation
r2 zu lesen, lesen wir immer einen Block in r1 und r2 und verarbeiten
alle darin enthaltenen Paare von Tupeln:
for each block B1 in r1
for each block B2 in r2
for each tuple t1 in B1
Implementierung relationaler Operationen
171
for each tuple t2 in B2
pruefe, ob <t1|t2> in Ergebnismenge kommt
Die Zahl der Blockübertragungen reduziert sich dann noch einmal
um den Blockungsfaktor. Wenn in unserem Beispiel auch r1 einen
Blockungsfaktor 20 hat, also 500 Blöcke belegt, sind nur noch 5.000
Blockübertragungen erforderlich.
Wir haben bisher unterstellt, daß pro Relation genau ein Block gepuffert werden kann, was ziemlich unrealistisch ist. Sind insgesamt n
Blöcke für die Pufferung verfügbar, so bilden wir in beiden Relationen jeweils Abschnitte von n/2 Blöcken und behandeln jeweils einen
Abschnitt wie einen Block im obigen Algorithmus.
Verbundberechnung mit Index. Beim einfachen und blockorientierten Iterieren wird die zweite Relation im Prinzip immer wieder
sequentiell nach Verbundpartnern für das aktuell betrachtete Tupel
der ersten Relation durchsucht. Die lineare Suche ist das ineffizienteste Suchverfahren. Sofern für die zweite Relation ein Primär- oder
Sekundärindex für das Verbundattribut (bzw. die Verbundattribute)
vorliegt, ist mit dessen Hilfe eine wesentlich effizientere Suche möglich
(s. Bild 7.2). U.U. lohnt es sich, einen Index temporär aufzubauen.
r1
A
Index
für
r2
r2
A
Abbildung 7.2: Verbundberechnung mit Index
Diese Verbundberechnung mit Index ist im sehr häufigen Fall anwendbar, daß der Verbund über einen Fremdschlüssel gebildet wird; der
Fremdschlüssel ist dann in der anderen Relation Primärschlüssel. Ein
172
Implementierung relationaler Operationen
Beispiel hierfür ist der schon früher betrachtete Verbund lieferungen
1 kunden.
Wie schon früher erwähnt lohnt der Einsatz von Indexen nicht,
wenn das unterstützte Attribut eine schlechte Selektivität hat. Bei
großen, nicht pufferbaren Relationen und geringer Selektivität des Verbundattributs entstehen allerdings immens große Resultate, die mit
hoher Wahrscheinlichkeit die verfügbaren Ressourcen überlasten, so
daß derartige Abfragen ohnehin unrealistisch sind.
Misch-Verbund (Merge Join). Sofern bei einem Verbund r1s
das Attribut A Verbundattribut ist und sowohl r als auch s nach A sortiert gespeichert sind, kann der Verbund unter gewissen Bedingungen
wie beim Misch-Algorithmus in einem einzigen parallelen Durchlauf
durch die beiden Relationen konstruiert werden.
r1
A
r2
A
x
x
x
x
x
Abbildung 7.3: Misch-Verbund
Hierzu wird in einer Schleife der jeweils nächstgrößere, in beiden
Relationen auftretende Wert des Verbundattributs bestimmt26 . In beiden Relationen bilden die Tupel, bei denen dieser Wert auftritt, jeweils
ein “Abschnitt”. Alle Tupel in den beiden Abschnitten müssen paarweise kombiniert und ausgegeben bzw. weiterverarbeitet werden.
Sofern das Verbundattribut eine hohe Selektivität hat, sind diese
Abschnitte kurz und können wahrscheinlich komplett gepuffert werden. Andernfalls werden diese Abschnitte entsprechend lang - im Extremfall kann die ganze Relation einen einzigen Abschnitt bilden -, d.h.
26
Werte, die nur in einer der Relationen auftreten, müssen nur bei äußeren Verbunden betrachtet werden.
Implementierung relationaler Operationen
173
wir stehen hier wieder vor dem Problem, einen Abschnitt puffern zu
müssen. Allerdings sind, wie schon oben erwähnt, Verbundattribute
mit geringer Selektivität ohnehin eher unrealistisch.
3-Wege-Verbund. Ein Verbund zwischen drei Relationen r1 1 r2
1 r3 kann im Prinzip auf die Hintereinanderschaltung zweier binärer
Verbunde (entweder (r11r2) 1 r3 oder r1 1 (r21r3) ) zurückgeführt
werden. Anzustreben ist in diesem Fall ein möglichst kleines Zwischenergebnis.
Alternativ kann der 3-stellige Verbund auch direkt, also ohne die
ggf. aufwendige Erzeugung eines Zwischenergebnisses, erzeugt werden.
Als Grundidee verwenden wir die Verbundberechnung mit Index. Wir
durchlaufen die mittlere Relation tupelweise (s. Bild 7.4) und suchen
jeweils “links” (in r1) und “rechts” (in r3) mit Unterstützung je eines
Index nach Verbundpartnern.
r1
A
r2
A B
r3
B
Abbildung 7.4: 3-Wege-Verbund
Dieses Verfahren ist besonders vorteilhaft anwendbar, wenn r2 eine
Verbindungstabelle zwischen r1 und r3 ist.
Glossar
3-Wege-Verbund: Verfahren zur Berechnung von zwei Verbunden mit 3
Eingaberelationen
einfaches Iterieren: Verfahren zur Verbundberechnung, bei dem die beiden Eingaberelationen in zwei geschachtelten Schleifen durchlaufen
werden
174
Implementierung relationaler Operationen
erweiterbares Hashing: Variante des Hashings, bei dem die Hashtabelle
über eine Umsetztabelle indirekt adressiert wird und die einzelnen Felder der Hashtabelle gestreut auf der Platte gespeichert werden können
invertierter Datenbestand: Datenbestand, zu dem ein oder mehrere Sekundärindexe vorhanden sind
Misch-Verbund (merge join): Verfahren zur Verbundberechnung, bei dem
die beiden Eingaberelationen zunächst nach den Verbundattributen
sortiert werden und dann für jeden auftretende Wertekombination der
Verbundattribute eine “lokaler” Verbund berechnet wird
Sekundärindex: Verzeichnis, das zu einzelnen Werten eine Liste von Referenzen auf die Speichereinheiten enthält, in denen dieser Attributwert
auftritt
Selektivität (eines Attributs einer Relation): Zahl der verschiedenen Werte des Attributs in seiner Relation; der entsprechende Bruchteil der
Relation wird im Durchschnitt geliefert, wenn nach einen auftretenden Wert des Attributs selektiert wird
Lehrmodul 8:
Abfrageverarbeitung und
Optimierung
Zusammenfassung dieses Lehrmoduls
Ein wesentlicher Vorteil relationaler Datenbanken liegt darin,
daß die Abarbeitung von Abfragen automatisch optimiert werden
kann. Zunächst wird im Rahmen der algebraischen Optimierung die
Abfrage anhand von Heuristiken in eine äquivalente, aber effizienter
ausführbare Form umgewandelt. In der anschließenden internen
Optimierung wird zwischen ggf. verfügbaren Implementierungen der
Elementaroperationen entschieden und damit zusammenhängend über
die Ausnutzung von Indexen. Die alternativen Ausführungspläne
werden hierzu anhand ihrer geschätzten Ausführungskosten bewertet.
Vorausgesetzte Lehrmodule:
obligatorisch:
– Das relationale Datenbankmodell
– Implementierung relationaler Operationen
empfohlen:
– Architektur von DBMS
Stoffumfang in Vorlesungsdoppelstunden:
c
2003
Udo Kelter
1.2
Stand: 12.10.2003
176
Abfrageverarbeitung und Optimierung
8.1
Motivation
Praktisch benutzte Abfragesprachen und selbst die relationale Algebra
sind Hochsprachen im gleichen Sinne wie “höhere” Programmiersprachen: sie entlasten den Nutzer von vielen systemnahen, lästigen Details der Datenverwaltung und erlauben es, Probleme in der Denkwelt
abstrakterer Konzepte zu lösen, im Falle von Abfragesprachen in der
Denkwelt des Datenbankmodells.
Die Operationen des Datenbankmodells müssen auf systemnahe
Funktionen zurückgeführt werden, insb. müssen die Datenobjekte,
mit denen die Operationen des Datenbankmodells arbeiten (einzelne
Tupel bzw. Tupelmengen) letztlich auf Strukturen der Speichermedien (i.d.R. Magnetplatten) abgebildet werden. Diese Abbildung stellt
man sich softwaretechnisch am besten als eine Schichtenarchitektur
vor. Die oberste Schicht exportiert Operationen mit Tupelmengen
und basiert auf der darunterliegenden Schicht, die Operationen mit
einzelnen Tupeln exportiert27 .
Wir beziehen uns hier begrifflich auf relationale Systeme, bei objektorientierten Systemen gelten diese Betrachtungen analog für Objekte. Navigierende Datenmodelle haben i.d.R. keine mengenwertigen
Operationen, so daß die oberste Schicht entfällt.
Wir konzentrieren uns in diesem Lehrmodul auf die Frage, wie Operationen mit Tupelmengen, insb. also Abfragen, auf Operationen mit
einzelnen Tupeln zurückgeführt werden können.
8.1.1
Grobablauf einer Abfrageverarbeitung
Den Ablauf der Bearbeitung einer Abfrage kann man wie folgt grob
gliedern:
1. Umformung der textuellen Darstellung der Abfrage in eine interne
Darstellung (analog zum Parser in einem Compiler) und Korrektheitsüberprüfung
2. Erstellung und Vergleich möglicher Ausführungspläne
27
Lehrmodul 3 beschreibt die Schichten detaillierter.
Abfrageverarbeitung und Optimierung
177
3. Ausführung des “optimalen” Plans
Die Korrektheitsüberprüfung im ersten Schritt betrifft
– die Syntax und
– die verwendeten Ressourcen; mit Hilfe des Systemkatalogs wird festgestellt, ob die angegebenen Relationen und Attribute überhaupt
existieren und ob entsprechende Zugriffsrechte gegeben sind.
Weiter werden in diesem Schritt virtuelle Relationen durch ihre definierende Abfrage ersetzt (view resolution). Im Endeffekt wird die
Abfrage in eine interne Baumdarstellung umgeformt, die einen Ausdruck in der relationalen Algebra oder einer Erweiterung derselben
repräsentiert.
Der zweite Schritt, die Optimierung, ist dadurch motiviert, daß es
meist zu einer Abfrage mehrere Ausführungsvarianten gibt, die alle
das gleiche Resultat liefern, aber verschiedene Kosten verursachen.
8.1.2
Optimierungsansätze
Die Frage, wo und wie die Abarbeitung einer Abfrage optimiert werden kann, kann offensichtlich nicht ohne Bezug auf die Abfragesprache
diskutiert werden. Wir beschränken uns hier auf die relationale Algebra (s. Lehrmodul 4), da sie einerseits die wichtigsten mengenwertigen Abfrageoperationen umfaßt, andererseits syntaktisch sehr einfach
strukturiert ist. Bei komplexeren Sprachen steigt vor allem die Zahl
der Abfrageoperationen an, die prinzipielle Vorgehensweise bleibt aber
gleich.
Die Abarbeitung einer Abfrage können wir für unsere aktuelle Fragestellung in zwei Themenkomplexe gliedern:
– die Implementierung der Operationen der relationalen Algebra
– die Verarbeitung geschachtelter Ausdrücke.
Die beiden Themenkomplexe sind nicht ganz unabhängig voneinander,
aber hilfreich für die Gliederung möglicher Optimierungsmaßnahmen.
178
Abfrageverarbeitung und Optimierung
Optimierung der Elementaroperationen. Wie schon in Abschnitt 4.3.9 erwähnt, haben Ausdrücke in der relationalen Algebra
eine intuitive operationale Semantik, nämlich die Auswertung von innen nach außen. Dies unterstellt, daß für jede Operation der relationalen Algebra genau eine Implementierung vorhanden ist und daß
bei der Abarbeitung des Ausdrucks diese Implementierung mit den
passenden Zwischenresultaten ausgeführt wird. Diese Annahme trifft
aber in doppelter Hinsicht nicht zu:
– Für eine Operation kann es mehrere Implementierungen geben, die
verschieden effizient sind und von denen eine auszuwählen ist, ggf.
abhängig von den benutzten Datenstrukturen.
– Es kann Implementierungen kompletter Teilausdrücke geben. Als
Beispiel betrachten wir eine Selektion gefolgt von einer Projektion
(πA (σB (...))): bei der intuitiven Abarbeitung würde man bei der
Selektion ganze Tupel in eine temporäre Relation schreiben und
diese dann projizieren. Stattdessen erzeugt man besser gleich die
projizierten Tupel und spart so den Platz und Aufwand für die
temporäre Relation komplett ein.
Alternative Implementierungen einzelner Operationen und Implementierungen kompletter Teilausdrücke zählen wir hier zu den Optimierungsmaßnahmen im Bereich der Implementierung von Operationen.
Optimierung der Abarbeitung von Ausdrücken. Die Optimierung der Abarbeitung von geschachtelten Ausdrücken sei durch
folgendes Beispiel motiviert: wir unterstellen wieder die Relationen
kunden und lieferungen und suchen die Namen der Kunden, die am
24.12.2000 eine Lieferung bekommen haben. Diese Frage können wir
auf zwei verschiedene Arten beantworten:
πKundenname (σDatum=24.12.2000 ( lieferungen 1 kunden ))
und
πKundenname (σDatum=24.12.2000 ( lieferungen ) 1 kunden )
Abfrageverarbeitung und Optimierung
179
Beide Ausdrücke sind äquivalent, berechnen also das gleiche Ergebnis, der zweite ist aber effizienter, weil der Verbund mit einer kleineren
Menge gebildet wird. Hierbei unterstellen wir wieder die intuitive operationale Semantik von Ausdrücken; wenn wir von einem effizienteren Ausdruck reden, sehen wir den Ausdruck als einen (vereinfachten,
abstrakten) Ausführungsplan an.
Daß es zu einer Aufgabe mehrere verschiedene, aber äquivalente
Lösungen gibt, trifft generell auf alle Hochsprachen zu und auf SQL
sogar in deutlich stärkerem Ausmaß als auf die relationale Algebra.
Ein Gegenstand der Optimierung ist somit die Auswahl einer
möglichst kostengünstigen Lösung. Hierbei wird in zwei Schritten vorgegangen:
1. Bei der algebraischen Optimierung werden zu dem vom Nutzer
vorgegebenen Ausdruck ein oder mehrere äquivalente Ausdrücke gebildet, die aufgrund von Heuristiken effizienter ausführbar erscheinen. Ein Beispiel hierfür wurde oben gegeben.
Die algebraische Optimierung ist im Gegensatz zu den weiteren
Maßnahmen unabhängig vom aktuellen Inhalt der Datenbank.
2. Bei der anschließenden internen Optimierung werden für jeden
Ausdruck mehrere alternative Ausführungspläne gebildet. In einem Ausführungsplan wird über die reine Operationsschachtelung hinaus festgelegt,
– welche der alternativ verfügbaren Implementierungen einer Operation gewählt wird; da für manche Implementierungen ein Index
vorhanden sein muß, wird auch entschieden, ob Indexe ausgenutzt werden;
– welche Zwischenergebnisse auf Platte oder im Hauptspeicher angelegt werden.
Für jeden Ausführungsplan werden die Ausführungskosten geschätzt. Bei dieser Schätzung spielen eine Rolle:
– Merkmale des aktuellen Datenbestands, insb. die Größe von
Relationen und die Verteilung von Attributwerten
180
Abfrageverarbeitung und Optimierung
– interne Speicherungsstrukturen, z.B. vorhandene Indexe oder
Sortierungen
Ferner werden gemeinsame Unterausdrücke berücksichtigt, die nur
einmal berechnet werden müssen.
Anzumerken ist noch, daß die Bezeichnung Optimierung insofern
mißverständlich (oder gar falsch) ist, als i.d.R. nicht etwa eine optimale, also minimal aufwendige Bearbeitung der Abfrage gesucht wird,
sondern nur eine möglichst gute bzw. bessere als die intuitiv naheliegende. Zum einen muß natürlich der Aufwand für die Optimierung
kleiner bleiben als der Gewinn durch die bessere Ausführungsvariante. Bei sehr kleinen Datenbanken lohnt sich deshalb die Optimierung
oft nicht. Sodann gibt es i.a. zu viele Ausführungsvarianten, um alle einzeln betrachten zu können, und man kann i.a. die Kosten einer
Variante nicht exakt prognostizieren, man muß also mit Heuristiken
arbeiten.
8.2
Optimierungskriterien
Bisher haben wir die Frage offengelassen, anhand welcher Kriterien wir
bestimmen, ob eine Abfrageverarbeitung gut oder weniger gut ist. Im
Endeffekt geht es um Performance-Maße wie Antwortzeit oder Durchsatz, die aus Benutzersicht erkennbar sind. Diese Größen können als
solche aber nicht direkt geschätzt werden, man muß also auf andere
Meßgrößen bzw. Optimierungskriterien zurückgreifen. Aufwand entsteht insb. in folgender Hinsicht:
– Plattenzugriffe zum Lesen der Ausgangsdaten und Schreiben und
Lesen von Zwischenergebnissen
– Plattenplatzbedarf für Zwischenergebnisse
– Hauptspeicherbedarf
– bei verteilten Systemen: Anzahl der Kommunikationen, Datenübertragungsvolumen
– Rechenaufwand (CPU-Belastung)
Abfrageverarbeitung und Optimierung
181
Ferner gibt es speziellere, ggf. sogar anwendungsspezifische Aufwandskriterien.
Das wichtigste Kriterium ist in der Regel die Zahl der Plattenzugriffe. Daher stellen viele Optimierungsverfahren vor allem auf die
Reduktion der Plattenzugriffe ab. Die CPU-Belastung ist aber auch
keineswegs unwichtig; bei den heute üblichen großen Hauptspeichern
können oft alle relevanten Daten gepuffert werden, so daß nach dem
unvermeidlichen initialen Lesen und ggf. Schreiben der Endergebnisse
keine weiteren Plattenzugriffe anfallen.
Es liegt daher nahe, mehrere dieser Meßgrößen mit geeigneten Faktoren zu gewichten und daraus ein Kostenmaß für Abfrageverarbeitungen zu bilden. In diesem Zusammenhang spricht man auch von
kostenbasierter Optimierung.
8.3
8.3.1
Algebraische Optimierung
Äquivalente algebraische Ausdrücke
Ziel der algebraischen Optimierung ist es, zu einem vorgegebenen Ausdruck einen äquivalenten Ausdruck zu finden, der effizienter ausführbar
ist.
Zwei relationale Ausdrücke A1 und A2 sind äquivalent, wenn bei
einem beliebigen Datenbankinhalt beide Ausdrücke das gleiche Ergebnis liefern. Für die algebraische Optimierung ist daher der Begriff
Äquivalenz von zentraler Bedeutung.
Im folgenden listen wir eine Reihe von Äquivalenzen auf, die mehr
oder minder unmittelbar durch Einsetzen der Definitionen beweisbar
sind und die auch als Gesetze bezeichnet werden.
r, s und t sind i.f. beliebige Relationen; bei den Mengenoperationen müssen die beteiligten Relationen den gleichen Typ haben. B, B1
und B2 sind Selektionsbedingungen, die syntaktisch zu den Typen der
Argumentrelationen passen, Q, Q1 und Q2 sind Verbundbedingungen.
Kommutativgesetze. Vereinigung, Schnitt, Verbund und Kreuzprodukt sind kommutativ:
182
Abfrageverarbeitung und Optimierung
r∪s=s∪r
r∩s=s∩r
r1s=s1r
r 1Q s = s 1Q r
r×s=s×r
Assoziativgesetze.
dukt sind assoziativ:
Vereinigung, Schnitt, Verbund und Kreuzpro-
r ∪ (s ∪ t) = (r ∪ s) ∪ t
r ∩ (s ∩ t) = (r ∩ s) ∩ t
r 1 (s 1 t) = (r 1 s) 1 t
r 1Q1 (s 1Q2 t) = (r 1Q1 s) 1Q2 t
r × (s × t) = (r × s) × t
Auflösung komplexer Selektionsbedingungen. Die Booleschen
Operatoren ∧ und ∨ zwischen Bedingungen B1 und B2 können wie
folgt in Schachtelungen von Selektionen oder Mengenoperationen umgeformt werden:
σB1∧B2 (r) = σB1 (σB2 (r))
σB1∧B2 (r) = σB2 (σB1 (r))
σB1∧B2 (r) = σB1 (r) ∩ σB2 (r)
σB1∨B2 (r) = σB1 (r) ∪ σB2 (r)
Distributivgesetze zwischen Selektion und Mengenoperatoren.
σB (r ∪ s) = σB (r) ∪ σB (s)
σB (r ∩ s) = σB (r) ∩ σB (s)
σB (r − s) = σB (r) − σB (s) = σB (r) − s
Gesetze für die Projektion.
Seien U, V ⊆ R. Dann gilt
πU (πV (r)) = πU ∩V (r).
Eine Projektion kann mit einer Selektion vertauscht werden, wenn die
Selektionsbedingung B nur Attribute aus V (die Menge der Attribute,
auf die projiziert wird) enthält:
Abfrageverarbeitung und Optimierung
183
σB (πV (r)) = πV (σB (r))
Eine Projektion kann mit dem Vereinigungsoperator vertauscht werden28 :
πY (r ∪ s) = πY (r) ∪ πY (s)
Verbund und Selektion. Seien r1 bzw. r2 Relationen des Typs R1
bzw. R2, B eine Selektionsbedingung, die nur Attribute aus R1 beinhaltet, Q eine Verbundbedingung. Dann gilt:
σB (r1 1 r2) = σB (r1) 1 r2
σB (r1 1Q r2) = σB (r1) 1Q r2
Als Erläuterung hierzu betrachten wir folgende Beispiele; sei R1 =
{ A, B, C, D }, R2 = { C, D, E, F }:
σA=B (r1 1 r2)
σA=E (r1 1 r2)
σA=a (r1 1A=F r2)
σA=F (r1 1B=E r2)
=
6
=
=
6
=
σA=B (r1) 1 r2
σA=E (r1) 1 r2
σA=a (r1) 1A=F r2
σA=F (r1) 1B=E r2
Wenn die Attribute, die in einer Selektionsbedingung sel auftreten,
in beiden Relationenschemata enthalten sind, dann gilt:
σsel (r1 1 r2) = σsel (r1) 1 σsel (r2)
Kreuzprodukt und Selektion. Seien r1 bzw. r2 Relationen des
Typs R1 bzw. R2, B eine Selektionsbedingung, die nur Attribute aus
R1 beinhaltet. Dann gilt:
σB (r1 × r2) = σB (r1) × r2
Ist B eine Verbundbedingung, so gilt:
σB (r1 × r2) = r1 1B r2
28
Für den Durchschnitt und die Differenz gilt dies nicht. Übungsaufgabe: Finden
Sie ein Gegenbeispiel.
184
Abfrageverarbeitung und Optimierung
Verbund und Projektion. Nach einem Verbund wird meist sofort oder später (z.B. nach einer Selektion) projiziert, d.h. manche
der zunächst aufwendig erzeugten Attribute werden später unbenutzt
gelöscht. Die Frage ist, ob man dies nicht vermeiden kann und ob man
vorher projizieren kann. Wie das nächste Beispiel (R1 und R2 seien
wie vorstehend definiert) zeigt, ist die Vertauschung aber i.a. nicht
zulässig:
πA (r1 1 r2) 6= (πA (r1)) 1 r2
Der Fehler liegt darin, daß {C, D} = R1 ∩ R2 die Verbundattribute
von r1 und r2 sind und daß diese Verbundattribute im rechten Teil
der Formel bei r1 wegprojiziert worden sind, der dortige Verbund also
zum Kreuzprodukt degeneriert; auf der rechten Seite werden also i.a.
mehr Tupel entstehen. Wenn bei der Projektion die Verbundattribute
erhalten bleiben, kann das Problem nicht auftreten. Anders gesagt
müssen dann, wenn man eine Projektion an einem Verbund vorbei
nach innen ziehen will, die Verbundattribute innen erhalten bleiben.
Nach dem Verbund müssen sie dann separat entfernt werden.
Diese Vorüberlegungen motivieren die folgende Äquivalenz. Seien
r1 bzw. r2 Relationen des Typs R1 bzw. R2, U ⊆ R1 ∪ R2, Q eine
Verbundbedingung, V die in Q auftretenden Verbundattribute. Seien
U1 = (U ∩ R1) ∪ V und U2 = (U ∩ R2) ∪ V. Dann ist
πU (r1 1Q r2) = πU (πU1 (r1) 1Q πU2 (r2))
Beim natürlichen Verbund ist analog V = R1 ∩ R2.
Man kann also vor der Verbundbildung alle Attribute entfernen,
die nicht für die Verbundbildung oder die außenstehende Projektion
benötigt werden.
Anzumerken ist hier, daß, sofern r1 und r2 nicht im Hauptspeicher
gepuffert werden können, der längere Ausdruck effizienter ausführbar
sein wird, obwohl er mehr Operationen enthält.
Kreuzprodukt und Projektion. Das Kreuzprodukt können wir
hier als Sonderfall des Verbunds mit leerer Verbundbedingung behandeln; die Menge der Verbundattribute ist somit leer und die allgemeine
Formel für den Verbund vereinfacht sich zu:
Abfrageverarbeitung und Optimierung
185
πU (r1 × r2) = πU (πR1∩U (r1) × πR2∩U (r2))
= πR1∩U (r1) × πR2∩U (r2)
8.3.2
Optimierungsheuristiken
Im vorigen Abschnitt ist eine größere Anzahl Äquivalenzen vorgestellt
worden. Im Rahmen der algebraischen Optimierung können diese jetzt
ausgenutzt werden, um zu einem vorgegebenen Ausdruck einen äquivalenten, aber effizienter ausführbaren zu finden.
Bei einem gegebenen Ausdruck werden normalerweise mehrere der
Äquivalenzen anwendbar sein. Nach einem Umformungsschritt wird
dies erneut der Fall sein, wir erhalten somit i.a. viele denkbare Sequenzen von Umformungsschritten. Selbst dann, wenn wir unsinnige
Sequenzen - z.B. solche, in denen direkt nach einer Umformung die inverse Umformung auftritt - aussortieren, bleibt die Zahl der Sequenzen
i.a. viel zu hoch, um alle parallel verfolgen zu können.
Die nachfolgenden, als Regeln formulierten Optimierungsheuristiken beschreiben solche Umformungsschritte, die mit sehr hoher Wahrscheinlichkeit und meist auch in intuitiv unmittelbar einsichtiger Weise
die Effizienz verbessern. Dabei wird zum einen die “Richtung”, in der
die Äquivalenzen ausgenutzt werden sollten, vorgegeben, ferner werden teilweise Bedingungen für einen Umformungsschritt angegeben.
Regel 1: Selektionen sollten so früh wie möglich ausgeführt werden.
Selektionen werden also möglichst weit nach innen in geschachtelte Ausdrücke verschoben. Hierdurch werden Zwischenergebnisse kleiner. Selbst wenn diese nicht gespeichert werden,
sinkt immer noch der Verarbeitungsaufwand.
Regel 2: Eine äußere Selektion, deren Bedingung eine Konjunktion
ist, sollte in eine Schachtelung von Selektionen aufgebrochen werden.
Der Sinn dieser Regel liegt darin, daß die Regel 1 dann öfter
anwendbar ist und möglichst viele elementare Selektionen unmittelbar bei den Basisrelationen angewandt werden.
186
Abfrageverarbeitung und Optimierung
Sofern mehrere Einzelselektionen in der Form σB1 (σB2 (X))
unmittelbar aufeinanderfolgen, sollte die Selektion mit der höheren Selektivität nach innen verschoben werden. Sofern X bereits
eine Basisrelation ist, sollten vorhandene Indexe ausgenutzt werden (vgl. Abschnitt 7.4). In beiden Fällen beziehen wir uns auf
Merkmale der aktuellen Datenbank, derartige Entscheidungen
gehören also nicht mehr strikt zur algebraischen Optimierung,
sondern schon zur internen Optimierung.
Regel 3: Selektionen und Kreuzprodukte sollten zu Verbunden zusammengefaßt werden, d.h. Tupel, die die Verbundbedingung
nicht erfüllen, werden gar nicht erst erzeugt.
Regel 4: Bei einem Verbund von 3 und mehr Relationen sollten Verbunde zuerst berechnet werden, die voraussichtlich kleine Ergebnisse erzeugen. Kleine Ergebnisse sind wahrscheinlich, wenn
– die Verbundattribute Identifizierungsschlüssel in einer der beteiligten Relationen sind
– mehrere Verbundattribute statt nur einem vorhanden sind
– die beteiligten Relationen klein sind29
Regel 5: Sofern sinnvoll (z.B. wenn Verbundergebnisse zwischengespeichert werden müssen) sollten zusätzliche Projektionen eingefügt werden.
Die neuen Projektionen sollten natürlich mit einer ggf. vorhandenen vorhergehenden (also inneren) Operation zusammengefaßt werden; vgl. generelle Bemerkungen zu Projektionen in
Abschnitt 7.6.
Regel 6: Sofern an irgendeiner Stelle im Syntaxbaum Zwischenergebnisse gespeichert werden müssen, sollten alle äußeren Projektionen, soweit möglich, bis an diese Stelle verschoben werden.
29
Auch dieses Argument basiert auf Merkmalen der aktuellen Datenbank, gehört
also nicht mehr strikt zur algebraischen, sondern zur internen Optimierung.
Abfrageverarbeitung und Optimierung
8.3.3
187
Optimierungsalgorithmen
Die vorstehenden Heuristiken sind noch kein Algorithmus - sie geben
immerhin an, in welcher “Richtung” die Äquivalenzen aus Abschnitt
8.3.1 ausgenutzt werden sollten. Nach wie vor können in einer bestimmten Situation mehrere Äquivalenzen anwendbar sein. Ein Optimierungsalgorithmus legt fest,
– welche Äquivalenz an welcher Stelle als nächstes ausgenutzt werden
soll;
– wann das Verfahren abgebrochen wird; hierbei ist natürlich die algebraische und interne Optimierung insgesamt zu betrachten. Der
zusätzliche Grenznutzen weiterer Optimierungsmaßnahmen kann
nach den ersten, offensichtlichen Maßnahmen unsicher sein.
Wegen der kombinatorischen Explosion der möglichen Einzelmaßnahmen kann der Aufwand für die Optimierung selbst ausufern;
auch hier müssen Heuristiken eingesetzt werden, um die Untersuchung weniger aussichtsreicher Maßnahmen früh abbrechen zu
können.
Ein einfacher Optimierungsalgorithmus könnte folgendermaßen
vorgehen:
1. zerlegen von Selektionen, deren Bedingung eine Konjunktion ist, in
geschachtelte Selektionen (Regel 2)
2. verschieben aller Selektionen so weit wie möglich nach innen (Regel
1)
3. zusammenfassen von Selektionen und Kreuzprodukten zu Verbunden (Regel 3)
4. vertauschen der Reihenfolge von Verbunden gem. Größe der Relationen (Regel 4)
5. ggf. einfügen von zusätzlichen Projektionen bei Verbunden (Regel
5)
6. verkleinern von zu puffernden Zwischenergebnissen, indem Projektionen nach innen verschoben werden (Regel 6)
188
Abfrageverarbeitung und Optimierung
Wenn eine Regel an mehreren Stellen innerhalb des Ausdrucks anwendbar ist, wird sie jeweils an der ersten gefundenen Stelle zuerst
angewandt.
Beispiel für eine Optimierung. Als Beispiel betrachten wir folgende SQL-Abfrage und ihre Optimierung:
SELECT DISTINCT r.A, s.B
FROM
R r, S s, T t
WHERE r.C = t.C AND s.D = t.D AND r.E = e
Nach der obligaten Syntaxprüfung wird diese Abfrage nach dem Standardschema zunächst in folgenden Ausdruck übersetzt:
πr.A,s.B (σr.C=t.C∧s.D=t.D∧r.E=e (r × (s × t)))
Nach Schritt 1 (Anwendung von Regel 2) erhalten wir:
πr.A,s.B (σr.C=t.C (σs.D=t.D (σr.E=e (r × (s × t)))))
Unter Anwendung von Regel 1 verschieben wir die Selektionen σr.E=e
und σs.D=t.D nach innen in das Kreuzprodukt:
πr.A,s.B (σr.C=t.C (σs.D=t.D (σr.E=e (r) × (s × t))))
πr.A,s.B (σr.C=t.C (σr.E=e (r) × σs.D=t.D (s × t)))
Unter Anwendung von Regel 3 bilden wir jeweils aus einer Selektion
und einem Kreuzprodukt einen Verbund:
πr.A,s.B (σr.E=e (r) 1r.C=t.C (σs.D=t.D (s × t)))
πr.A,s.B (σr.E=e (r) 1r.C=t.C (s 1s.D=t.D t))
Als nächstes stellt sich die Frage, in welcher Reihenfolge die beiden
Verbunde ausgeführt werden sollen30 . Sofern keine weitere Information über die Größe der Relationen verfügbar ist, können wir wegen der
Selektion davon ausgehen, daß die Eingaberelation σr.E=e (r) die kleinste ist; daher sollte zunächst mit ihr ein Verbund berechnet werden.
Da sich die Verbundbedingung, in der r vorkommt, auf t als zweite
30
Dies unter der Annahme, daß kein 3-Wege-Verbund gewählt wird, was hier vermutlich die effizienteste Lösung wäre, aber um des Beispiels willen hier nicht weiter
verfolgt wird.
Abfrageverarbeitung und Optimierung
189
Relation bezieht, sollte der erste Verbund zwischen r und t gebildet
werden. Wir stellen unseren Ausdruck also wie folgt um:
πr.A,s.B ((σr.E=e (r) 1r.C=t.C t) 1s.D=t.D s)
Zum Schluß fügen wir noch Projektionen ein, um nicht im Endergebnis
benötigte Attribute vor den Verbundbildungen zu entfernen:
πr.A,s.B ( πr.A,t.D (σr.E=e (r) 1r.C=t.C t)
1s.D=t.D
πs.B,s.D (s)
)
und
πr.A,s.B ( πr.A,t.D ( πr.A,r.C (σr.E=e (r))
1r.C=t.C
πt.D,t.C (t)
)
1s.D=t.D
πs.B,s.D (s)
)
8.4
Kostenschätzung
Wir hatten schon bei der algebraischen Optimierung z.B. bei der Berechnung mehrerer Verbunde bemerkt, daß man ggf. Informationen
über die Größe der Relationen braucht, um entscheiden zu können,
welche Alternative die wahrscheinlich günstigere ist.
Die Kosten einer Abfrage (z.B. die reale Antwortzeit, s. Abschnitt 8.2) können nicht exakt prognostiziert werden, sondern allenfalls später bei der Ausführung gemessen werden31 . Die absoluten Kosten sind auch insofern unwichtig, als es primär um den Vergleich verschiedener Ausführungspläne geht, also relative Kostenangaben ausreichen. Anzustreben ist daher allenfalls eine ungefähre Prognose, ferner müssen die Ausgangsdaten leicht beschaffbar sein und
die Berechnungsfunktionen dürfen nicht zu aufwendig sein.
Als hinreichend exakter Maßstab hat sich die Zahl der in Zwischenergebnissen oder im Endergebnis erzeugten Tupel bewährt. Um diese
31
Wobei sich herausstellen wird, daß die Kosten nicht exakt reproduzibel sind,
insofern eine exakte Prognose weitere Einflußfaktoren berücksichtigen müßte.
190
Abfrageverarbeitung und Optimierung
zu berechnen oder abzuschätzen, werden folgende Ausgangsdaten (vgl.
Abschnitt 7.4) verwendet:
sr
der durchschnittliche Speicherplatzbedarf eines Tupels (incl.
Hilfsdaten) der Relation r
|r|
die Zahl der Tupel in der Relation r
V(A,r)
die Zahl der verschiedenen Werte, die Attribut A in Relation
r annimmt
Diese (und ggf. weitere) Daten über den Datenbestand können i.a.
nicht ständig exakt vorgehalten werden; es reicht aber aus, diese Daten z.B. einmal täglich zu betriebsschwachen Zeiten zu aktualisieren.
Die laufenden Änderungen in der Datenbank haben auf diese statistischen Werte i.a. nur marginalen Einfluß, d.h. die leicht veralteten
statistischen Daten sind weiterhin brauchbar.
Schätzung der Kosten einer Selektion. In einigen Sonderfällen
kann die Größe des Ergebnisses recht genau vorhergesagt werden:
– Hat die Selektionsbedingung die Form A=a und ist A Identifizierungsschlüssel, so gilt | σA=a (...) | ≤ 1. Analog gilt dies für Identifizierungsschlüssel mit mehreren Attributen.
– Hat die Selektionsbedingung die Form A=a und existiert ein Sekundärindex für A, so kann die Zahl der Treffer durch Auslesen
eines einzigen Satzes im Sekundärindex bestimmt werden.
Sofern diese Sonderfälle nicht zutreffen, kann mit Hilfe der Zahl
V(A,r) wie folgt geschätzt werden:
| σA=a (r) | =
|r|
V (A,r)
Diese Schätzung unterstellt, daß jeder Wert des Attributs A in etwa
gleichhäufig auftritt, die Varianz der Häufigkeitsverteilung also vernachlässigbar ist.
Schätzung der Kosten einer Projektion. Bei Projektionen ohne
Duplikateliminierung hat die Ausgabe gleichviele Tupel wie die Eingaberelation. Mißt man die Größe der Relationen in Tupeln, so gilt
Abfrageverarbeitung und Optimierung
191
| π...(r) |=| (r) |. Für eine detailliertere Analyse des Platzbedarfs des
Ergebnisses kann man den Platzbedarf der projizierten Tupel zusätzlich betrachten.
Bei Projektionen mit Duplikateliminierung gilt das Vorstehende
ebenfalls, sofern die Menge der Attribute, auf die projiziert wird, einen
Identifizierungsschlüssel enthält.
Kosten eines Kreuzprodukts.
akte Formel:
Hier gilt ausnahmsweise eine ex-
| r×s|=|r| ∗|s|
Schätzung der Kosten eines Verbunds. Seien r1 bzw. r2 Relationen des Typs R1 bzw. R2 und V = R1 ∩ R2 die Verbundattribute.
Wenn die beiden Relationen keine gemeinsamen Attribute haben,
also V = ∅, ist der Verbund ein Kreuzprodukt und die vorstehende
Formel ist anwendbar.
Sofern V einen Identifizierungsschlüssel für R2 enthält, ist für jedes
Tupel aus r1 höchstens ein Verbundpartner vorhanden, also:
| r1 1 r2 | ≤ | r1 |
Sofern zusätzlich V in r1 als Fremdschlüssel auf r2 deklariert ist, also
sichergestellt ist, daß immer ein Verbundpartner vorhanden ist, gilt
| r1 1 r2 | = | r1 |.
Sofern die vorstehenden Voraussetzungen nicht zutreffen, kann es
zu einem Tupel von r1 mehrere Verbundpartner in r2 geben. Die
Größe des Ergebnisses kann dann analog wie bei der Selektion abgeschätzt werden. Hierzu nehmen wir vereinfachend an:
– V = {A}, also nur ein Verbundattribut
– Gleichverteilung der Werte von A in r2
Für ein Tupel t in r1 ist die Menge der Verbundpartner in r2 gerade
σA=t[A] (r2). Zur Schätzung der Größe dieser Menge setzen wir die bei
der Selektion entwickelte Formel ein und erhalten:
192
Abfrageverarbeitung und Optimierung
|r2|
=
| r1 1 r2 | = | r1 | ∗ V (A,r2)
|r1|∗|r2|
V (A,r2)
In den vorstehenden Überlegungen können wir natürlich die Rollen
von r1 und r2 vertauschen und erhalten
| r2 1 r1 | =
|r2|∗|r1|
V (A,r1)
Wir haben nun zwei unterschiedliche Schätzungen für | r2 1 r1 |,
denn V(A,r1) und V(A,r2) können signifikant verschieden sein. Wenn
bspw. V(A,r1) kleiner als V(A,r2) ist, bedeutet das, daß in r2 mehr
unterschiedliche Werte im Attribut A auftreten als in r1. Offensichtlich
können dann nicht alle Tupel in r2 einen Verbundpartner finden, die
nur in einer Relation auftretenden Werte sind “hängende Referenzen”.
Als Beispiel betrachten wir in Bild 8.1 zwei Relationen r1 und r2
mit Verbundattribut A und V(A,r1)=3 und V(A,r2)=8. Zur Vereinfachung treten die Zahlen 1, 2, 3 usw. als Werte in A auf, ferner nehmen
wir an, daß beide Relationen nach A sortiert sind. Wenn wir nun r1
durchlaufen, finden wir zu jedem Tupel in r1 |r2|
8 Tupel in r2 als Ver|r1|∗|r2|
Tupel.
bundpartner. Insgesamt entstehen also
8
A
r1
1
2
3
V(A,r1)=3
A
1
2
3
4
.
.
.
r2
V(A,r1)=8
Abbildung 8.1: Größenschätzung eines Verbunds
Wenn wir stattdessen r2 durchlaufen, finden wir nur für | r2 | ∗ 83
Tupel überhaupt einen Verbundpartner in r1. Für jedes dieser Tupel
3 |r1|
finden wir |r1|
3 Verbundpartner. Insgesamt entstehen also | r2 | ∗ 8 ∗ 3
= |r1|∗|r2|
Tupel.
8
Generell gilt also: bei der unterstellten Gleichverteilung der Attributwerte und bei der (optimistischen) Annahme, daß alle in r2 auf-
Abfrageverarbeitung und Optimierung
193
tretenden Werte auch in r1 auftreten, also πA (r2) ⊂ πA (r1), müssen
wir die höhere Selektivität bzw. den kleineren Schätzwert verwenden.
Unsere obige Annahme πA (r2) ⊂ πA (r1) kann falsch sein. Sofern in
beiden Relationen nur wenige Werte in A gemeinsam auftreten, wird
das Ergebnis kleiner werden. Im Extremfall πA (r1) ∩ πA (r2) = ∅ ist
das Ergebnis sogar leer. Sofern man die Zahl der in beiden Relationen
in A auftretenden Werte bestimmt (was in der Praxis aus Aufwandsgründen i.a. nicht möglich sein wird), kann hiermit ein weiterer Korrekturfaktor gebildet werden. Allerdings wird die Schätzung immer
unzuverlässiger; an dieser Stelle sei daran erinnert, daß auch die Annahme der Gleichverteilung der Attributwerte i.a. die Realität stark
vereinfacht.
Glossar
Äquivalenz relationaler Ausdrücke: zwei relationale Ausdrücke sind
äquivalent, wenn bei einem beliebigen Datenbankinhalt beide Ausdrücke das gleiche Ergebnis liefern
Ausführungsplan: konkreter Algorithmus, der zu einer gegebenen Abfrage
das Ergebnis berechnet
Optimierung: Kollektion von Maßnahmen, die zu einer möglichst effizienten Berechnung eines Abfrageergebnisses führen
Optimierung, algebraische: Umformung einer gegebenen Abfrage in eine
äquivalente, effizienter ausführbare; unabhängig vom Datenbankinhalt
Optimierung, interne: Optimierungsmaßnahmen, bei denen Merkmale
des Datenbestands, Indexe, Sortierungen und sonstige interne Merkmale ausgenutzt werden, um einen möglichst guten Ausführungsplan
zu konstruieren bzw. auszuwählen
Sichtenauflösung: Ersetzung einer virtuellen Relation durch die sie definierende Abfrage bei der Abfrageverarbeitung
Lehrmodul 9:
Metadaten
Zusammenfassung dieses Lehrmoduls
Metadaten sind Daten über (Nutz-) Daten.
Metadaten treten
in Datenbanken, in der Dokumentverwaltung, bei der Software-Modellierung und in vielen weiteren Kontexten auf. Entitätsbezogene
Metadaten sind einzelnen Nutzdatengranulaten, typbezogene Metadaten hingegen dem Typ von Nutzdatengranulaten zugeordnet.
Systeme, die Metadaten im gleichen Datenbankmodell wie die
Nutzdaten repräsentieren, nennt man selbstreferentiell.
Typbezogene Metadaten (Schemata) sind instantiierbar, wenn ein DVS
verfügbar ist, das die Instantiierung durchführt. Die auftretenden
Metadaten, deren selbstreferentielle Darstellung und die entstehende
Metadaten-Hierarchie untersuchen wir für relationale Datenbanken,
XML-Dateien und die Metamodell-Hierarchie der UML.
Vorausgesetzte Lehrmodule:
obligatorisch:
– Datenverwaltungssysteme
– Architektur von DBMS
– Einführung in SQL
Stoffumfang in Vorlesungsdoppelstunden:
Stand: 25.06.2007
2.0
c
2007
Udo Kelter
Metadaten
9.1
195
Einordnung und Motivation
Informell definiert man Metadaten als “Daten über Daten”, also Daten, die andere (Nutz-) Daten beschreiben oder einordnen, sie besser
verständlich machen, ihre Struktur darstellen usw. Diese Definition
unterstellt, daß es andere Daten gibt (oder gab oder geben wird, der
Zeitpunkt ist unerheblich) und daß die Metadaten einen vorhandenen
Informationsbedarf stillen.
Der Begriff Metadaten ist alt, er wird immer wieder in neuen Kontexten und in neuen Variationen benutzt. Er ist ferner mit weiteren
komplexen Begriffen wie Metaschema, Metamodell und Meta-CASE
verbunden. Schließlich ist die Trennung zwischen Daten und Metadaten nicht immer eindeutig. Dies alles erklärt die regelmäßig auftretenden Konfusionen um diese Begriffe. Für Metadaten wichtige Kontexte
waren und sind:
– Dokumentverwaltung: Nutzdaten sind hier Bücher und andere elektronische Dokumente, Metadaten sind Angaben über Autor,
Publikationsjahr, Verleger, ggf. persönliche Anmerkungen usw.
Die wichtigste Dokumentsammlung ist inzwischen sicherlich das
WWW; die Bezeichnung Metadaten wird seit einigen Jahren zunehmend mit diesem Kontext verbunden.
– Datenbanken: hier treten neben den Nutzdaten diverse Arten von
Metadaten auf, die wichtigsten sind die konzeptuellen Schemata.
– Programmierung: in objektorientierten Sprachen ist das Prinzip
der Reflexion (reflection) bzw. Introspektion verbreitet; bei Bedarf
können hier Metadaten dynamisch erzeugt werden, die Informationen über die Typstruktur von Objekten darstellen.
– System-Modellierung: man kann die Struktur von Modellen mittels Metamodellen spezifizieren; die UML benutzt diesen Ansatz
durchgängig
In den folgenden Abschnitten analysieren wir die vorstehenden
Fälle detaillierter, um Gemeinsamkeiten und Unterschiede herauszuarbeiten.
196
9.1.1
Metadaten
Metadaten in Datenbanken
Beim Stichwort Datenbankinhalt denkt man oft nur an die eigentlichen
Nutzdaten, z.B. bei einer Adreßdatenbank an die Tupel, die jeweils
eine Adresse darstellen. Auch wenn von Datenbankabfragen bzw. Datenmanipulationsoperationen die Rede ist, sind i.d.R. diese Nutzdaten
gemeint. Neben den Nutzdaten gibt es aber noch weitere Daten, die
ebenfalls mehr oder weniger notwendiger Inhalt einer Datenbank sind
und die i.d.R. eigene Zugriffsschnittstellen haben:
1. die Datenbankschemata, also insb. die Definitionen der applikationsspezifischen Typen
2. Daten über die zugelassenen Benutzer und deren Rechte
3. Daten über die physische Organisation der Datenbank (z.B. Aufteilung auf Dateien oder logische Plattenlaufwerke, Datenträger,
Archive u.ä.) und ggf. interne Schemata
4. ggf. Daten über integrierte Applikationen und speziell bei objektorientierten DBMS Daten über die Operationen einzelner Objekttypen
5. Angaben zur Herkunft der Daten: z.B. kann zu jedem Datum interessieren, wann und von welchem Benutzer es um letzten Mal
geändert wurde
An Rande erwähnenswert sind transiente Hilfsdaten, z.B. über
die angemeldeten Anwendungsprozesse und die von ihnen gehaltenen
Sperren. Bei manchen DBMS kann man diese Daten abfragen und so
spezielle Informationsbedürfnisse befriedigen. Transiente Metadaten
betrachten wir i.f. nicht weiter.
Die im Kontext von DBMS auftretenden Arten von persistenten
Metadaten können wir danach gruppieren, wer ggf. diese Daten lesen
oder ändern möchte und welche Schnittstellen dafür benötigt werden:
1. Eine erste Gruppe persistenter Metadaten dient primär dazu, die
logische Struktur der Daten zu beschreiben und das Verständnis
von Sinn und Zweck der Daten zu unterstützen; man kann hier von
semantischen Metadaten reden. Hierzu zählen die externen und
Metadaten
197
konzeptuellen Schemata, Angaben zur Herkunft der Daten und Angaben zu den Applikationen, in denen die Daten verwendet werden.
Für diese Metadaten muß es Schnittstellen geben, durch die die
Daten von Applikationen abgefragt und ggf. auch geändert werden können. Ferner sind entsprechende Standard-Dienstprogramme
wünschenswert; benutzt werden sie von Applikationsentwicklern
beim Entwickeln und Testen der Applikationen und teilweise auch
von Endnutzern.
2. Eine zweite Gruppe von persistenten Metadaten dient vor allem
administrativen Zwecken. Hierzu zählen die internen Schemata,
Zugriffsrechte, Verwaltung der Datenträger usw. Diese Metadaten
spielen normalerweise (zum Glück) keine Rolle für die Applikationslogik oder den Endbenutzer, sie werden typischerweise nur vom
Datenbank- bzw. Systemadministrator benutzt.
Für die administrativen Metadaten muß es i.w. die gleichen
Schnittstellen für Abfragen und Änderungen geben wie für die semantischen.
Die Trennlinie zwischen semantischen und administrativen Metadaten ist nicht scharf, sie hängt von den individuellen Informationsbedürfnissen ab. Häufig besteht an den administrativen Metadaten
kein Interesse, daher sie werden nicht als Metadaten wahrgenommen.
9.1.2
Metadaten in der Dokumentverwaltung
Klassische Fälle von Dokumentsammlungen sind elektronische Bibliotheken und Büroinformationssysteme. Während diese Sammlungen
noch halbwegs strukturiert sind, ist das WWW als “Dokumentsammlung” extrem heterogen und unstrukturiert. Dementsprechend schwierig ist es, in solchen nicht oder nur schwach strukturierten Datenbeständen zu suchen und Metadaten zu systematisieren. Metadaten
sind hier vor allem dazu gedacht, die Suche nach Dokumenten zu unterstützen.
Eine wichtige Methode, die Strukturen von Nutzdaten besser erkennbar zu machen, besteht darin, zu trennen zwischen
198
Metadaten
– inhaltlich relevanten Daten, die in XML-Dateien gespeichert werden, und
– Formatierungsangaben bzw. Layout-Daten, die z.B. in Style-Sheets
verwaltet werden. Formatierungsangaben sind oft nicht wirklich
Teil der Nutzdaten, weil sie abhängig von Benutzerpräferenzen oder
Anzeigekontexten geändert werden.
Die Struktur von XML-Dateien kann durch Dokumenttypdefinitionen
(oder XML-Schemata) beschrieben werden; diese sind konzeptuell vergleichbar mit Datenbankschemata.
9.1.3
Metadaten vs. Nutzdaten
Bei vielen Metadaten stellt sich die Frage, wieso man sie nicht als Nutzdaten ansieht, vor allem wenn auch der Endnutzer darauf zugreift, und
ob hier nicht die konzeptionelle Trennung zwischen Nutzdaten und Metadaten zerstört wird. Die Antwort ist:
1. Daten sind dann Metadaten, wenn es einen Nutzdatenbestand gibt
(oder gab oder geben wird), den die Metadaten beschreiben, und
wenn die Metadaten zur Interpretation dieser Nutzdaten tatsächlich
genutzt werden. Metadaten beziehen sich immer auf einen Nutzdatenbestand, ohne diesen sind sie keine Metadaten.
Die tatsächliche Nutzung ist eine Frage des Standpunkts oder
der Systemgrenzen, kann also subjektiv unterschiedlich beurteilt
werden. Ein Beispiel sind Analyse-Datenmodelle (ER-Diagramme
oder Analyse-Klassendiagramme): diese sind Metadaten für eine
Person, die sie gebraucht, um entsprechende Nutzdaten zu verstehen oder zu dokumentieren, und nur Nutzdaten für einen ER- oder
UML-Diagrammeditor.
2. Die Speicherungsform spielt keine Rolle dafür, ob Daten Metadaten sind oder nicht. Man kann z.B. die DB-Schemata als Text
repräsentieren oder durch Tabelleninhalte. Unabhängig von der
Speicherungsform sind die Schemata immer Metadaten.
Metadaten
199
3. Wer bzw. welches System die Metadaten ausnutzt, um die Nutzdaten zu interpretieren, ist ebenfalls unerheblich; entscheidend ist,
daß die Metadaten überhaupt für diesen Zweck genutzt werden.
In manchen Fällen werden Metadaten in der Bedienschnittstelle
eines Informationssystems angezeigt, damit Anwender die Nutzdaten verstehen und einordnen können; ein Anwender nutzt die Metadaten mental aus, um die Nutzdaten richtig zu interpretieren.
Metadaten werden oft auch ausgenutzt, um die Nutzdaten maschinell zu interpretieren oder zu verarbeiten. Hauptbeispiel sind
die konzeptuellen Schemata; im DBMS-Kern werden sie dazu benutzt, um Schnittstellen zu den Nutzdaten zu realisieren, in Browsern oder ähnlichen Applikationen dazu, Standard-Darstellungen
der Nutzdaten zu erzeugen.
9.1.4
Selbstreferentialität
Eine ähnliche Frage wie die nach dem Unterschied zwischen Nutzdaten und Metadaten ist die Frage, ob man die Metadaten wie normale
Nutzdaten, also im gleichen Datenbankmodell mittels eines passenden
Schemas modellieren soll.
Die Antwort ist: Für die Speicherungsform und technische Handhabung der Metadaten stehen im Prinzip alle Optionen offen, also
auch die Modellierung im gleichen Datenbankmodell wie die Nutzdaten oder sogar die Speicherung in der gleichen Installation. Details
hängen natürlich vom Datenbankmodell ab. Weiter unten werden wir
am Beispiel von relationalen Datenbanken zeigen, wie man relationale
Schemata durch Tabellen repräsentieren kann.
Sofern Datenbankschemata oder vergleichbare Typdefinitionen eines Datenverwaltungssystem (DVS) als Nutzdaten repräsentiert werden, bezeichnet man dies auch als Selbstreferentialität32 . Die
32
Der Begriff Selbstreferentialität ist nicht optimal, aber es gibt keinen völlig
überzeugenden. Nicht gemeint ist hier Rekursion oder eine Referenz eines Objekts
auf sich selbst. Selbstreferenzierung ist eigentlich ein linguistischer Begriff und bezeichnet das Phänomen, daß ein Text direkt oder indirekt Aussagen über sich selbst
macht (“Jede Regel hat Ausnahmen.”). Es treten mehrere Sprachebenen auf, die
Aussagen über den Text liegen auf einer Meta-Sprachebene.
200
Metadaten
selbstreferentielle Verwaltung bzw. Repräsentation von Metadaten
ändert natürlich nichts an dem inhaltlichen Charakter der Metadaten,
Metadaten werden nicht zu Nutzdaten, nur weil sie technisch genauso
wie die Nutzdaten verwaltet werden.
Die Selbstreferentialität liegt insofern nahe, als die Datenbankschemata und andere DB-Metadaten sowieso innerhalb der Datenbank-Installation benötigt werden und irgendwie verwaltet werden müssen.
Vorteilhaft ist ferner, daß man die Standardschnittstellen und Standardeditoren des Systems verwenden kann, um die Metadaten zumindest auszulesen. Veränderungen an den Metadaten dagegen verursachen erhebliche Probleme, die wir später diskutieren werden.
9.1.5
Sprachebenen in der Linguistik
Metadaten weisen viele Parallelen zum Konzept der Metasprachen auf,
das aus der Linguistik stammt. Eine zentrale Erkenntnis der Linguistik
ist, daß sprachliche Aussagen auf verschiedenen semantischen Sprachebenen (anders gesagt Bedeutungsebenen) stehen können:
Die Basis bilden Aussagen in der sogenannten Objektsprache
(“Hans Maier wohnt in Essen.”).
Nicht mehr zur Objektsprache, sondern zur Metasprache erster
Stufe gehören Aussagen über Aussagen der Objektsprache, z.B.:
“Nachnamen fangen mit einem Großbuchstaben an.”
“Eine Postleitzahl hat 5 Ziffern.”
“Deutsche Sätze haben meist ein Subjekt und ein Prädikat.”
Die vorstehenden Beispiele machen Aussagen zur Wortbildung und
Syntax der Objektsprache. Darüber hinaus könnnen auch Aussagen
zur Bedeutung und zum Wahrheitsgehalt von Aussagen gemacht werden:
“Seine Behauptung ist eine Unverschämtheit.”
“Dieses Buch enthält viele Fehler.”
“Kinder und Betrunkene lügen nicht.”
“Wenn A und B Aussagen sind, wenn eine Aussage der Form ‘aus
A folgt B’ gilt und wenn A zutrifft, dann trifft auch B zu.”
Metadaten
201
Das letzte Beispiel zeigt, daß die mathematische Aussagenlogik
Aussagen in der Metasprache enthält.
Die Metasprache zweiter Stufe enthält Aussagen über Aussagen der Metasprache erster Stufe. Der vorige Abschnitt enthält viele
derartige Aussagen.
Die Parallele zwischen Metadatenebenen und Sprachebenen ergibt
sich daraus, daß Daten ebenfalls Aussagen sind, nur nicht in der Syntax
einer Umgangssprache, sondern etwas kryptischer und platzsparender
codiert. Nutzdaten entsprechen daher Aussagen in der Objektsprache,
Metadaten Aussagen in der Metasprache. Wie wir später sehen werden, muß man analog zu Metasprachebenen auch Metadatenebenen
unterscheiden.
Ein großes Problem entsteht für die Linguistik dadurch, daß die
Umgangssprache alle Sprachebenen zugleich beinhaltet und daß eine
einzige Aussage Begriffe und Bedeutungen auf mehreren Ebenen haben kann (“Dieser Satz hat fünf Worte.”). Wenn eine Aussage auf der
Metaebene auf sich selbst Bezug nimmt und dabei etwas über ihre eigene Wahrheit oder Falschheit aussagt, kann ein Paradoxon entstehen
(“Dieser Satz ist falsch.” “Keine Regel ohne Ausnahme.”).
Bei Daten und Metadaten existieren normalerweise keine analogen Probleme, weil diese durch den Anwendungskontext genau einer
Bedeutungsebene zugeordnet sind. Von der Linguistik kann die Informatik lernen, daß man sich massive Probleme einhandelt, wenn man
Bedeutungsebenen nicht voneinander strikt trennt.
9.2
9.2.1
Arten von Metadaten
Typbezogene vs. entitätsbezogene Metadaten
Sowohl bei Datenbanken wie auch in der Dokumentverwaltung kann
man zwei Arten von Metadaten unterscheiden:
– entitätsbezogene Metadaten: diese sind einzelnen Nutzdatengranulaten bzw. den dadurch dargestellten realen Entitäten zugeord-
202
Metadaten
net. Beispiel: Publikationsdatum oder Seitenzahl eines Buchs. Entitätsbezogene Metadaten müssen für jedes Nutzdatengranulat individuell verwaltet und wie normale Attribute der Nutzdaten modelliert werden. Sie können integriert mit den Nutzdaten oder separat
verwaltet werden.
– typbezogene Metadaten: XML-Dokumenttypdefinitionen, Datenbankschemata, Data Dictionary-Einträge usw. sind Metadaten,
die einheitlich für eine Sammlung von Dokumenten, Tupeln, Datensätzen usw. eines bestimmten Typs gelten. Jedes einzelne Nutzdatengranulat muß einen eindeutigen Typ haben, über den Typ
werden ihm die typbezogenen Metadaten indirekt zugeordnet.
Entitätsbezogene Metadaten werden in diesem Lehrmodul nicht
weiter betrachtet.
9.2.2
Instantiierbare Metadaten
Oben wurden Datenbankschemata als Beispiele von typbezogenen Metadaten genannt – daß ein Nutzer ein Datenbankschema zum Verständnis der Datenbank benutzt, mag durchaus vorkommen, viel häufiger werden Datenbankschemata aber benutzt, um die Datenbank zu
“konfigurieren” und die Aufnahme von Nutzdaten überhaupt erst zu
ermöglichen.
Typbezogene Metadaten, die von einem Datenverwaltungssystem
(DVS) instantiiert werden können, bezeichnen wir als instantiierbare
Metadaten oder Schemata für dieses DVS.
Metadaten sind nicht von sich aus instantiierbar, sondern nur, wenn
ein DVS vorhanden ist, das die Instantiierung im Detail bestimmt.
Charakteristisch für den Umgang des DVS mit den instantiierbaren
Metadaten ist:
– Das DVS wird durch Schemata konfiguriert. D.h. dieses DVS realisiert eine Funktion, mit der ein Schema in das DVS übernommen
werden kann (Beispiel: CREATE TABLE ...); danach können Daten
gemäß diesem Schema (“Instanzen”) in einer Installation des DVS
erzeugt, geändert, gelöscht und durchsucht werden (durch Funktio-
Metadaten
203
nen analog zu INSERT, UPDATE, DELETE und SELECT in relationalen DBMS).
– Alle vorgenannten Funktionen sind insofern generisch, als sie mit
beliebigen Basistypen, die in einem Schema definiert sind, arbeiten
können, und wenigstens einen Typ-Parameter haben, in denen ein
zu benutzender Basistyp explizit angeben wird (z.B. INSERT INTO
relationR ..., SELECT attributeA FROM relationR ...).
– Die Grundzüge der generischen Funktionen werden durch das zugrundeliegende Datenbankmodell definiert. Wie diese Funktionen
im Detail arbeiten und ob es ggf. weitere ergänzende Funktionen
gibt, wird erst durch das konkrete DVS bestimmt. Beispielsweise
könnten verschiedene relationale DBMS mit signifikant verschiedenem Funktionsumfang durch die exakt gleichen Schemata konfigurierbar sein.
Was es also konkret bedeutet, daß eine Instanz von instantiierbaren Metadaten gebildet wird und in welcher Form eine Instanz danach
existiert, hängt in groben Zügen vom Datenbankmodell und im Detail von dem konkreten DVS ab, wird jedenfalls nicht allein durch die
Schemata (egal in welcher Darstellung) spezifiziert. Für sich alleine
genommen sagen die Schemata insb. nichts darüber aus,
– welche enthaltenen Typen einzeln instantiierbar sind (i.d.R. sind
z.B. Attribute nicht einzeln instantiierbar) und
– welche generischen Funktionen vorhanden sind, welche Parameter
sie haben, ob sie mit einzelnen Instanzen oder mit Mengen von
Instanzen arbeiten und wie sie im Detail arbeiten.
Typbezogene vs. instantiierbare Metadaten. Instantiierbare
Metadaten sind definitionsgemäß typbezogenen, aber nicht alle typbezogenen Metadaten sind instantiierbar. Ein Beispiel für typbezogene, nicht instantiierbare Metadaten sind Angaben zu einem Datenfeld,
warum und auf wessen Wunsch es eingeführt wurde und wie es pragmatisch zu benutzen ist. Metadaten sind nur dann instantiierbare Me-
204
Metadaten
tadaten, wenn sie die generischen Funktionen des unterstellten DVS
beeinflussen.
Instantiierbare Metadaten haben einen wesentlich anderen Charakter als “normale” Metadaten:
– Statt die Nutzdaten nur deskriptiv zu ergänzen oder unscharf zu
beschreiben, sind instantiierbare Metadaten Vorschriften, wie die
Nutzdaten strukturiert sein müssen.
– Während normale Metadaten frei gestaltet werden können, müssen
instantiierbare Metadaten völlig konsistent mit den Konzepten des
unterstellten DVS und dessen Datenbankmodell sein. Wie instantiierbare Metadaten aussehen können, wird sehr genau durch das
unterstellte DVS vorgegeben, der eventuelle Informationsbedarf von
Nutzern spielt keine Rolle. Instantiierbare Metadaten sind daher
letztlich als eine von mehreren denkbaren Repräsentationen der
Schemata des unterstellten DVS anzusehen.
– Die Schemata müssen auf jeden Fall innerhalb des Datenbankkerns
verwaltet werden, während alle anderen Metadaten außerhalb des
Datenbankkerns, also wie normale Nutzdaten verwaltet werden.
Instanz-von-Beziehungen. Sofern das DVS die instantiierbaren
Metadaten (und ggf. weitere typbezogene Metadaten) selbstreferentiell darstellt, liegt es nahe, die Nutzdaten mit ihren Typdefinitionen
zu verbinden. Technisch kann dies auf unterschiedliche Weise geschehen, z.B. durch Instanz-von-Beziehungen von den Nutzdaten zu den
selbstreferentiellen Schema-Darstellungen. Im Endeffekt können Applikationen, die mit den Nutzdaten arbeiten, die zugehörigen selbstreferentiell repräsentierten Metadaten lokalisieren, auslesen und bei der
Verarbeitung der Nutzdaten ausnutzen.
Oft werden in der Applikation selbst gemäß dem Analysemuster
Exemplartyp (s. [AMU]) Beschreibungen von Typen und deren Instanzen verwaltet und durch Instanz-von-Beziehungen verbunden. Wie die
Instanzen erzeugt und verwaltet werden, kann bei der Gestaltung der
Applikation völlig frei entschieden werden. Die durch die Applikation
Metadaten
205
bzw. das DBMS realisierten Instanz-von-Beziehungen haben daher eine völlig andere Bedeutung und dürfen trotz ähnlich klingender Namen
nicht gleichgesetzt werden.
9.3
Selbstreferentialität in relationalen Datenbanken
9.3.1
Repräsentation relationaler Schemata durch Tabellen
In relationalen Systemen werden Schemata üblicherweise selbstreferentiell repräsentiert. Der ANSI/ISO SQL-Standard von 2003 definiert eine Datenbank INFORMATION SCHEMA, die diverse Metadaten zu allen Relationen in allen Datenbanken einer Installation bereitstellt. Die Schemata werden durch rund 20 Tabellen repräsentiert,
darunter die Tabellen SCHEMATA, TABLES, COLUMNS und TABLE CONSTRAINTS. Die Datenbank INFORMATION SCHEMA
ist mit SELECT lesbar; verändert werden kann sie nur durch Kommandos wie CREATE TABLE, nicht hingegen durch die Elementaroperationen INSERT, DELETE und UPDATE. I.f. stellen wir eine
stark vereinfachte Version der Inhalte dieser Datenbank vor.
Angaben über die vorhandenen Tabellen und deren Attribute kann man selbstreferentiell bereitstellen mittels einer Tabelle
tabellenattribute, die für jedes Attribut jeder Tabelle den Namen, Typ usw. angibt33 . Die benutzerdefinierte Relation kunden mit
den Spalten Kundennummer, Kundenname, Wohnort und Kreditlimit
würde innerhalb dieser Tabelle wie folgt repräsentiert:
33
Die hier definierte Tabellen tabellenattribute und idschluessel sind stark
vereinfachte Versionen der Tabellen COLUMNS und TABLE CONSTRAINTS.
Wir gehen hier vereinfachend davon aus, daß nur ein einziges Datenbankschema
verwaltet werden muß und man sich implizit hierauf bezieht.
206
Metadaten
Tabelle: tabellenattribute
Tabellenname Attributname
...
...
kunden
Kundennummer
kunden
Kundenname
kunden
Wohnort
kunden
Kreditlimit
...
...
Attributtyp
...
integer
char(40)
char(25)
decimal(5,0)
...
Vorgabewert
...
–
–
–
0,0
...
Die vorhandenen Identifizierungsschlüssel könnte man durch die
folgende Tabelle (idschluessel) darstellen. Eine Tabelle kann mehrere Identifizierungsschlüssel haben, diese werden durch das Attribut
IdSchlNr durchnumeriert. Jeder einzelne Identifizierungsschlüssel besteht aus einer Menge von Attributen, pro Attribut wird ein Tupel in
der Tabelle eingetragen.
Tabelle: idschluessel
Tabellenname IdSchlNr
...
...
kunden
1
...
...
Attributname
...
Kundennummer
...
Letztlich kann man alle Angaben über Tabellen, Domänen, Sichten,
Primärschlüssel, Fremdschlüssel usw., die in den SQL-Kommandos zur
Schemaverwaltung ( CREATE TABLE usw.) textuell dargestellt werden,
auch in tabellarischer Form repräsentieren.
Allerdings deutet bereits das vorstehende Beispiel darauf hin, daß
die tabellarische Darstellung aller Details eines Schemas nicht besonders übersichtlich ist und die textuelle Darstellung deutlich lesbarer
ist. Die Komplexität der Schemata kann reduziert werden, wenn man
für Detailstrukturen eine textuelle Darstellung wählt. In unserem Beispiel haben wir dies für die Attributtypen so gemacht: Texte wie “decimal(5,0)” beinhalten mehrere Angaben, für die bei einer komplett
relationalen Modellierung eigene Spalten vorhanden sein müßten.
Das Prinzip der Selbstreferentialität ist nicht nur bei den Schemata,
sondern bei allen Arten von Metadaten anwendbar, z.B. administrati-
Metadaten
207
ve Metadaten, insb. sofern der Bedarf besteht, diese Metadaten ohne
zusätzliche Schnittstellen abfragen oder sogar verändern zu können.
Das Prinzip der Selbstreferentialität ist im Prinzip bei allen Datenbankmodellen anwendbar, nicht nur beim relationalen. Schemata und
die viele andere Arten von Metadaten haben indessen eine komplexe
Struktur, die spannende Frage ist, ob es die Modellierungsfähigkeiten
des Datenbankmodells erlauben, diese Strukturen bequem zu modellieren. Das obige Beispiel zeigte bereits, daß das relationale Modell
nur bedingt geeignet ist, relationale Schemata zu modellieren.
9.3.2
Zugriff auf selbstreferentiell repräsentierte Schemata
Der offensichtliche praktische Nutzen der Selbstreferentialität ist, daß
man die Standardschnittstellen des Systems verwenden kann, um die
Schemata auszulesen. Man braucht keine eigene Schnittstelle im
DBMS-Kern zu realisieren; eine ggf. gewünschte andere Darstellung
- z.B. textuell - kann durch eine Applikation außerhalb des Datenbankkerns realisiert werden. Ob man die Schemata auch nach der
gleichen Methode verändern kann, ist hingegen fraglich:
1. Wenn wir wieder auf das Beispiel der Tabelle tabellenattribute
zurückkommen, dann müßte das Löschen eines Tupels zur Folge haben, daß in der betroffenen Tabelle ein Attribut entfernt und ggf.
Teile der Datenbank konvertiert werden. Dies ist aber u.U. überhaupt nicht möglich oder nicht im Normalbetrieb; der Versuch, das
Tupel zu löschen, müßte dann mit einer speziellen Fehlermeldung
abgelehnt werden. Dies bedeutet, daß sich die Semantik von Standardoperationen ändert, wenn man sie auf Metadaten anwendet,
und zwar durch eine Vielzahl von Nebeneffekten und zusätzliche
Fehlerfälle. Dies ist umständlicher und schlechter verstehbar als
eigene Operationen.
2. Die Struktur der Metadaten ist oft relativ komplex und kann komplizierte Integritätsbedingungen aufweisen. Da das zugrundeliegende Datenbankmodell normalerweise recht elementare Operationen
208
Metadaten
aufweist, braucht man mehrere elementare Operationen, um eine
korrekte Typdefinition zu konstruieren oder abzuändern (z.B. bei
einer Objekttypdefinition wird zuerst der Typ erzeugt und dann
werden ‘Eltern’-Beziehungen zu den Supertypen erzeugt, dann die
Attribute zugeordnet). Die einzelnen Änderungen dürfen zunächst
keine Auswirkungen auf die Metadaten haben, erst wenn die gesamte Sequenz von Operationen ausgeführt ist, können die Metadaten
tatsächlich geändert werden. Da das DBMS von sich aus den Abschluß der Änderung nicht erkennen kann, benötigt man zusätzlich
eine Operation, die den Abschluß signalisiert; das DBMS muß dann
herausfinden, welche Detailänderungen vorgenommen wurden, und
prüfen, ob der neue Zustand korrekt ist.
Die Vorstellung, daß durch normale Datenmanipulationsoperationen implizit auch die Metadaten verändert werden, kann hier
praktisch nicht mehr aufrechterhalten werden.
Aufgrund der vorstehenden Probleme eignet sich der selbstreferentielle Ansatz i.a. nur für das Auslesen, nicht aber für das Ändern von
Metadaten. Daher werden im ANSI/ISO SQL-Standard alle Tabellen
mit Metadaten als schreibgeschützt definiert.
9.3.3
Metatypen und Meta-Metadaten
Die Metadaten haben natürlich auch Typen; diese Typen bezeichnet
man als Metatypen, entsprechende Schemata als Metaschemata.
Ein Beispiel für ein Metaschema ist das Schema unserer oben erwähnten Tabelle tabellenattribute.
Die Metatypen kann man wiederum selbstreferentiell repräsentieren; diese Daten sind Daten über Metadaten, also Meta-Metadaten.
Die folgende Tabelle zeigt dies für die Metatypen aus den Tabellen
tabellenattribute und idschluessel. Man beachte, daß die Spaltenköpfe der beiden genannten Tabellen hier zu Datenwerten in der
Spalte Attributname werden.
Metadaten
Tabelle: datenbankmodellKonzepte
Tabellenname
Attributname Attributtyp
tabellenattribute Tabellenname char(200)
tabellenattribute Attributname char(200)
tabellenattribute Attributtyp
char(200)
tabellenattribute Vorgabewert
char(1000)
idschluessel
Tabellenname char(200)
idschluessel
IdSchlNr
integer
idschluessel
Attributname char(200)
209
Vorgabewert
–
–
–
–
–
–
–
Die Tabelle wurde datenbankmodellKonzepte genannt, weil die
Metatypen den Konzepten aus dem Datenbankmodell entsprechen.
Es war relativ leicht, die Tabelle datenbankmodellKonzepte hinzuschreiben und den Begriff Meta-Metadaten zu bilden. Bei genauem
Hinsehen ist aber nicht klar, ob das überhaupt sinnvoll ist, was wir da
gemacht haben:
1. Meta-Metadaten stillen eigentlich keinen Informationsbedarf, der
bei der Interpretation oder Verarbeitung der Metadaten entstehen
würde.
Entwickler von Applikationen und Datenbank-Nutzer wissen sowieso, daß Attribute einen Namen, Typ und Vorgabewert haben,
dahingehend besteht kein Informationsbedarf. Wenn diese Kenntnisse über das Datenmodell nicht vorhanden wären, könnte man
außerdem die Meta-Metadaten, die ja als Nutzdaten repräsentiert
werden, gar nicht abfragen, denn um die Abfrage formulieren zu
können, muß man dieses Wissen schon haben.
Allenfalls sind Abfragen sinnvoll, wie lang z.B. der Name einer
Tabelle maximal sein darf; dies sind aber technische Details, die
man eher als Konfigurationsparameter der generischen Funktionen
des DBMS-Kerns auffassen wird.
Der DBMS-Kern konsultiert auch nicht die Meta-Metadaten, bevor er auf die Metadaten zugreift, um herauszufinden, ob er diese
Metadaten als Schemata von relationalen Tabellen oder als Dokumenttypdefinitionen von XML-Dateien oder Konfiguration einer
210
Metadaten
Suchmaschine interpretieren soll – die generischen Funktionen, die
der Laufzeitkern eines relationalen DBMS realisiert, können nur mit
relationalen Tabellen arbeiten, mit sonst nichts.
2. Die Meta-Metadaten können nicht ohne weiteres (signifikant)
geändert werden, ohne zugleich den DBMS-Kern umzuprogrammieren. Ändert man das Metaschema ab, so ist deswegen alleine
überhaupt nicht klar, wie der DBMS-Kern mit diesen neuen Strukturen umgehen soll.
Wir könnten z.B. in der Tabelle datenbankmodellKonzepte ein
neues Tupel (’tabellenattribute’, ’Geheimhaltungsstufe’,
’char(200)’, ’’ ) eintragen. Was das bedeuten soll, ist völlig
unklar. Man müßte zunächst klären, wie das Konzept einer Geheimhaltungsstufe zu verstehen ist, dazu passend müßte ggf. die
Syntax des CREATE TABLE-Kommandos erweitert werden, und die
Wirkung der generischen Funktionen müßte geeignet modifiziert
werden. Außerdem müßte natürlich die Metadaten-Tabelle tabellenattribute eine weitere Spalte Geheimhaltungsstufe bekommen. Im Endeffekt müssen wesentliche Teile des DBMS-Kerns
umgestaltet werden. Ferner müßten ggf. sogar alle Nutzdaten entsprechend angepaßt werden.
Als Konsequenz aus den vorstehenden Überlegungen sind das Metaschemata eines DBMS und dessen selbstreferentielle Repräsentation durch Meta-Metadaten, also hier die Tabelle datenbankmodellKonzepte, immer komplett statisch. Selbstreferentiell repräsentierte
Metaschemata sind daher (in üblichen DBMS) in der Praxis weitgehend sinnlos! Man kann diese Metadaten nicht ändern, und um diese
Daten abzufragen, muß man viele Konzepte schon vorher kennen, weil
sie in der Abfrage verwendet werden.
9.3.4
Übersicht über die semantischen Ebenen
Man kann die auftretenden Daten bzw. selbstreferentiellen Schemarepräsentationen je nach ihrer Bedeutung in mehrere Ebenen einteilen,
diese Ebenen sind in der Tabelle in Bild 9.1 zusammengefaßt.
Lesehinweise zu dieser Tabelle: Auf Ebene 0 werden Nutzdaten
Metadaten
Nr. Bedeutungsebene
(Daten repräsentieren...)
2
1
0
Meta-Metadaten: Repräsentationen von Metaschemata / Metatypen
Metadaten: Repräsentationen von Schemata / Typen
Nutzdaten:
Repräsentationen von Realwelt-Entitäten
211
Beispiel
einer
dargestellten
Entität
Begriff “Tabelle”
Tabellenschema
“Adressen”
eine Adresse
Syntax
und
Semantik
der
Daten
wird
bestimmt durch
...
MetaMetaschema
veränderbar
Metaschema +
Datenbankmodell + DBMS
Schema + Dokumentation
ja
nein
ja
Abbildung 9.1: Hierarchie der Bedeutungsebenen von Daten in einer
Datenbank
verwaltet. Die “syntaktische” Struktur der Nutzdaten wird durch ein
Schema vorgegeben, das allerdings komplexere Konsistenzbedingungen
i.d.R. nicht beinhaltet; letztere können z.B. in einem Data Dictionary
verbal dokumentiert sein, insofern wird noch nicht einmal die syntaktische Struktur der Daten durch das Schema vollständig dargestellt.
Überhaupt nicht dargestellt wird die Bedeutung der Daten. Schemata
werden auf Ebene 0 nur genutzt, aber nicht in irgendeiner Form als
Daten repräsentiert oder verwaltet.
Auf Ebene 1 werden Repräsentationen von Schemata verwaltet.
Daß dies in der syntaktischen Form von Tabellen geschieht, ist willkürlich, man könnte genausogut eine textuelle Darstellung verwenden34 .
Entscheidend ist, daß Schemata dargestellt werden. Für das Metaschema gelten die gleichen prinzipiellen Bemerkungen wie für das Schema:
es stellt nur die syntaktische Struktur der Schemata weitgehend dar,
34
Die textuelle Darstellung wäre durch eine Grammatik bzw. Sprachdefinition
strukturiert! Man kann übrigens die Daten auf alle Ebenen textuell darstellen und
erhält dann eine Hierarchie von Sprachebenen. In der Tabelle muß dazu überall
“Schema” durch “Grammatik” ersetzt werden.
212
Metadaten
aber nicht vollständig, und die Bedeutung der Schemata überhaupt
nicht.
Die letzte Spalte gibt an, ob diese Daten innerhalb eines DBMS
durch die Nutzer veränderbar sind.
Man kann diese Daten- und Schemahierarchie beliebig nach oben
fortsetzen, es bringt aber nichts ein. Schon auf Ebene Metadaten
stößt das Prinzip der Selbstreferentialität an Grenzen, denn ändernde
Standard-Operationen sind nicht mehr erlaubt35 . Die selbstreferentielle Repräsentation der Metatypen ist sinnlos, weil die Metatypen
eines DBMS komplett statisch sind.
9.3.5
Meta-Ebenen vs. Implementierungsebenen von
Datenbankobjekten
Die semantischen Meta-Ebenen in Bild 9.1 werden leicht verwechselt
mit den Ebenen der Abstraktionshierarchie für Datenbankobjekte, die
in Abschnitt 3.4 vorgestellt wird.
Prinzipiell haben diese beiden Hierarchien nichts miteinander zu
tun, sie sind völlig orthogonal zueinander. Nutzdaten, Metadaten und
ggf. Meta-Metadaten existieren alle nebeneinander und gleichzeitig als
persistente Daten, sie müssen in irgendeiner Form auf den persistenten
Medien gespeichert und beim Lesen von dort in mehreren Schritten an
die Schnittstellen gebracht werden.
Ein extern sichtbares Tupel, das z.B. eine Adresse darstellt, existiert intern in absteigender Reihenfolge der Ebenen als Pufferbereich,
als Inhalt eines Speichersatzes, als Teil eines Blocks und letztlich als
magnetische Struktur auf einer Platte – in allen Fällen sind dies semantisch gesehen die gleichen Nutzdaten, nur die Implementierungsebene
unterscheidet sich. In der nachfolgenden Tabelle sind Nutzdaten in
Spalte 2 skizziert und jeweils mit “Std.” für Standardverfahren mar35
Zur Klarstellung sei daran erinnert: wir diskutieren hier nur instantiierbare Metadaten, also Repräsentationen von Schemata. Andere Metadaten können natürlich
mit Standard-Operationen geändert werden, da sie keine operationale Bedeutung
haben. Obwohl es sich semantisch um Metadaten handelt, können sie technisch wie
Nutzdaten behandelt werden.
Metadaten
213
kiert.
Implementierungsebene
Nutzdaten
n-Tupel-Ebene
1-Tupel-Ebene
Speichersatzebene
Std.
Std.
Std.
Metadaten
(Schemata)
nur lesen
nur lesen
Std.
Segmentebene
Std.
Std.
Metametadaten
(Metaschemata)
geeignet??
geeignet??
nur
teilw.
sinnv.
nur
teilw.
sinnv.
Analog wie Nutzdaten müssen auch die Metadaten über die komplette Implementierungshierarchie hinweg realisiert werden. In der
vorstehenden Tabelle sind Metadaten in Spalte 3 skizziert, die parallelen Spalten für Nutzdaten und Metadaten sollen andeuten daß beide
Arten von Daten gleichzeitig nebeneinander existieren.
Auf den beiden unteren Ebenen kann man die Metadaten wie
normale Daten verwalten, man kann aber ebensogut abweichende
Implementierungen verwenden, weil auf Metadaten anders als auf
Nutzdaten zugegriffen wird. Auf der 1-Tupel-Ebene kann man immerhin noch für lesende Zugriffe die Standardschnittstellen und Implementierungsverfahren anbieten, für schreibende Zugriffe sind andere Schnittstellen sinnvoller. Auch dann, wenn Standardverfahren
zum Einsatz kommen, und unabhängig von der Implementierungsebene sind die Daten, die z.B. ein Schema darstellen, immer Metadaten.
Metametadaten, also speziell das Metaschemata, kann man theoretisch ebenfalls selbstreferentiell repräsentieren; diese Daten existieren
dann parallel zu den Nutzdaten und Metadaten ebenfalls über alle Implementierungsebenen. Wie aber schon früher diskutiert können aus
diversen praktischen Gründen Metametadaten nur mit sehr starken
Einschränkungen selbstreferentiell repräsentiert werden. Weil es auch
wenig Vorteile einbringt, liegt es nahe, komplett darauf zu verzichten.
214
9.4
9.4.1
Metadaten
Selbstreferentialität in XML
Aufbau von XML-Dateien
XML-Dateien enthaltenen i.w. zwei Teile:
– einen Nutzdatenbestand, dessen Struktur ein Baum ist. Der Baum
wird textuell dargestellt. Ein Teilbaum, auch Element genannt,
wird in einem Textabschnitt dargestellt, der mit einem öffnenden
tag beginnt, z.B. <Adresse>, und einem schließenden tag endet, z.B.
</Adresse>. Jeder Knoten des Baums hat einen Typ, der Name
des Typs steht in beiden tags. Im öffnenden tag können ferner Attributwertzuweisungen stehen, z.B. <Adresse AdrID=’A112’>. Hier
ein Beispiel eines Teils der Nutzdaten:
<Adresse AdrID=’A112’ >
<Name>Frank</Name>
<Vorname>Ulrich</Vorname>
<Straße>Hauptstr.</Straße>
<Hausnummer>5</Hausnummer>
<Ort PLZ=’57076’>Siegen</Ort>
</Adresse>
<Adresse>
....
</Adresse>
– einer optionalen Dokumenttypdefinition (DTD), in der die Schachtelungsstruktur der tags definiert wird.
Bei der DTD handelt es sich im Prinzip um eine kontextfreie Grammatik, die die Syntax und die inhaltliche Struktur des Textes, der die
Nutzdaten darstellt, definiert. Hier können wir folgenden sehr interessanten Sachverhalt feststellen: Die Bedeutungsebenen von Daten,
Metadaten usw. in Datenbanken (s. Tabelle 9.3.4) gelten analog für
Texte, Grammatiken, Meta-Grammatiken usw.
Das Prinzip der Selbstreferentialität wird somit (mit hier nicht interessierenden Ausnahmen) auch in XML-Dateien in Form von DTDs
Metadaten
215
oder XML-Schemata angewandt. Auf Details gehen spätere Lehrmodule über Transportdateien und die XML [TRD] ein.
9.4.2
Typ-Annotationen
Eine spezielle, oft irreführende Form von Metadaten stellen die Typangaben in den Tags in XML-Dateien dar. Derartige Angaben zum
Typ der Daten, die direkt in die Nutzdaten eingebettet sind, bezeichnen wir als Typ-Annotationen. Typ-Annotationen treten auch in
Bibtex-Dateien und vielen anderen Transportdateiformaten auf.
Als Beispiel betrachten wir wieder den obigen Ausschnitt aus einer XML-Datei, die in den Nutzdaten eine Adreßliste enthält. Die
eigentlichen Adreßdaten sind offensichtlich Nutzdaten. Die Frage ist,
ob die Namen der Elementtypen und Attribute Metadaten sind und
welche Art von Metadaten hier vorliegt. Diese Namen kann man ohne weiteres gemäß der allgemeinen Definition, wonach Metadaten die
Interpretation der Nutzdaten ermöglichen bzw. unterstützen, als entitätsbezogene Metadaten ansehen; dies ist abhängig von der subjektiven Verwendung dieser Daten. Unklar ist hingegen, ob diese Namen
auch typbezogene Metadaten in dem Sinne sind, daß sie implizit ein
Schema der Nutzdaten darstellen (ggf. redundant bei jeder Instanz).
9.4.2.1
Typ-Annotationen in schwach strukturierten Daten
An dieser Stelle muß man sich bewußt machen, daß XML eigentlich
für schwach strukturierte Daten gedacht ist, das sind Daten, deren
Struktur extrem variantenreich ist und/oder sich ständig unvorhersehbar ändert. Das Fehlen von eindeutigen Typdefinitionen ist gerade das
Wesensmerkmal schwach strukturierter Daten.
In Datenbanken und in vielen Programmiersprachen haben Typen
die zentrale Eigenschaft, für alle Instanzen des Typs eine einheitliche
Struktur sicherzustellen; genau diese Eigenschaft ist unerwünscht bei
schwach strukturierten Daten. Weil es für derartige Daten keine Schemata im Sinne von Datenbanken gibt, ist die Selbstreferentialität hier
prinzipiell nicht sinnvoll.
216
Metadaten
Wenn man, obwohl es kein Schema gibt, trotzdem etwas über die
Struktur aller Instanzen eines Elementtyps wissen will, kann man bestenfalls die Kindelementtypen und Attribute, die bei den vorhandenen Instanzen dieses Elementtyps auftretenden, aufsammeln. Man
findet aber mit dieser Methode viele Strukturmerkmale nicht sicher
heraus: die zulässige Häufigkeit einzelner Kindelemente, Reihenfolgerestriktionen, bei Attributen wie z.B. AdrID die Art des Attributs36 .
Ferner könnte die vollständige Typdefinition einer Adresse eine optionale Angabe der Anrede und des Landes beinhalten, die zufällig in
den vorhandenen Nutzdaten nirgendwo auftritt. Die implizit durch
die Typ-Annotationen gegebenen Typdefinitionen sind also i.a. vage
und unvollständig.
9.4.2.2
Typ-Annotationen in strikt typisierten Nutzdaten
Sofern die Daten strikt typisiert sind, also eine DTD (oder ein XMLSchema) vorhanden ist und nur gemäß der DTD gültige XML-Dateien
betrachtet werden, interessiert die Frage nicht mehr, ob die tags
implizit eine Typdefinition darstellen. Die Typnamen in den tags
sind nunmehr als Referenzen auf die Typdefinitionen in der DTD
zu verstehen, also als unidirektional implementierte “ist-Instanz-von”Beziehungen37 .
Wenn man Typ-Annotationen als Referenzen auf Typdefinitionen
versteht, ist es wenig sinnvoll, sie als entitätsbezogene Metadaten anzusehen, weil sie ja nur Referenzen auf etwas anderes sind und selbst
nichts aussagen. Dies wird besonders offensichtlich, wenn die Typnamen keine intuitive Semantik vermitteln, sondern nur “sinnlose”,
generierte Nummern sind:
.....
<TypId117543>Frank</TypId117543>
<TypId117544>Ulrich</TypId117544>
36
Möglich wäre ein ID-, IDREF-, IDREFS- oder CDATA-Attribut.
Es kommt hier nicht darauf an, daß die Typdefinitionen tatsächlich technisch
in einem XML-Format vorliegen, sondern daß sie im Anwendungskontext (z.B. innerhalb von Applikationen) als Referenzen auf Typdefinitionen interpretiert und
benutzt werden.
37
Metadaten
217
.....
Der entscheidende Punkt ist hier, daß man (meist unbewußt) zu
einem anderen Datenbankmodell übergegangen ist, nämlich zu einem
Datenbankmodell mit streng typisierten Datengranulaten. In einem
solchen Datenbankmodell hat jedes Datengranulat einen eindeutigen
Typ, und für jeden Typ liegt eine vollständige Definition vor. Das
relationale Datenbankmodell ist ein Beispiel hierfür.
Bei einem streng typisierten Datenbankmodell müssen die internen
Implementierungsstrukturen so gestaltet werden, daß zu jedem Datengranulat sein Typ festgestellt werden kann. Im relationalen Datenbankmodell wird dies i.d.R. dadurch realisiert, daß alle Tupel gleichen
Typs in einem Container (einer Tabelle) verwaltet werden und die Typdefinition der Tabelle zugeordnet ist. Man kann aber auch die Datengranulate gemischt speichern, muß dann aber an jedem Datengranulat
explizit eine Typangabe speichern. Ob man hierfür ausdrucksstarke
Namen oder sinnlose Nummern verwendet, ist eine Implementierungsentscheidung. Konzeptuell wird in allen Fällen eine Referenz auf die
volle Typdefinition realisiert.
Eine XML-Datei entspricht bzgl. des Implementierungsniveaus einem B*-Baum in der Implementierungshierarchie für Datenbankobjekte38 . Die XML-Datei implementiert einen getypten Baum; man sieht
(leider) die Implementierungsdetails komplett.
Unsere Ausgangsfrage, ob bei strikt typisierten Nutzdaten die
Typ-Annotationen Metadaten sind, ist letztlich nur Folge eines falsch
gewählten Betrachtungsstandpunkts; hier werden Meta-Ebenen und
Implementierungsebenen verwechselt (vgl. Abschnitt 9.3.5).
38
Man beachte die Analogie zwischen den Begriffen “physische Konsistenz” einer
Datenbank und “Wohlgeformtheit / Validität” einer XML-Datei. Wenn eine Datenbank physisch inkonsistent ist, ist der intern sichtbare Inhalt nicht mehr korrekt
gemäß den Schemata interpretierbar. Wenn eine XML-Datei infolge eines falsch
geschriebenen Typnamens oder Fehlers in einem Tag nicht mehr valide bzgl. einer
DTD bzw. wohlgeformt ist, wird ihr Inhalt nicht mehr von einem validierenden
XML-Prozessor akzeptiert, sie kann nicht mehr verarbeitet werden.
218
Metadaten
9.5
9.5.1
Metadaten in der UML-Begriffswelt
Bedeutungsebenen von UML-Modellen
Die UML-Definition nutzt ebenfalls intensiv das Prinzip der Selbstreferentialität und setzt eine Hierarchie semantischer Ebenen ein, die auf
den ersten Blick identisch zu der Hierarchie in Bild 9.1 erscheint, bei
genauer Betrachtung aber erhebliche Unterschiede aufweist. Diese versteckten Begriffsdifferenzen führen notorisch zu Kommunikationsproblemen, zumal beide Begriffswelten in vielen Fällen parallel verwendet
werden müssen. Der wichtigste derartige Fall ist die Transformation
von Analyseklassendiagrammen in Datenbankschemata, die suggeriert,
daß Analyseklassendiagramme und Datenbankschemata einander entsprechen; eben dies trifft, wie wir sehen werden, gerade nicht zu.
Kürzel
für die
MetaEbene
M3
M2
M1
M0
dieser Ebene zugeordnete
Daten oder Realweltentitäten
Beispiel
einer Instanz
Daten werden modelliert durch
Repräsentation der “Sprache”, in der Typdefinitionen definiert werden (MetaMetaschema)
Definitionen von Typen von
Modellen bzw. Modellelementen (Meta-Metadaten)
Struktur- und Verhaltensmodelle (Metadaten)
Meta
Object Facility
(MOF)
Meta-MetaMetamodell
die UML
MetaMetamodell
Zustandsautomat
“MobilTel”
GUI
eines
Mobiltelefons
Metamodell
beliebige Realweltentitäten
bzw. Daten, die Realweltausschnitte repräsentieren
Modell
Abbildung 9.2: Hierarchie der Bedeutungsebenen von Daten (Modellen) der UML
Die in [UML-IS06] und anderen Quellen benutzte Hierarchie semantischer Ebenen ist in Bild 9.2 wiedergegeben. Die UML-Daten-
Metadaten
219
bzw. Bedeutungsebenen M1 bis M3 (M0 bildet eine Ausnahme) haben in mehrerer Hinsicht bis auf Äußerlichkeiten gleiche Strukturen
(vgl. Bilder 9.1 und 9.2) wie die Bedeutungsebenen von Nutzdaten
bzw. Schemarepräsentationen in Datenbanken:
– Die Daten auf allen Bedeutungsebenen sind strikt typisiert und entsprechen einem Schema bzw. einem Modell.
– Der Ebene M(i+1) sind Daten zugeordnet, die das Schema bzw.
das Modell der Ebene Mi selbstreferentiell repräsentieren.
– Das Verhalten der Objekte auf Ebene Mi wird abgesehen von einer Ausnahme (die beiden untersten Ebenen der UML-Hierarchie)
nicht auf Ebene M(i+1) spezifiziert.
Eine nur scheinbare Gemeinsamkeit der Datenbank- und der UMLBegriffswelt besteht darin, daß der untersten Ebene unter anderem (!)
Daten zugeordnet sind, die im Anwendungskontext relevante Entitäten
der realen Welt repräsentieren.
Ebene M0. Die UML-Spezifikationen betonen an vielen Stellen, daß
die Daten der Ebene M0 kein Gegenstand der UML sind. Die UML ist
definitionsgemäß eine Sprache, in der man Dokumente wie Klassendiagramme, Anwendungsfalldiagramme usw. formulieren kann, also
Dokumente, die durch Daten repräsentiert werden, die der Ebene M1
zuzuordnen sind. Die Ebene M0 wird nur gebraucht, um punktuell erklären zu können, wie “Instanzen der Modelle” aussehen können und
wie Modelle gebildet werden sollten, um einen Realweltausschnitt korrekt wiederzugeben.
Ebene M1. Die Rolle der Modelle wird klar, wenn man danach
fragt, welche Art von Systemen die UML bzw. ein Datenbankmodell
spezifizieren und was darin die Nutzdaten sind. Der Sinn und Zweck
der UML besteht darin, zu spezifizieren, wie Editoren und andere Entwicklungswerkzeuge für UML-Dokumente Modelle verarbeiten sollen.
Die Nutzdaten solcher Werkzeuge bzw. Systeme sind die Modelle bzw.
Diagramme, also Daten der Ebene M1!
220
Metadaten
Die Frage, ob überhaupt und ggf. in welchem Sinne die UMLModelle Metadaten sind, werden wir anschließend im Detail diskutieren. An dieser Stelle sei jedenfalls betont, daß die UML nicht nur Klassendiagramme definiert, sondern auch Sequenzdiagramme und diverse
andere Diagrammtypen, die Verhaltenseigenschaften modellieren. Verhaltenseigenschaften werden z.B. im Programmcode des modellierten
Systems realisiert und sind i.a. innerhalb des modellierten Systems
(oder wo auch immer) überhaupt nicht durch Daten repräsentiert. Daher sind Sequenzdiagramme und andere Verhaltensmodelle gar keine
Metadaten: es gibt keinen Datenbestand, der mit ihrer Hilfe strukturiert oder interpretiert wird!
Ebene M2. Die Daten der UML-Ebene M2 enthält Metamodelle;
wie schon erwähnt werden hier ausschließlich Klassendiagramme in
Sinne reiner Datenmodelle eingesetzt. Diese Modelle modellieren ausschließlich die statischen Datenstrukturen, durch die die Struktur- und
Verhaltensmodelle der Ebene M1 repräsentiert werden können.
Verhalten der Modelle der Ebene M1 wird nicht modelliert. Bei
allen Modelltypen könnte man theoretisch z.B. Editieroperationen,
durch die die Struktur- und Verhaltensmodelle aufgebaut und editiert werden, durch Aktivitätsdiagramme modellieren. Mit bestimmten Einschränkungen könnte man auch Simulatoren für Aktivitätsdiagramme spezifizieren. Offensichtlich wäre dies extrem aufwendig
und im Sinne eines Standards auch überflüssig, weil dies gerade Werkzeugfunktionen sind, in denen sich die Produktanbieter unterscheiden
wollen.
Betont werden muß jedenfalls, daß die Metamodelle die Modelle
nur sehr lückenhaft repräsentieren, weitaus unvollständiger jedenfalls,
als man mit diversen Modellen der Ebene M1 den Realweltausschnitt
modelliert. Daß die UML-Begriffshierarchie unterschiedslos aussagt,
die nächsthöhere Stufe sei ein “Modell” der darunterliegenden, verschleiert diesen wichtigen Qualitätsunterschied und ist die Ursache
vieler Mißverständnisse.
Metadaten
221
Vergleich der Datenbank- und UML-Metadatenebenen. Jede Metadatenhierarchie bezieht sich explizit oder implizit auf eine bestimmte Art von Systemen39 , die Metadaten nutzen, um Nutzdaten
zu interpretieren. Zentraler Bezugspunkt sind die Daten, die in der
jeweiligen Systemklasse als Nutzdaten anzusehen sind. In der Datenbankbegriffswelt sind die Daten der Ebene M0 die Nutzdaten, in der
UML-Begriffswelt hingegen die Daten der Ebene M1. Diese beiden
Ebenen entsprechen einander daher. Alle höheren Ebenen korrespondieren dementsprechend jeweils um einen Zähler verschoben. Dieser
und weitere Unterschiede bzw. Korrespondenzen sind in Bild 9.3 zusammengefaßt.
Vergleichsaspekt
spezifizierte Systemklasse
DBMS
DBMS
Ebene der Nutzdaten der spezifizierten
Systemklasse
Ebene der Schemata / Steuerdaten der
spezifizierten Systemklasse
implizite Mengenverwaltung der Nutzdaten, generische Suchfunktionen
Schemata / Steuerdaten dürfen sich
während der Lebenszeit von Nutzdaten
ändern
Sichtenmechanismus für Nutzdaten
M0
M1
UML
CASEWerkzeuge
M1
ja
M2 (MetaCASE)
nein
ja
nein
ja
nein
Abbildung 9.3: Korrespondierende Konzepte von UML und DBMS
Dem ersten, aber falschen Anschein nach entsprechen die Modelle
der UML-Hierarchie – zumindest Klassendiagramme ohne Operationen – den Schemata. Bestärkt wird dieser Anschein im speziellen Fall
von Analyseklassendiagrammen dadurch, daß diese fast automatisch
in Schemata übersetzt werden können.
Die Frage ist noch offen, welche Art von Systemen durch die Me39
oder eine Personengruppe, diesen Fall betrachtet wir hier nicht.
222
Metadaten
tamodelle der UML analog zu den Schemata in einer Datenbank konfiguriert bzw. gesteuert wird. In erster Linie zu nennen sind hier
sogenannte Meta-CASE-Werkzeuge, die wir unten diskutieren werden.
9.5.2
“ist-Instanz-von”-Beziehungen
Die UML-Begriffswelt postuliert, daß die Objekte der Ebene Mi als
Instanzen der Objekte der Ebene M(i+1) aufzufassen sind, s. z.B.
Bild 7.8 in [UML-IS06] und die << instanceOf >>-Beziehungen zwischen den Objekten verschiedener Ebenen. Dies ist leider eine sehr
unsaubere Begrifflichkeit, die automatisch zu Komplikationen führt.
Die “ist-Instanz-von”-Beziehungen, die zwischen den verschiedenen
Ebenen auftreten, sind nämlich nicht immer einheitlich interpretierbar. Ferner haben “ist-Instanz-von”-Beziehungen zwischen den korrespondierenden Ebenen bei DBMS und bei der UML teilweise verschiedene Bedeutungen. Grundsätzlich kann man “ist-Instanz-von”Beziehungen auf zwei Arten interpretieren:
1. “von unten nach oben”: Ausgangspunkt ist das reale System, das
Modell ist ein vereinfachtes, unvollständiges Abbild. Aus dem Modell kann das modellierte System nicht komplett rekonstruiert werden.
2. “von oben nach unten”: Ausgangspunkt ist das Modell, es wird
als Konfigurationsparameter eines “generischen” Softwaresystems
benutzt und konfiguriert letzteres so, daß Instanzen des Modells
verarbeitet werden können. Das System auf der unteren Ebene,
das die Instanzen bearbeiten bzw. verwalten kann, entsteht durch
Übersetzen oder Interpretieren des Modells.
Man kann den Unterschied auch so auf den Punkt bringen, daß Modelle entweder vage oder präzise Spezifikationen des modellierten Systems
sind.
In der Datenbank-Begriffswelt sind insb. die instantiierbaren Metadaten, also die Schema, als präzise Spezifikation der Schicht aufzufassen, in der die Nutzdaten verwaltet werden.
Metadaten
223
In der UML-Begriffswelt wird die Frage, ob Modelle als vage oder
präzise Spezifikationen zu verstehen sind, oft ambivalent beantwortet
und differiert auf den verschiedenen Ebenen.
9.5.2.1
Interpretation der UML-Modelle der Ebene M1
UML-Modelle der Ebene M1 werden normalerweise als vage oder unvollständige Spezifikationen verstanden. Diese Möglichkeit ist völlig
unverzichtbar. Von irrelevanten Details eines Systems zu abstrahieren
ist gerade das Grundprinzip der Modellierung.
Bei Diagrammtypen, die Verhalten modellieren, kann man meist
nicht sinnvoll oder nur mit erheblichen begrifflichen Verrenkungen definieren, was überhaupt eine Instanz des Modells sein soll und in welchen Laufzeitobjekten bzw. Realweltausschnitt sich dieses Modell manifestiert. Die Instanzbildung funktioniert bei jedem Modelltyp völlig
anders, ist weitgehend undefiniert und hängt vor allem vom Phantasiereichtum des Betrachters ab.
Da nach eigenem Bekunden die Ebene M0 kein Gegenstand der
UML ist, liegt es nahe, die Frage nach der Bedeutung der Modelle der
Ebene M1 und der “ist-Instanz-von”-Beziehungen von Ebene M0 nach
M1 als eigentlich gegenstandslos anzusehen.
UML-Modelle der Ebene M1 werden jedoch in manchen Kontexten
als Systemspezifikationen eingesetzt, z.B. zur schnellen Bereitstellung
von Wegwerf-Prototypen bei der Systemanalyse, zur Generierung von
Programmrahmen aus den Modellen oder sogar zur kompletten Realisierung des Systems (insb. beim MDA-Ansatz); die UML mutiert
dann von einer Modellierungssprache zu einer graphischen Programmiersprache.
Entscheidend ist hier die Beobachtung, daß man heimlich zu einem
anderen Systemtyp gewechselt hat. Ein GUI-Generator hat GUIs als
Nutzdaten und kann durch ein Klassendiagramm konfiguriert werden.
Ein GUI-Generator ist kein Klassendiagramm-Editor und erst recht
kein Meta-CASE-Werkzeug im obigen Sinne. Selbst wenn man einen
Klassendiagramm-Editor und einen GUI-Generator technisch in einer
Arbeitsumgebung integriert, bleiben es Werkzeuge, die ihre Nutzdaten
224
Metadaten
auf verschiedenen semantischen Ebenen haben.
9.5.2.2
Interpretation der UML-Modelle der Ebene M2
UML-Modelle der Ebene M2 sind bzgl. der Präzisionsfrage ebenfalls
ambivalent.
Die Menge der UML-Produkte, die die Conformance-Klauseln der
UML erfüllen, soll möglichst groß gehalten werden. Daher werden viele Aspekte von UML-Werkzeugen (externe Darstellung der Dokumente, Dokumentverwaltung, Prüffunktionen, Speicherformat usw.) überhaupt nicht modelliert oder durch “presentation options”, “variation
points” für die Semantik von Modellen und die Verwendung natürlicher Sprache zur Erklärung von Optionen sehr offen gehalten40 . Aus
dieser Motivation heraus sind die UML-Spezifikationen (und damit die
Modelle der Ebene M2) oft unpräzise bzw. unvollständig, im Prinzip
also vage Spezifikationen.
Andererseits werden die Modelle in manchen Systemen als präzise Spezifikationen benutzt. Solche Werkzeuge werden allgemein als
Meta-CASE-Werkzeuge bezeichnet.
Am bekanntesten sind hierunter graphische Editoren für netzwerkartige Modelltypen. Der Kerngedanke besteht darin, die erheblichen
Gemeinsamkeiten, die Editoren für netzwerkartige Modelltypen aufweisen, in einem generischen Kern zu implementieren41 und diesen
Kern mit einem konzeptuellen Modell der jeweiligen Modelltypen, also deren Metamodell, zu konfigurieren. Über die Modellkonzepte hin40
Die Conformance Level der UML verkomplizieren die Thematik hier zusätzlich.
Die Conformance Level ermöglichen es, nur eine Teilmenge aller Dokumenttypen in
einem standardkonformen Produkt zu unterstützen und unterschiedlich gute architektonische Merkmale (Konfigurier- bzw. Erweiterbarkeit) anzubieten. Für die hier
diskutierten Fragen sind die Conformance Level irrelevant, denn die Frage nach der
Bedeutung der Spezifikationen ist weitgehend unabhängig davon, ob der komplette
Standard oder nur eine Teilmenge abgedeckt wird.
41
Hierbei wird man i.d.R. die gemäß dem Standard zulässige Vielfalt der Implementierungen substantiell einschränken, bei Wahlmöglichkeiten also entweder
eine konkrete Wahl treffen und diese hart im generischen Kern der Werkzeuge verdrahten oder mehrere Wahlmöglichkeiten realisieren und durch werkzeugspezifische
Konfigurationsparameter wählbar machen.
Metadaten
225
aus müssen indessen auch Darstellungsformen von Diagrammelementen abhängig vom jeweiligen Modelltyp konfiguriert werden können;
dies macht die Konfigurierung von Meta-CASE-Werkzeugen deutlich
komplizierter als die “Konfiguration” eines DBMS mittels eines Schemas.
Weitere Meta-CASE-Werkzeuge sind Transformatoren, die Modelle
in andere Modelle, Programmrahmen o.ä umformen, Prüfwerkzeuge,
Differenzbildungs- und Mischwerkzeuge, Export- oder Importwerkzeuge u.a.m. Auch für diese gilt analog zu Editoren, daß das Metamodell
eines Modelltyps i.a. nicht ausreicht, um den generischen Kern des
Meta-CASE-Werkzeugs zu konfigurieren, sondern daß zusätzliche dokumenttypspezifische Konfigurationsdaten benötigt werden.
Glossar
Metadaten (meta data): Daten über Daten; im Kontext von DBS vor
allem Schemata bzw. Typdefinitionen
Meta-Metadaten (meta meta data): Daten über Metadaten; insb. eine
selbstreferentielle Repräsentation des Metaschemas
Metaschema (meta schema): Schema, das zur Speicherung von Metadaten
(insb. Schemata und Typdefinitionen) benutzt wird
Nutzdaten: die in einem System verwalteten “primären” Daten (ohne die
Metadaten)
Selbstreferentialität: Ansatz, die Metadaten in einem DVS wie Nutzdaten
darzustellen
Typ-Annotationen: in die Nutzdaten eingebettete Angaben zum Typ der
Daten, Beispiel: tags in XML
Lehrmodul 10:
Entwurf redundanzfreier
Datenbankschemata
Zusammenfassung dieses Lehrmoduls
Beim Entwurf von Schemata für relationale Datenbanken können
bestimmte Fehler gemacht werden, die entweder zu Redundanz oder
zu einer inkorrekten Wiedergabe der Realität führen. Wir analysieren
diese Entwurfsfehler genauer und definieren bestimmte Kriterien, die
derartige Entwurfsfehler ausschließen. Diese Kriterien werden auch
als Normalformen bezeichnet. Ein zentraler Begriff bei der Definition
der Kriterien ist der der funktionalen Abhängigkeit, der den Begriff
Identifizierungsschlüssel verallgemeinert.
Vorausgesetzte Lehrmodule:
obligatorisch:
– Das relationale Datenbankmodell
Stoffumfang in Vorlesungsdoppelstunden:
Stand: 20.10.2005
3.0
c
2005
Udo Kelter
Entwurf redundanzfreier Datenbankschemata
10.1
227
Einleitung und Einordnung
Der Entwurf relationaler Datenbankschemata ist eine Tätigkeit, die
man im Rahmen der Entwicklung eines Informationssystems am ehesten zur Entwurfsphase zählen kann (wenn wir das Phasenmodell unterstellen). Ausgangsbasis ist somit ein Datenmodell, das in der Analysephase gewonnen wurde, z.B. in Form eines ER- oder OOA-Modells.
Das zu erstellende Datenbankschema kann man als wichtige persistente Datenstruktur innerhalb der Gesamtarchitektur des Informationssystems ansehen; häufig findet sich auch programmseitig eine äquivalente oder ähnliche Datenstruktur bzw. ein entsprechendes Modul (vgl.
[TAE]).
Für die Transformation von Datenmodellen in Tabellen gibt es Vorgehensweisen, die trotz punktueller Entscheidungsfreiräume insg. doch
relativ schematisch ablaufen (s. Abschnitt 2 in [TAE]). Die Frage
drängt sich auf, wo denn überhaupt noch ein Problem ist, das ein umfangreiches Lehrmodul rechtfertigt. Die Antwort ist, daß man die Schemata falsch entwerfen kann; Effekte dieser Fehler können sein:
– redundant gespeicherte Daten42
– Datenverluste und falsche Abbildung der Realität in der Datenbank
Man kann nun argumentieren, daß ein solcher Fehler in einem Datenbankschema (a) vermutlich schon in dem zugrundeliegenden Datenmodell vorlag, also nicht erst bei der Transformation des Datenmodells
in das Schema verursacht worden ist, und daß man (b) den Fehler doch
lieber gleich im Datenmodell vermeiden sollte. Die Antwort auf (a) ist:
völlig richtig. Zu (b): Im Prinzip richtig, aber dieser Vorschlag kann
in der Praxis problematisch sein. Die Feststellung, ob ein Fehler vorliegt, erfordert ein gewisses Maß an mathematischem Denkvermögen,
42
Unter Datenbänklern ist es ein fester Glaubensgrundsatz, daß redundante Datenspeicherung (in einer nichtverteilten Datenbank) etwas ganz Schlimmes sei. Dieser Glaube stammt aus einer Zeit, als die Kapazität von Platten nach heutigen
Maßstäben winzig und die Preise pro MB Plattenplatz astronomisch waren, man
also sehr gute Gründe hatte, keinen Platz zu verschwenden. Heute ist dieses Argument außer bei sehr großen Datenmengen nicht mehr gravierend. Aber auch ohne
dieses Argument ist eine redundante Speicherung grundsätzlich unmotiviert, und
wir werden später noch konkrete Nachteile identifizieren.
228
Entwurf redundanzfreier Datenbankschemata
und die Behebung des Fehlers kann die Datenmodelle unanschaulicher
machen. Da Datenmodelle vor allem für Anwender intuitiv verständlich sein sollen, kann insb. der zweite Punkt ein Nachteil sein. Die
gute Nachricht an dieser Stelle ist, daß solche Fehler eigentlich selten sind, weil man mit etwas “Erfahrung” die Datenmodelle intuitiv
richtig entwirft.
Ziel dieses Lehrmoduls ist es daher, diese Erfahrung zu vermitteln
und Definitionen und Algorithmen zu präsentieren, mit denen man das
Vorliegen von Fehlern tatsächlich entdecken und diese durch Umbau
der Schemata beseitigen kann.
Historisch gesehen sind “Korrektheitsbegriffe” für Schemata im
Kontext von Datenbanken entstanden, und zwar unter der wenig anschaulichen Bezeichnung “Normalformen”. Es ist eine sehr umfangreiche Theorie der Normalformen entstanden. Man kann diese Theorie
im Prinzip problemlos auf die Datenmodelle der Analysephase übertragen, was aber nicht üblich ist43 .
10.2
Fehler beim Entwurf relationaler Datenbankschemata
Wir beschreiben zunächst typische Fehler, die in relationalen Datenbankschemata auftreten können, und deren Konsequenzen. Als Beispiel benutzen wir die beiden Relationen kunden und lieferungen aus
Lehrmodul 4 bzw. Varianten dieser Relationen.
10.2.1
Zu viele Attribute in einem Relationentyp
Als Beispiel betrachten wir eine Relation kundenlieferungen, die folgenden Relationentyp hat:
Kundenlieferungen = ( Datum: date;
Wert: real;
Kundennummer: string;
43
Über die Ursachen kann man nur spekulieren.
Gründe sind sicher nicht alleine ausschlaggebend.
Die o.g. anwenderseitigen
Entwurf redundanzfreier Datenbankschemata
229
Kundenname: string;
Wohnort: string;
Kreditlimit: real;
Lager: integer;
Lieferadresse: string; )
Tabelle: kundenlieferungen
Datum
Wert
Kunden- Kundenname
nummer
00-08-12 2730.00 167425 Schneider, P...
00-08-14
427.50 167425 Schneider, P...
00-08-02 1233.00 171876 Litt, Michael
Wohnort
Netphen
Netphen
Siegen
Kreditlimit
14000.00
14000.00
0.00
Abbildung 10.1: Beispieltabelle für Lieferungen an Kunden
Bild 10.1 zeigt die zugehörige Relation kundenlieferungen mit einigen Beispieltupeln. Die Relation kundenlieferungen soll die beiden Relationen kunden und lieferungen ersetzen. In der Relation
lieferungen ist das Attribut Kundennummer ergänzt worden durch
die drei Attribute Kundenname, Wohnort und Kreditlimit.
Ein Tupel in der Relation kundenlieferungen faßt alle Angaben
zu einer Lieferung und dem belieferten Kunden zusammen, was u.U.
als ganz praktisch erscheint. Dieser Relationentyp führt allerdings zu
erheblichen Problemen:
– Die Angaben über den Kunden müssen bei jeder Lieferung erneut
gespeichert werden. Hieraus ergeben sich folgende Probleme:
1. redundante Datenspeicherung
2. Gefahr von Inkonsistenzen: bei jeder erneuten Lieferung an einen
schon vorhandenen Kunden müssen erneut dessen Daten eingegeben werden; aus Versehen können aber abweichende Daten
eingegeben werden, so daß dann die Daten zu diesem Kunden
nicht konsistent sind.
3. die “Änderungsanomalie”: Wenn wir z.B. das Kreditlimit eines Kunden verändern, muß das entsprechende Attribut in al-
...
...
...
...
230
Entwurf redundanzfreier Datenbankschemata
len Tupeln dieses Kunden modifiziert werden. M.a.W. führt die
Änderung eines einzigen Sachverhalts dazu, daß an n > 1 Tupeln
Änderungen vorgenommen werden müssen.
– Wenn wir einen neuen Kunden erfassen wollen, der aber noch nichts
geliefert bekommen hat, haben wir ein Problem (die “Einfügeanomalie”): Wenn wir ein Tupel mit den Kundendaten erzeugen
wollen, müssen wir für die eigentlichen Lieferungsdaten Nullwerte
einsetzen. Nullwerte sind in vieler Hinsicht sehr störend (s. Lehrmodul 6).
– Wenn umgekehrt das letzte Lieferungstupel zu einem Kunden
gelöscht wird, gehen auch die Daten über den Kunden selbst verloren. Hier liegt eine “Löschanomalie” vor.
Insgesamt muß man hier feststellen, daß beim Relationentyp
Kundenlieferungen zu viele Attribute zusammengefaßt worden sind
– dieser Relationentyp ist sozusagen zu “groß” – und daß dies zu
Redundanz, Nullwerten, Informationsverlusten und Anomalien beim
Einfügen, Ändern und Löschen von Tupeln führt.
10.2.2
Zu “kleine” Relationentypen
Ausgehend vom Problem zu großer Relationentypen könnte man im
Umkehrschluß zur Meinung kommen, daß man lieber nur sehr kleine
Gruppen von Attributen zu Relationen zusammenfaßt. Wir verwenden
wieder die Attribute aus dem Relationentyp Lieferungen und bilden
nunmehr zwei kleinere Relationentypen:
Lieferungen1 = ( Datum: date;
Wert: real;
Kundennummer: string; )
Lieferungen2 = ( Kundennummer: string;
Lager: integer;
Lieferadresse: string; )
Die entsprechenden Relationen Lieferungen1 und Lieferungen2
bilden wir, indem wir Lieferungen auf die jeweiligen Attributmengen
Entwurf redundanzfreier Datenbankschemata
231
projizieren:
lieferungen1 = πDatum,Wert,Kundennummer (lieferungen)
lieferungen2 = πKundennummer,Lager,Lieferadresse (lieferungen)
Die Ergebnisse dieser Projektionen sehen folgendermaßen aus:
Tabelle: lieferungen1
Datum
Wert
Kundennummer
00-08-12 2730.00 167425
00-08-14
427.50 167425
00-08-02 1233.00 171876
Tabelle: lieferungen2
Kunden- Lager Lieferadresse
nummer
167425
Mitte Bahnhofstr. 5
167425
Nord
Luisenstr. 13
171876
West
Bergstr. 33
Wenn wir nun unsere Daten nur noch in den Tabellen lieferungen1 und lieferungen2 speichern, so sollten wir dennoch in der Lage
sein, die ursprüngliche Tabelle lieferungen wieder zu rekonstruieren,
naheliegenderweise als Verbund lieferungen1 1 lieferungen2. Das
Ergebnis dieser Verbundbildung ist:
Tabelle: lieferungen1 1 lieferungen2
Datum
Wert
Kundennummer Lager
00-08-12 2730.00
167425
Mitte
00-08-14
427.50
167425
Nord
00-08-12 2730.00
167425
Nord
00-08-14
427.50
167425
Mitte
00-08-02 1233.00
171876
West
Lieferadresse
Bahnhofstr. 5
Luisenstr. 13
Luisenstr. 13
Bahnhofstr. 5
Bergstr. 33
Dies ist nicht mehr die ursprüngliche Relation lieferungen! Das
3. und 4. Tupel sind neu hinzugekommen. Diese wundersame Tupelvermehrung wird dadurch verursacht, daß der Verbund über das
Verbundattribut Kundennummer gebildet wird, bei diesem Attribut der
Wert 167425 in zwei Tupeln auftritt und die “linke” und “rechte Hälfte” der beiden ursprünglichen Tupel beliebig miteinander kombiniert
werden.
Angenommen, die beiden neuen Tupel wären doch in der ursprünglichen Datenbank enthalten, dann hätte dies auf beiden Relationen
232
Entwurf redundanzfreier Datenbankschemata
lieferungen1 und lieferungen2 keinerlei Einfluß, diese Unterschiede
in lieferungen gehen beim Projizieren verloren. Die korrekte Relation lieferungen ist deshalb i.a. aus dem Inhalt der Datenbank nicht
mehr rekonstruierbar, die Datenbank gibt also die Realität nicht mehr
korrekt wieder. Die obige Zerlegung des Relationentyps Lieferungen
und der zugehörigen Relation lieferungen führt also zum Verlust
der Korrektheit der Datenbank und wird daher als verlustbehaftet
bezeichnet. Irritierenderweise gehen bei einer verlustbehafteten Zerlegung keine Tupel verloren, sondern es kommen allenfalls welche hinzu
(“Datenmüll”); leider weiß man nicht, welche.
10.2.3
Verlustfreie Zerlegungen
Eine nicht verlustbehaftete Zerlegung nennen wir verlustfrei. Ein
Beispiel für eine verlustfreie Zerlegung ist die Zerlegung unseres
früheren Relationentyps Kundenlieferungen in die Relationentypen
Kunden und Lieferungen. Allgemein ist die Verlustfreiheit von Zerlegungen wie folgt definiert:
Definition: Sei R ein Relationentyp, Ri , 1 ≤ i ≤ n, Attributmengen.
S
{R1 , ..., Rn } heißt Zerlegung von R, falls R = ni=1 Ri
Definition: Sei {R1 , ..., Rn } Zerlegung von R. Die Zerlegung ist verlustfrei ⇐⇒ für jede “korrekte” Relation44 r gilt:
r = 1ni=1 πRi (r)
Zerlegungen beziehen sich im Prinzip auf Relationentypen; wir werden den Begriff aber oft auch auf eine Relation r anwenden und meinen
dann die Projektionen πRi (r).
Da bei einer Zerlegung einer Relation und anschließendem Verbund
der Projektionen πRi (r) keine der ursprünglichen Tupel verlorengehen,
gilt folgender Satz:
44
Korrekte Relation soll hier bedeuten, daß die Relation den Konsistenzkriterien
der Anwendung genügt. Später werden wir den Begriff Korrektheit noch präziser
fassen.
Entwurf redundanzfreier Datenbankschemata
233
Satz: Sei {R1 , ..., Rn } Zerlegung von R, r eine Relation mit Relationentyp R. Dann gilt:
r ⊆ 1ni=1 πRi (r)
Zum Beweis dieser Behauptung nehme man ein Tupel t ∈ r an. t wird
durch die Zerlegung in mehrere, möglicherweise überlappende Teile
t[Ri ] zerlegt. Bei der Bildung des Verbunds werden diese Teile wieder
zu dem ursprünglichen Tupel t zusammengesetzt.
10.3
Funktionale Abhängigkeiten
10.3.1
Beispiel und Definition
Wir kommen noch einmal auf unser Beispiel für eine verlustfreie Zerlegung zurück, die Zerlegung des Relationentyps Kundenlieferungen
in die Relationentypen Kunden und Lieferungen. Daß diese Zerlegung verlustfrei ist, liegt an folgendem Merkmal der Relation
kundenlieferungen: Wenn man irgendeinen Wert des Attributs
Kundennummer wählt, z.B. 167425, dann kann es mehrere Tupel geben, die diesen Wert aufweisen. Diese Tupel haben bei allen anderen
Attributen, die Kunden beschreiben (Kundenname usw.) immer den
gleichen Wert! Hieraus folgt: Die Projektion
πKunden (kundenlieferungen)
enthält für jeden auftretenden Wert von Kundennummer genau
ein Tupel, und {Kundennummer} ist Identifizierungsschlüssel in
πKunden (kundenlieferungen). Anders gesehen liegt hier eine (partielle) Funktion im mathematischen Sinne vor, die jedem Wert von
Kundennummer die Werte der anderen Kundenattribute eindeutig zuordnet. Die anderen Kundenattribute werden daher als funktional
abhängig von Kundennummer bezeichnet.
Wenn wir nun den Verbund
πLieferungen (kundenlieferungen) 1 πKunden (kundenlieferungen)
bilden, dann ist darin das Attribut Kundennummer Verbundattribut
und jedes Tupel aus πLieferungen (kundenlieferungen) wird mit ge-
234
Entwurf redundanzfreier Datenbankschemata
nau einem Tupel aus πKunden (kundenlieferungen) kombiniert. Die
störende Tupelvermehrung unterbleibt also.
Im vorigen Beispiel war jedes Kundenattribut funktional abhängig
von Kundennummer. Ein Attribut kann auch von einer Menge von
Attributen funktional abhängig sein. Die allgemeine Definition von
funktionaler Abhängigkeit ist:
Definition: Sei R ein Relationentyp und seien A, B ⊆ R zwei Attributmengen. B ist funktional abhängig von A (notiert als A → B)
⇐⇒ ∀ Relation r mit dem Relationentyp R ∀ t1, t2 ∈ r:
t1[A] = t2[A] ⇒ t1[B] = t2[B]
Übungsaufgabe:
Beweisen Sie: A ⊇ B ⇒ A → B
Funktionale Abhängigkeiten, bei denen A ⊇ B gilt, nennt man auch
trivial, denn sie sagen nichts über den Datenbestand aus.
Graphische Darstellung funktionaler Abhängigkeiten. Es ist
manchmal hilfreich, sich funktionale Abhängigkeiten graphisch zu veranschaulichen, indem man die Attribute auf einer Zeichenfläche geeignet plaziert, die beiden beteiligten Attributmengen durch eine geschlossene Linie eingrenzt und den Abhängigkeitspfeil zwischen diesen
Grenzlinien anbringt. Als Beispiel zeigt Bild 10.2 die Abhängigkeit
Kundennummer→{Kundenname, Wohnort, Kreditlimit}.
Kundenname
Kundennummer
Wohnort
Kreditlimit
Abbildung 10.2: Beispiel für die graphische Darstellung
Entwurf redundanzfreier Datenbankschemata
10.3.1.1
235
Beispiel für die Analyse einer Tabelle
Als Beispiel für die Analyse existierender Daten untersuchen wir die
folgende sehr kleine Relation mit den Attributen A, B, C und D daraufhin, welche Abhängigkeiten in ihr auftreten:
Tupel
t1
t2
t3
t4
A
a
a
b
b
B
c
d
e
e
C
f
g
g
h
D
i
j
k
l
Bei der Analyse suchen wir zunächst nach Abhängigkeiten zwischen
einzelnen Attributen, die also die Form X → Y haben (wir benutzen
die Schreibweise X für die Menge {X}). Bei 4 Attributen ergeben sich
im Prinzip 16 Möglichkeiten, von denen 4 trivial sind (X → X). Die
Ergebnisse sind in der folgenden Tabelle angegeben. Ein + bedeutet,
daß das zur Spalte gehörende Attribut funktional von dem zur Zeile
gehörenden Attribut abhängt. Ein - bedeutet das Gegenteil, wobei
dann noch ein Paar von Tupeln angegeben ist, das der funktionalen
Abhängigkeit widerspricht. Bei trivialen Abhängigkeiten steht ein *.
→
A
B
C
D
A
*
+
- (t2,t3)
+
B
- (t1,t2)
*
- (t2,t3)
+
C
- (t1,t2)
- (t3,t4)
*
+
D
- (t1,t2)
- (t3,t4)
- (t2,t3)
*
Als nächstes untersuchen wir Abhängigkeiten von 2 Attributen,
die also die Form XY → Z haben (wir benutzen die Schreibweise XY
für die Menge {X, Y}). Einige Abhängigkeiten werden impliziert durch
Abhängigkeiten von einem Attribut; dies ist dann in Klammern hinter dem + vermerkt. Wir erkennen, daß nur AC→B, AC→D und BC→D
wirklich neue Abhängigkeiten sind.
236
Entwurf redundanzfreier Datenbankschemata
→
AB
AC
AD
BC
BD
CD
A
*
*
*
+ (B→A)
+ (B→A)
+ (D→A)
B
*
+
+ (D→B)
*
*
+ (D→B)
C
- (t3,t4)
*
+ (D→C)
*
+ (D→C)
*
D
- (t3,t4)
+
*
+
*
*
Zum Schluß untersuchen wir noch Abhängigkeiten der Form XYZ
→ U; hier sind keine Abhängigkeiten wirklich neu:
→
ABC
ABD
ACD
BCD
10.3.1.2
A
*
*
*
+ (D→A)
B
*
*
+ (D→B)
*
C
*
+ (D→C)
*
*
D
+ (AC→D)
*
*
*
Identifizierungs- und Superschlüssel
Die mit Abstand häufigste Form funktionaler Abhängigkeiten sind
Schlüssel. Wenn K ⊆ R ein Identifizierungs- oder Superschlüssel ist,
dann gilt offensichtlich
K→R
Identifizierungs- und Superschlüssel sind also spezielle funktionale
Abhängigkeiten, der Begriff funktionale Abhängigkeit ist eine Verallgemeinerung des Begriffs Superschlüssel.
Die inhaltliche Nähe beider Begriffe zeigt sich auch in folgendem:
A → B impliziert, daß in der Relation πA∪B (r) die Attributmenge A
Superschlüssel ist.
10.3.2
Funktionale Abhängigkeiten als Integritätsbedingungen
Bisher noch offen ist die Frage, wie man funktionale Abhängigkeiten erkennt und wieso sie überhaupt auftreten. Daß in unserer Beispielrelation kundenlieferungen die funktionale Abhängigkeit Kundennummer
Entwurf redundanzfreier Datenbankschemata
237
→ Kunden auftrat, ist offenbar kein Zufall. Daß jeder Kundennummer eindeutige Kundendaten zugeordnet werden, wollen wir so, dies
ist in unserem Beispiel eine Anforderung, die sich aus der Analyse der
Anwendung ergibt, und nicht eine temporäre Erscheinung, die zufällig
gerade im aktuellen Inhalt der Relation auftritt und durch Einfügen
weiterer Tupel wieder verlorengehen kann.
Funktionale Abhängigkeiten sind somit Integritätsbedingungen, die
im Rahmen der Systemanalyse festgestellt werden, noch bevor überhaupt die Relation angelegt und mit Tupeln gefüllt worden ist. Trotzdem kann es im Einzelfall durchaus sinnvoll sein, vorhandene Datenbestände oder verfügbare Beispieldaten daraufhin zu analysieren,
ob funktionale Abhängigkeiten auftreten, und bei den gefundenen
Abhängigkeiten zu fragen, ob sie Zufall sind oder nicht.
Funktionale Abhängigkeiten sind daher als Teil des Datenbankschemas anzusehen. Wenn wir diesen Sachverhalt betonen wollen,
werden wir für Relationentypen die alternative Notation (R, F ) benutzen. Darin ist R wie bisher die Menge der Attribute; F ist die
Menge der funktionalen Abhängigkeiten.
Festzuhalten bleibt, daß es Aufgabe eines Informationssystems ist,
sicherzustellen, daß der aktuelle Datenbestand die Integritätsbedingungen stets einhält, also in diesem Sinne korrekt ist. Gefährdet sind
funktionale Abhängigkeiten nur beim Einfügen neuer Tupel, Löschungen von Tupeln können keinen Schaden anrichten; eine Änderung betrachten wir hier als eine Abfolge von Löschung und Einfügung. Immer dann, wenn ein neues Tupel eingefügt werden soll, muß geprüft
werden, ob hierdurch eine funktionale Abhängigkeit verletzt werden
würde. Diese Prüfung muß innerhalb eines Informationssystems entweder von der Applikation oder vom DBMS übernommen werden. Auf
diese Frage kommen wir später wieder zurück.
10.3.3
Verlustfreie Zerlegungen
Wir kommen an dieser Stelle noch einmal auf den Begriff verlustfreie
Zerlegung zurück. Wir hatten diesen Begriff schon in Abschnitt 10.2.3
definiert, allerdings unter Verwendung des nur informell definierten Be-
238
Entwurf redundanzfreier Datenbankschemata
griffs “korrekte Relation” (s.o.). Eine Relation können wir nun präziser als korrekt definieren, wenn in ihr die funktionalen Abhängigkeiten
eingehalten werden. In diesem Fall können wir die Verlustfreiheit einer
Zerlegung wie folgt definieren:
Definition: Sei {R1 , R2 } Zerlegung von R, F die Menge der für R
gültigen funktionalen Abhängigkeiten. Die Zerlegung ist verlustfrei
⇐⇒ F impliziert
R1 ∩R2 →R1 oder R1 ∩R2 →R2
Die Bedingung besagt, daß R1 ∩R2 Superschlüssel von R1 oder R2
sein muß. R1 ∩R2 sind gerade die Verbundattribute, über die Projektionen πR1 (r) und πR2 (r) einer Relation r wieder verbunden werden
können. Für jede einzelne Wertekombination dieser Verbundattribute
kann wegen der Superschlüsseleigenschaft in πR1 (r) oder πR2 (r) nur
ein passendes Tupel, das als Verbundpartner dienen kann, vorhanden
sein. Neue Tupel können daher durch Zerlegung und anschließenden
Verbund nicht entstehen, die Zerlegung ist somit verlustfrei.
Als Beispiel für eine verlustfreie Zerlegung sei wieder auf Abschnitt
10.3.1 verwiesen. Dort war das Attribut Kundennummer sogar Identifizierungsschlüssel in πKunden (kundenlieferungen).
10.3.4
Die Armstrong-Axiome
Aus dem Beispiel in Abschnitt 10.3.1.1 läßt sich die Erkenntnis gewinnen, daß die Gesamtzahl der funktionalen Abhängigkeiten groß werden kann, daß aber die meisten entweder trivial sind oder aus anderen
Abhängigkeiten folgen.
Wir haben oben ohne weiteren Beweis behauptet, daß z.B. aus A→B
auch AC→B folgt. Diese Behauptung können wir aber durch Einsetzen
der Definitionen schnell beweisen. (Übung!) Derartige Beweise immer
im Einzelfall zu führen ist aber zu aufwendig. Stattdessen kann man
direkt die folgenden sogenannten Armstrong-Axiome benutzen, die
eine kalkülartige Ableitung von neuen funktionalen Abhängigkeiten
aus vorhandenen ermöglichen. X, Y und Z sind i.f. beliebige Attributmengen eines Relationentyps R.
Entwurf redundanzfreier Datenbankschemata
239
Reflexivitätsregel: X ⊇ Y ⇒ X→Y
Erweiterungsregel: X→Y ⇒ X ∪ Z→Y ∪ Z
Transitivitätsregel: X→Y ∧ Y→Z ⇒ X→Z
Bild 10.3 veranschaulicht die Armstrong-Axiome in einer graphischen Darstellung. Zur Vereinfachung wurde bei der Erweiterungsregel
und der Transitivitätsregel angenommen, daß die beteiligten Attributmengen disjunkt sind. Die Regeln gelten natürlich auch ohne diese
Annahme.
Reflexivitätsregel
X
Y
Erweiterungsregel
X
Z
Z
X
Y
Y
Transitivitätsregel
X
Y
Z
X
Z
Abbildung 10.3: Graphische Darstellung der Armstrong-Axiome
Ein Beispiel für den Einsatz der Regeln findet sich im letzten Abschnitt: dort haben wir u.a. behauptet, daß die Abhängigkeit ACD→B
aus der Abhängigkeit A→B folgt. Beweisen können wir diese Behauptung nun wie folgt:
1. ACD→BCD
2. BCD→B
(folgt aus A→B mittels Erweiterungsregel mit Z = CD)
(wegen Reflexivitätsregel)
240
3. ACD→B
Entwurf redundanzfreier Datenbankschemata
(folgt aus 1. und 2. wegen Transitivitätsregel)
Die Reflexivitätsregel ist nur eine andere Formulierung unserer
früheren Behauptung, daß triviale Abhängigkeiten immer gelten. Die
Erweiterungsregel und die Transitivitätsregel können ebenfalls durch
Einsetzen der Definitionen leicht bewiesen werden. Dies zeigt die Korrektheit der Axiome.
Die vorstehende Menge an Axiomen ist außerdem vollständig in
dem Sinne, daß alle ableitbaren Abhängigkeiten durch Verwendung
der Axiome herleitbar sind.
Die folgenden drei zusätzlichen Axiome sind aus den vorstehenden
ableitbar, bringen also qualitativ nichts Neues, vereinfachen aber oft
die Ableitungen (s. auch Bild 10.4):
Vereinigungsregel
X
Y
Y
X
X
Z
Z
Zerlegungsregel
Y
X
Y
Z
X
Z
X
Pseudotransitivitätsregel
W
W
Z
Z
X
Y
X
Abbildung 10.4: Zusätzliche Axiome
Vereinigungsregel: X→Y ∧ X→Z ⇒ X→Y ∪ Z
Entwurf redundanzfreier Datenbankschemata
241
Zerlegungsregel: X→Y ∪ Z ⇒ X→Y ∧ X→Z
Pseudotransitivitätsregel: W ∪ Y→Z ∧ X→Y ⇒ W ∪ X→Z
Die Pseudotransitivitätsregel bedeutet bildlich gesprochen, daß
man in einer vorhandenen Abhängigkeit Voraussetzungen (die Attribute Y) durch stärkere Voraussetzungen (die Attribute X) ersetzen kann.
10.3.5
Die transitive Hülle einer Menge funktionaler
Abhängigkeiten
Bei der Systemanalyse steht man im Prinzip vor dem Problem, alle
funktionalen Abhängigkeiten zu erfassen; später sind geeignete Maßnahmen zur Überwachung der Abhängigkeiten zu installieren, die
natürlich möglichst wenig Aufwand verursachen sollen.
Bei der Erfassung der funktionalen Abhängigkeiten einer Applikation stehen wir vor dem Problem, daß i.a. nur eine vom Zufall abhängige
Teilmenge aller Abhängigkeiten notiert werden wird; einige der implizierten Abhängigkeiten werden fehlen. Jemand anders, der die gleiche
Anwendung analysiert, käme vielleicht auf eine etwas anders zusammengesetzte Menge von Abhängigkeiten, die aber dennoch “äquivalent” zu der ursprünglichen wäre.
Bzgl. der Überwachung der Abhängigkeiten besteht eine entscheidende Beobachtung darin, daß man abgeleitete Abhängigkeiten
nicht mehr zu überwachen braucht, wenn man die vorausgesetzten
Abhängigkeiten überwacht! Offensichtlich läßt sich der Gesamtaufwand für die Überwachung aller Abhängigkeiten minimieren, indem
man nur eine minimale Menge von nicht mehr ableitbaren Abhängigkeiten überwacht, die die restlichen impliziert. Eine solche minimale
Menge ist äquivalent zur Ausgangsmenge.
Wichtig ist in beiden Fällen der Begriff der Äquivalenz zweier Mengen von Abhängigkeiten. Definitionstechnisch gehen wir so vor, daß
wir zunächst zu einer gegebenen Menge von Abhängigkeiten die sog.
transitive Hülle, die alle ableitbaren Abhängigkeiten enthält, definieren.
242
Entwurf redundanzfreier Datenbankschemata
Definition: Sei F eine Menge funktionaler Abhängigkeiten. Die
transitive Hülle F + (closure) von F ist die Menge aller ableitbaren funktionalen Abhängigkeiten (incl. F ).
Definition: Seien F und G zwei Mengen funktionaler Abhängigkeiten. F und G sind äquivalent (G ≈ F ), wenn G+ = F + ist.
Definition: Sei X ⊆ R eine Attributmenge und F eine Menge funktionaler Abhängigkeiten. X+ ist die Menge der Attribute, die bei F
direkt oder indirekt abhängig von X sind. M.a.W. ist X→X+ ∈ F + .
Die Mengen X+ sind sehr nützlich. Z.B. kann man mit ihnen feststellen, ob eine Attributmenge ein Superschlüssel ist. X ist genau dann
ein Superschlüssel, wenn X+ = R.
Die Berechnung von X+ betrachten wir zunächst an einem Beispiel.
Sei R = {A, B, C, D, E}, F = {A→B, BC→D, E→D}. Gesucht ist AC+ .
Wir gehen wie folgt vor: Sei Z die Menge der Attribute, von denen wir
schon wissen, daß sie von AC abhängen.
1. Initial sei Z = AC. Hier nutzen wir die Reflexivitätsregel aus.
2. Wir untersuchen nun, ob eine der funktionalen Abhängigkeiten anwendbar ist, um Z zu vergrößern. Dies ist bei solchen Abhängigkeiten X→Y der Fall, für die X ⊆ Z gilt.
BC→D und E→D sind derzeit nicht anwendbar. A→B ist anwendbar, wir können also B in Z aufnehmen, also Z = ABC.
3. Dadurch, daß Z größer geworden ist, können bisher nicht anwendbare Abhängigkeiten anwendbar geworden sein. Wir untersuchen
daher die bisher noch nicht angewandten Abhängigkeiten, ob sie
nunmehr angewandt werden können.
E→D ist immer noch nicht anwendbar. BC→D ist jetzt anwendbar geworden, da BC ⊆ Z. Wir nehmen also D in Z auf, somit Z =
ABCD.
Entwurf redundanzfreier Datenbankschemata
243
4. Weil Z wieder größer geworden ist, untersuchen wir erneut die noch
nicht angewandten Abhängigkeiten. E→D ist weiterhin nicht anwendbar. Da wir keine neuen anwendbaren Abhängigkeiten gefunden haben, sind wir fertig. AC+ = ABCD ist das Endergebnis.
Allgemein kann X+ mit folgendem Algorithmus berechnet werden.
Gegeben sind X und F . Z und Z1 sind temporäre Variablen, die eine
Attributmenge enthalten.
Z := X;
Z1 := ∅;
WHILE Z1 6= Z DO
Z1 := Z;
FOREACH X→Y ∈ F DO
IF X ⊆ Z THEN Z := Z ∪ Y;
X+ := Z;
10.3.6
Kanonische Überdeckung von funktionalen Abhängigkeiten
Wie schon erwähnt möchte man aus Aufwandsgründen nicht alle
funktionalen Abhängigkeiten kontrollieren, sondern nur eine minimale
Menge, die keine ableitbaren Abhängigkeiten mehr enthält. Zu einer
gegebenen Menge von funktionalen Abhängigkeiten F suchen wir daher eine Menge Fc mit folgenden Eigenschaften.
1. F ≈ Fc
2. Fc ist linksminimal: Die Abhängigkeiten in Fc enthalten auf der
linken Seite keine überflüssigen Attribute, d.h. wenn man in einer
Abhängigkeit auf der linken Seite ein Attribut entfernt, ist die neue
Menge nicht mehr äquivalent zu F :
∀ X→Y ∈ Fc , A ∈ X : (Fc − {X→Y} ∪ {X-{A}→Y})+ 6= F +
3. Fc ist rechtsminimal: auch die rechten Seiten der Abhängigkeiten
dürfen keine überflüssigen Attribute enthalten:
∀ X→Y ∈ Fc , A ∈ Y : (Fc − {X→Y} ∪ {X→Y-{A}})+ 6= F +
244
Entwurf redundanzfreier Datenbankschemata
Wenn Fc diese Eigenschaften hat, ist es eine kanonische Überdeckung von F .
Aus der Rechtsminimalität ergibt sich, daß Fc keine überflüssigen
Abhängigkeiten enthält, d.h. für jede Abhängigkeit X→Y ∈ Fc gilt:
(Fc − {X→Y})+ 6= F + .
Beim Umgang mit kanonischen Überdeckungen sind zwei normierte Darstellungen für Mengen von Abhängigkeiten nützlich:
1. Einelementige rechte Seiten der Abhängigkeiten: Hier müssen alle Abhängigkeiten die Form X→A, A ∈ R, haben. Mittels der
Zerlegungsregel können wir eine anders geformte Abhängigkeit
X→{A1 ,..,An} in einzelne Abhängigkeiten X→Ai zerlegen. F =
{A→BC} würde also in {A→B, A→C} umgeformt werden.
2. Eindeutige linke Seiten: Hier fassen wir unter Ausnutzung der Vereinigungsregel alle Abhängigkeiten mit gleicher linker Seite zu einer
einzigen zusammen.
Formal erhalten wir durch die Umformungen, die für eine normierte Darstellung erforderlich sind, natürlich eine andere Menge von
Abhängigkeiten; inhaltlich sind diese Umformungen aber unerheblich,
weswegen wir vereinfachend von einer anderen Darstellung der gleichen
Menge sprechen.
Der Begriff kanonische Überdeckung wird manchmal so definiert,
daß neben der Minimalität auch eine der beiden normierten Darstellungsformen verlangt wird.
Um nun zu einer vorgegebenen Menge F eine kanonische Überdeckung zu berechnen, prüfen wir wiederholt die obigen Bedingungen
2 und 3 und entfernen ggf. überflüssige Abhängigkeiten oder Attribute. Hierzu müßten wir nach der obigen Definition jeweils die transitive
Hülle von F und der veränderten Menge von Abhängigkeiten bilden
und vergleichen, was unnötig aufwendig ist, es reicht ein einfacherer
Test, der von der Seite abhängt, auf der wir das Attribut entfernen:
– Wenn wir auf der linken Seite einer Abhängigkeit X→Y ein Attribut
A weglassen, ist die neue Abhängigkeit X-{A}→Y eine “stärkere”
Entwurf redundanzfreier Datenbankschemata
245
Aussage, denn wir können aus X-{A}→Y wieder X→Y ableiten. Es
gilt also automatisch
(F − {X→Y} ∪ {X-{A}→Y})+ ⊇ F +
Die umgekehrte Mengeninklusion gilt nicht automatisch, d.h. wir
müssen explizit zeigen, daß die neue Abhängigkeit X-{A}→Y aus F
abgeleitet werden kann.
– Wenn wir auf der rechten Seite einer Abhängigkeit X→Y ein Attribut A weglassen, fällt diese Abhängigkeit komplett weg, falls Y =
{A}. Wenn wir die normierte Darstellung mit einelementigen Mengen auf den rechten Seiten unterstellen, brauchen wir nur diesen
Fall zu betrachten. Wir müssen also nur noch
(F − {X→Y})+ = F +
zeigen. Die Mengeninklusion “⊆” ist offensichtlich, zu zeigen bleibt
die Inklusion “⊇” bzw. X→Y ∈ (Fc − {X→Y})+ . Mit anderen Worten muß die ursprüngliche Abhängigkeit X→Y aus den restlichen
Abhängigkeiten folgen.
Als Beispiel für die Berechnung einer kanonischen Überdeckung
behandeln wir die Menge F , die in der ersten Spalte der folgenden
Tabelle angegeben ist:
F
AB→BC
A→BC
B→A
B→AC
BC→AC
C→AB
Fc1
AB→B
AB→C
A→B
A→C
B→A
B→C
BC→A
BC→C
C→A
C→B
A→B
A→C
B→A
B→C
C→A
C→B
Fc2
A→B
A→C
B→C
B→A
B→C
C→A
C→B
C→B
246
Entwurf redundanzfreier Datenbankschemata
Als erstes formen wir die Menge um in ihre normierte Darstellung mit
einelementigen rechten Seiten (s. Spalte 2). Duplikate, hier z.B. B→A,
werden dabei eliminiert.
Als zweites entfernen wir alle trivialen Abhängigkeiten, hier AB→B
und BC→C.
Dann suchen wir Abhängigkeiten mit gleicher rechter Seite. Wir
finden hier z.B. AB→C und A→C. AB ist eine Obermenge von A. Aus
A→C ist AB→C ableitbar, wir können daher AB→C entfernen. Analog verfahren wir mit BC→A und C→A. Es verbleiben nun noch die
Abhängigkeiten in der 3. Spalte der obigen Tabelle.
Wir suchen nunmehr nach transitiven Abhängigkeiten. A→B wird
durch A→C und C→B impliziert, wird also entfernt. B→A wird durch
B→C und C→A impliziert, wird also ebenfalls entfernt. Es verbleiben
die Abhängigkeiten gemäß der Spalte Fc1 der Tabelle; von diesen ist
keine mehr überflüssig.
Wenn wir allerdings die Abhängigkeiten in einer anderen Reihenfolge untersucht hätten, hätten wir statt A→B und B→A z.B. A→C und
C→A entfernen können und die Abhängigkeiten gemäß der Spalte Fc2
übrigbehalten. Dieses Beispiel zeigt, daß die kanonische Überdeckung
von F nicht eindeutig bestimmt ist.
Da es mehrere kanonische Überdeckungen gibt, stellt sich die Frage,
welche der kanonischen Überdeckungen minimal ist bzw. ob man sich
die Mühe machen soll, nach einer minimalen Überdeckung zu suchen.
Die Minimalität kann sich z.B. auf die Anzahl der Abhängigkeiten, also
einen Kostenfaktor, beziehen. Die Suche nach einer minimalen Überdeckung ist leider ein NP-vollständiges Problem, d.h. alle bekannten
Lösungen haben eine exponentielle Laufzeit, und es ist unwahrscheinlich, daß schnellere Algorithmen existieren. Abhängigkeitsmengen mit
vielen kanonischen Überdeckungen sind allerdings recht komplex und
selten, d.h. die praktische Relevanz dieses Problems ist gering.
Entwurf redundanzfreier Datenbankschemata
10.4
247
Das Boyce-Codd-Kriterium
Eine zentrale Frage in diesem Lehrmodul war, wie “richtige” oder “gute” Relationentypen gebildet sein müssen. In Abschnitt 10.2 haben
wir Mängel von Relationentypen aufgelistet; wir benötigen aber umgekehrt positive Qualitätskriterien, die angeben, wann ein Relationentyp
“richtig” geformt ist.
Für derartige Qualitätskriterien wird in der klassischen DatenbankLiteratur der Begriff Normalform verwendet. Ein Relationentyp ist
in einer der Normalformen, wenn er das zugehörige Qualitätskriterium
erfüllt. Diese Begriffsbildung ist wenig intuitiv oder sogar irreführend,
denn der Begriff Normalform wird häufig anders verstanden (nämlich
als normierte Darstellung), und ist allenfalls historisch erklärbar.
10.4.1
Definition
Das in diesem Abschnitt vorgestellte Kriterium ist nach den Autoren
Boyce und Codd benannt und besagt, daß zu große Relationentypen
im Sinne von Abschnitt 10.2.1 nicht auftreten dürfen. Somit werden
keine abhängigen Daten redundant gespeichert. Formal ist das BoyceCodd-Kriterium wie folgt definiert:
Definition: Sei R ein Relationentyp, F die Menge der für R gültigen
funktionalen Abhängigkeiten in der normierten Darstellung mit eindeutigen linken Seiten. F erfüllt das Boyce-Codd-Kriterium (bzw.
ist in Boyce-Codd-Normalform, abgekürzt BCNF) ⇐⇒
∀ X→Y ∈ F gilt:
– X→Y ist trivial, also Y ⊆ X
oder
– X→R, d.h. X ist Superschlüssel von R
Inhaltlich besagt das Boyce-Codd-Kriterium somit, daß außer den
trivialen Abhängigkeiten, die ja nichts aussagen, nur Schlüsselabhängigkeiten vorhanden sein dürfen. Schlüsselabhängigkeiten sind ebenfalls unvermeidlich, denn sie sind eine Konsequenz der Schlüsseleigenschaft, und Identifizierungsschlüssel sind ja per definitionem vom Ent-
248
Entwurf redundanzfreier Datenbankschemata
wickler gewünscht. Erlaubt sind also nur “unvermeidliche” Abhängigkeiten, sonst keine! Insofern ist das Boyce-Codd-Kriterium intuitiv
naheliegend, ferner ist die Struktur seiner Definition sehr einfach45 .
Das Boyce-Codd-Kriterium verbietet alle nichttrivialen Abhängigkeiten, die die Form X→Y haben, worin X kein Superschlüssel von R
ist. Wenn K ein Identifizierungsschlüssel von X ist, dann ist in solchen
Fällen Y auch indirekt von K abhängig:
K→X→Y
Eine derartige Abhängigkeit X→Y wird daher auch als transitive
Abhängigkeit bezeichnet. Wenn man noch einmal den zu großen
Relationentyp in Abschnitt 10.2.1 betrachtet, dann sollte klar werden,
daß transitive Abhängigkeiten gerade die Redundanz und die Anomalien verursachen. Relationen, die das Boyce-Codd-Kriterium erfüllen,
sind in diesem Sinne völlig frei von Redundanzen.
Von unseren früheren Beispielen erfüllen die Relationentypen
Kunden und Lieferungen das Boyce-Codd-Kriterium:
– Kunden hat nur {Kundennummer} als Identifizierungsschlüssel und
sonst keine funktionalen Abhängigkeiten.
– Bei Lieferungen können wir {Datum, Kundennummer} als Identifizierungsschlüssel annehmen46 . Außer {Datum, Kundennummer}→
Lieferungen sind keine hiervon nicht ableitbaren nichttrivialen
funktionalen Abhängigkeiten vorhanden.
Der Relationentyp Kundenlieferungen erfüllt das Boyce-CoddKriterium hingegen nicht: Auch hier können wir {Datum, Kundennummer} als Identifizierungsschlüssel annehmen. Es liegt hier aber
45
Zumindest, wenn man die Definition wie hier anlegt. In manchen Lehrbüchern
wird die Boyce-Codd-Normalform als Erweiterung der 3. Normalform definiert. Diese Definitionen sind technisch komplex und verbergen den intuitiv naheliegenden
Sinn des Kriteriums weitgehend. Historisch ist diese Definitionsmethode dadurch
erklärbar, daß die 3. Normalform zuerst gefunden wurde.
46
Um des Beispiels willen erlauben wir nur eine Lieferung pro Tag an einen Kunden.
Entwurf redundanzfreier Datenbankschemata
249
die Abhängigkeit der Kundendaten von der Kundennummer vor, also Kundennummer→{Kundenname, Wohnort, Kreditlimit}. Diese
Abhängigkeit verletzt das Boyce-Codd-Kriterium, denn sie ist nicht
trivial und {Kundennummer} ist kein Identifizierungsschlüssel.
10.4.2
Boyce-Codd-Zerlegungen
Sofern ein Relationentyp das Boyce-Codd-Kriterium nicht erfüllt, kann
man ihn verlustfrei so zerlegen, daß die entstehenden Relationentypen
die Boyce-Codd-Eigenschaft haben. Diese nennen wir Boyce-CoddZerlegung des Relationentyps.
Das Verfahren ist sehr einfach und intuitiv naheliegend. Als Beispiel betrachten wir zunächst ein Adreßverzeichnis, eine Relation mit
dem Typ
Adressen = ( Name: string;
Vorname: string;
PLZ: integer;
Wohnort: string;
Telnr: string; )
Einige Beispieltupel der zugehörigen Relation adressen sind in der
folgenden Tabelle angegeben:
Tabelle: adressen
Name
Vorname
Büdenbender Hanna
Litt
Michael
Müller
Markus
Schmidt
Karl
Schneider
Peter
PLZ
57250
57078
57072
57078
57250
Wohnort
Netphen
Siegen
Siegen
Siegen
Netphen
Telnr
...
...
...
...
...
Wir unterstellen, daß {Name, Vorname} der (einzige) Identifizierungsschlüssel ist. Wenn man die Beispieltabelle betrachtet, sollte
einem die redundante Angabe des Ortsnamens zu den Postleitzahlen auffallen; hier liegt die Abhängigkeit PLZ→Wohnort vor. Diese
Abhängigkeit verletzt natürlich das Boyce-Codd-Kriterium.
250
Entwurf redundanzfreier Datenbankschemata
Die naheliegende Lösung des Problems liegt darin, die Zuordnung
zwischen Postleitzahl und Ortsname in einer separaten Tabelle zu verwalten und in der Relation adressen nur noch die Postleitzahl zu
speichern, den Ortsnamen dagegen zu entfernen. Wir erhalten hier
folgende Relationen und zugehörige Relationentypen:
Tabelle: adressen2
Name
Vorname
Büdenbender Hanna
Litt
Michael
Müller
Markus
Schmidt
Karl
Schneider
Peter
PLZ
57250
57078
57072
57078
57250
...
...
...
...
...
...
Tabelle: plzort
PLZ
Wohnort
57072 Siegen
57078 Siegen
57250 Netphen
Im allgemeinen gehen wir wie folgt vor: Sei R der Relationentyp
und X→Y ∈ F die unzulässige Abhängigkeit, X, Y ⊆ R. Wir unterstellen, daß F in Form einer kanonischen Überdeckung vorliegt, die
Abhängigkeiten also keine trivialen Anteile enthalten (somit X ∩ Y =
∅). Dann zerlegen wir (R, F ) in folgende Relationentypen:
1. (R – Y, F – {X→Y})
2. (X ∪ Y, {X→Y})
Der erste Relationentyp hat die gleichen Identifizierungsschlüssel wie
R und entsteht, indem man in R die Attribute aus Y entfernt; gerade diese Attribute entsprechen ja den redundant gespeicherten Daten.
Die unzulässige Abhängigkeit entfällt.
Der zweite Relationentyp hat den Identifizierungsschlüssel X und
sonst keine Abhängigkeiten, erfüllt also das Boyce-Codd-Kriterium.
Übung:
Zeigen Sie, daß die vorstehende Zerlegung verlustfrei ist.
Sofern mehrere unzulässige Abhängigkeiten in (R, F ) vorhanden
sind, muß für jede einzelne unzulässige Abhängigkeit nach dem oben
Entwurf redundanzfreier Datenbankschemata
251
beschriebenen Verfahren eine Zerlegung durchgeführt werden. Am Ende ist keine unzulässige Abhängigkeit mehr vorhanden und das BoyceCodd-Kriterium erfüllt.
Durch die Zerlegungen erreichen wir unser Ziel, redundante Daten
zu vermeiden. Es sei aber nicht verschwiegen, daß Zerlegungen auch
einen Nachteil haben, der in Einzelfällen gravierend sein kann: Sofern
die Daten in Form der ursprünglichen, “zu großen” Relation benötigt
werden, muß diese aus den kleineren Relationen wieder rekonstruiert
werden. Hierzu müssen Verbunde gebildet werden, was sehr aufwendig sein kann. Manchmal verzichtet man besser auf die Zerlegung,
muß dann aber durch gezielte Maßnahmen die in Abschnitt 10.2 beschriebenen Anomalien behandeln und individuelle Maßnahmen zur
Konsistenzsicherung ergreifen.
Zum vorstehenden Zerlegungsverfahren ist noch nachzutragen, daß
wir uns heimlich eine gewisse Unsauberkeit erlaubt haben: F kann außer X→Y noch weitere Abhängigkeiten enthalten, die Attribute aus Y
und R - X beinhalten, z.B. Z→Y, Z ∩ X = ∅, s. Bild 10.5. Nachdem die
R
R
X
Z
X
Z
Y
X
vor der Zerlegung
Y
nach der Zerlegung
Abbildung 10.5: Entstehen nichtlokaler Abhängigkeiten
Attribute aus Y in R entfernt worden sind, wirkt eine solche Abhängigkeit bei R etwas deplaziert, denn sie betrifft Attribute, die in R gar
nicht mehr enthalten sind. Sofern alle Attribute einer Abhängigkeit
zu dem zweiten Relationentyp gehören, kann man sie dem 2. Re-
252
Entwurf redundanzfreier Datenbankschemata
lationentyp zuordnen, wobei dann zu prüfen wäre, ob er dann noch
das Boyce-Codd-Kriterium erfüllt. Es kann aber immer noch relationsübergreifende Abhängigkeiten geben, die “quer” zu den beiden
entstandenen Relationentypen liegen, d.h. die, wenn sie z.B. vom ersten auf den zweiten Relationentyp gerichtet sind, die Form U→V mit
U ⊆ R-(X∪Y) und V ⊆ Y haben.
10.5
Lokale Überwachbarkeit
10.5.1
Motivation und Definition
Wir sind bisher ausgegangen von der Problematik, daß ein Relationentyp R zu viele Attribute enthält und somit zerlegt werden sollte,
z.B. in die Relationentypen R1 und R2 . Abhängigkeiten von R, die
Attribute aus R1 – R2 und R2 – R1 enthalten, können weder R1 noch
R2 gut zugeordnet werden. Man müßte solche relationsübergreifenden
Abhängigkeiten47 an anderer Stelle notieren. Das Notationsproblem
ist hier allerdings zweitrangig.
Viel gravierender ist das Problem, daß man nun einen Verbund (zumindest partiell) berechnen muß, um die Einhaltung der Abhängigkeiten zu kontrollieren. Dies kann sehr unangenehm sein, denn die Kontrolle ist bei jeder Erzeugung oder Änderung eines Tupels erforderlich
und die Berechnung von Verbunden ist i.a. aufwendig. Man möchte
relationsübergreifende Abhängigkeiten daher möglichst vermeiden und
nur Abhängigkeiten haben, bei denen alle involvierten Attribute zu einem Relationentyp gehören, so daß die Abhängigkeit in der zugehörigen Relation ohne Verbundbildung lokal überwachbar ist. Dies ist
meist mit Hilfe von Indexen sehr effizient möglich.
Nicht stören würden relationsübergreifende Abhängigkeiten, die
von lokal überwachbaren ableitbar sind, denn ableitbare Abhängigkeiten brauchen ja nicht überwacht zu werden. Diese Beobachtung führt
47
Diese relationsübergreifenden Abhängigkeiten dürfen nicht mit Fremdschlüsseln
verwechselt werden. Fremdschlüssel sind keine funktionalen Abhängigkeiten, sondern Inklusionsabhängigkeiten: Alle auftretenden Fremdschlüsselwerte müssen
auch in der referierten Tabelle auftreten.
Entwurf redundanzfreier Datenbankschemata
253
zum Begriff einer unabhängigen Zerlegung: bei einer solchen sind alle
Abhängigkeiten, die durch die Zerlegung relationsübergreifend werden,
ableitbar.
Definition: Sei (R,F ) ein Relationentyp, {R1 , ..., Rn } eine Zerlegung
von R. Für 1 ≤ i ≤ n sei
Fi = { X→Y ∈ F + | X, Y ⊆ Ri }
Die Zerlegung {R1 , ..., Rn } heißt unabhängig (dependency preserving)
S
bzgl. F , wenn ( ni=1 Fi )+ = F + .
Jede der Mengen Fi enthält die Abhängigkeiten, die lokal in πRi (r)
überwachbar sind.
Ein Beispiel für eine unabhängige Zerlegung ist die Zerlegung von
Kundenlieferungen in Kunden und Lieferungen.
10.5.2
Beispiel: Postleitzahlenbuch
In diesem Abschnitt stellen wir ein Beispiel einer nicht unabhängigen Zerlegung vor. Es handelt sich hier um eine vereinfachte Variante
des Postleitzahlenbuchs. Dieses gibt zu einer Stadt und einer Straße
die Postleitzahl an, ferner nehmen wir an, daß ein PLZ-Gebiet immer
ganz in einer Stadt liegt48 . Der zugehörige Relationentyp kann wie
folgt definiert werden:
PLZBuch = ( Ort: string;
Straße: string;
PLZ: integer;
)
Einige Beispieltupel aus der zugehörigen Relation plzbuch zeigt
die folgende Tabelle:
48
Tatsächlich kann die Postleitzahl auch noch von der Hausnummer abhängen,
und es gibt Städte, bei denen die Postleitzahl nicht von der Straße abhängt. Ferner
haben in einigen Gegenden verschiedene Orte die gleiche Postleitzahl.
254
Entwurf redundanzfreier Datenbankschemata
Tabelle:
Ort
Siegen
Siegen
Siegen
Siegen
Siegen
Siegen
Siegen
plzbuch
Straße
Grabenstr.
Kohrweg
Hölderlinstr.
Poststr.
Marktstr.
Ruhrststr.
Schulstr.
PLZ
57072
57074
57076
57076
57078
57078
57080
Es liegen folgende funktionale Abhängigkeiten vor:
– {Ort, Straße}→PLZ
– PLZ→Ort
Ort
PLZ
Straße
Abbildung 10.6: Graphische Darstellung der funktionalen Abhängigkeiten im Relationentyp PLZBuch
{Ort, Straße} ist offensichtlich Identifizierungsschlüssel. Aus
PLZ→Ort folgt mittels der Erweiterungsregel, daß auch {PLZ,
Straße}→{Ort, Straße}; somit ist auch {PLZ, Straße} ein Identifizierungsschlüssel.
Wir betrachten nun folgende Zerlegung von PLZBuch:
– PLZBuch1 = {PLZ, Ort} mit Identifizierungsschlüssel {PLZ}
– PLZBuch2 = {PLZ, Straße} mit Identifizierungsschlüssel {PLZ,
Straße}
Die beiden Identifizierungsschlüssel stellen die einzigen nichttrivialen Abhängigkeiten der beiden Relationentypen dar.
Entwurf redundanzfreier Datenbankschemata
Tabelle: plzbuch1
PLZ
Ort
57072 Siegen
57074 Siegen
57076 Siegen
57078 Siegen
57080 Siegen
255
Tabelle: plzbuch2
PLZ
Straße
57072 Grabenstr.
57074 Kohrweg
57076 Hölderlinstr.
57076 Poststr.
57078 Marktstr.
57078 Ruhrststr.
57080 Schulstr.
Abbildung 10.7: Zerlegte Postleitzahlen-Relation
Bild 10.7 zeigt die beiden entstehenden Relationen.
Diese Zerlegung ist verlustfrei, denn PLZBuch1 ∩ PLZBuch2 =
{ PLZ } und PLZ ist Identifizierungsschlüssel für PLZBuch1.
Die Zerlegung ist nicht unabhängig, denn {Ort, Straße}→PLZ ist
nicht von den lokal überwachbaren Abhängigkeiten ableitbar. Dies beweist man leicht, indem man mit dem in Abschnitt 10.3.5 vorgestellten
Algorithmus die Menge der von {Ort, Straße} abhängigen Attribute
berechnet.
Wenn man z.B. in plzbuch versuchen würde, das Tupel (Siegen,
Hölderlinstr., 57080) einzufügen, obwohl schon (Siegen, Hölderlinstr.,
57076) vorhanden ist, würde dieser Fehler erkannt werden. Bei der
Zerlegung müßte man entsprechend in der Relation plzbuch1 das Tupel (57080, Siegen) einfügen (was sich hier zufällig erübrigt, weil es
schon vorhanden ist) und in der Relation plzbuch2 das Tupel (57080,
Hölderlinstr.); beide Einfügungen sind mit den lokalen Abhängigkeiten
konsistent. Um herauszufinden, ob dem Paar (Siegen, Hölderlinstr.)
nicht auf einmal zwei verschiedene Postleitzahlen zugeordnet werden,
müßte bei Einfügungen auf die jeweils andere Relation zugegriffen werden und ein auf die vorliegenden Werte des Verbundattributs PLZ beschränkter Verbund gebildet werden.
Das vorstehende Beispiel ist insofern wichtig, als es zeigt, daß es
Relationentypen gibt, die keine unabhängige Zerlegung in kleinere Re-
256
Entwurf redundanzfreier Datenbankschemata
lationentypen, die das Boyce-Codd-Kriterium erfüllen, haben. Im einzelnen:
– PLZBuch erfüllt das Boyce-Codd-Kriterium nicht, denn PLZ→Ort
widerspricht dem. PLZ→Ort ist nicht trivial und {PLZ} ist kein
Identifizierungsschlüssel für PLZBuch.
– Das in Abschnitt 10.4.2 vorgestellte Verfahren zur Erzeugung einer Boyce-Codd-Zerlegung führt gerade zu der vorstehenden Zerlegung. Dieser erfüllt nach Konstruktion das Boyce-Codd-Kriterium,
ist aber nicht unabhängig.
– Andere verlustfreie Zerlegungen existieren nicht; es müßte entweder Ort oder Straße als Verbundattribut benutzt werden; in keinem
Fall ist dies ein Identifizierungsschlüssel für eine der entstehenden
Teil-Relationentypen.
R
K
Y1
X
Y2
Abbildung 10.8: Varianten von transitiven Abhängigkeiten
Bild 10.8 zeigt zwei Alternativen, wie eine unzulässige funktionale
Abhängigkeit liegen kann. Hieran können wir die Ursache des Problems beim Postleitzahlenbuch-Schema generell diskutieren.
Gegeben ist ein Relationentyp R mit einem Identifizierungsschlüssel
K und der transitiven Abhängigkeit K→X→Y1. Um diese Abhängigkeit zu entfernen, müssen wir R zerlegen und die Attributmenge Y1
aus R entfernen. Dadurch werden aber die Attribute des Identifizierungsschlüssels K “auseinandergerissen”, die Abhängigkeit K→X wird
zu einer nichtlokalen. Da Identifizierungsschlüssel i.a. nicht von anderen Abhängigkeiten impliziert werden, geht die Unabhängigkeit der
Zerlegung verloren.
Entwurf redundanzfreier Datenbankschemata
257
Bild 10.8 ist zusätzlich die transitive Abhängigkeit K→X→Y2 eingezeichnet. Diese hat nicht die Form einer “Schlinge”, es ist also nicht
Y2 ⊂ K, deshalb kann man scheinbar problemlos das übliche Zerlegungsverfahren anwenden. Dies stimmt aber nicht ganz, denn wenn
es einen zweiten Identifizierungsschlüssel K2 gibt und wenn Y2 ⊂ K2
ist, dann haben wir das gleiche Problem. Entscheidend ist also, ob die
indirekt abhängige Attributmenge in einem Identifizierungsschlüssel
liegt49 oder nicht. Falls ja, haben wir ein Problem.
10.6
Die dritte Normalform
10.6.1
Motivation und Definition
In den vorigen Abschnitten wurde gezeigt, daß einerseits das BoyceCodd-Kriterium sehr naheliegend ist und die natürliche Konkretisierung des Wunsches nach Redundanzfreiheit ist, daß andererseits aber
nicht immer eine unabhängige Boyce-Codd-Zerlegung existiert. Sofern
letzteres der Fall ist, muß man entweder auf die Redundanzfreiheit oder
die lokale Überwachbarkeit verzichten. I.a. wird man der lokalen Überwachbarkeit die höhere Priorität einräumen (in Ausnahmefällen kann
die Entscheidung auch zugunsten der Redundanzfreiheit ausfallen).
Wir benötigen somit ein Qualitätskriterium für Relationentypen,
das schwächer als das Boyce-Codd-Kriterium ist und bei dem in gewissem Umfang Redundanz erlaubt wird. Ein solches Kriterium ist
die dritte Normalform50 , die in diesem Abschnitt vorgestellt wird. Sie
ist folgendermaßen definiert:
Definition: Sei R ein Relationentyp, F die Menge der für R gültigen funktionalen Abhängigkeiten. R ist in dritter Normalform (abgekürzt 3NF) ⇐⇒ ∀ X→Y ∈ F gilt:
49
Sie muß eine echte Teilmenge sein, wenn sie identisch mit dem Identifizierungsschlüssel wäre, wäre auch X ein Identifizierungsschlüssel und die Abhängigkeit wäre
zulässig.
50
Offensichtlich gibt es dann auch eine erste und zweite Normalform. Beide sind
im Moment irrelevant, wir gehen in Abschnitt 10.8 kurz darauf ein.
258
Entwurf redundanzfreier Datenbankschemata
1. X→Y ist trivial, also Y ⊆ X
oder
2. X→R, d.h. X ist Superschlüssel von R
oder
3. Y ist Teilmenge eines Identifizierungsschlüssels, d.h. ∃ K ⊆ R mit
K→R und Y ⊆ K
Die dritte Art von zulässigen Abhängigkeiten stellt gerade die angekündigte Aufweichung gegenüber dem Boyce-Codd-Kriterium dar.
Informell ausgedrückt bedeuten solche Fälle, daß ein Schlüsselattribut
von einer Attributmenge, die kein Schlüssel ist, abhängig ist.
Unser Relationentyp Postleitzahlenbuch ist in dritter Normalform;
die beim Boyce-Codd-Kriterium unzulässige Abhängigkeit PLZ→Ort
stört hier nicht mehr, denn {Ort} ist Teilmenge des Identifizierungsschlüssels {Ort, Straße}, d.h. sie fällt unter die dritte Art zulässiger
Abhängigkeiten.
Ein Relationentyp, der das Boyce-Codd-Kriterium erfüllt, ist offensichtlich auch in dritter Normalform. Das Beispiel des Postleitzahlenbuchs zeigt, daß die Umkehrung dieser Aussage nicht gilt. Die dritte
Normalform ist somit ein schwächeres Korrektheitskriterium als das
Boyce-Codd-Kriterium.
10.6.2
Konstruktion einer Zerlegung in dritter Normalform
Bei jedem Qualitätskriterium für Relationentypen stehen wir vor der
Frage, ob wir zu einem gegebenen Relationentyp, der das Qualitätskriterium nicht erfüllt, immer eine verlustfreie und unabhängige Zerlegung finden können, die das Kriterium erfüllt. Beim Boyce-CoddKriterium war die Antwort nein. Bei der dritten Normalform ist die
Antwort hingegen ja, es gibt einen Algorithmus, der zu einem Relationentyp und einer Menge funktionaler Abhängigkeiten zu diesem
Relationentyp eine Zerlegung in dritter Normalform konstruiert.
Die Grundidee zu diesem Algorithmus ist informell sehr einfach
zu erklären: Jede funktionale Abhängigkeit X→Y muß ja überwacht
werden, am einfachsten und direktesten durch eine eigene Tabelle mit
Entwurf redundanzfreier Datenbankschemata
259
dem Relationentyp (X∪Y, {X→Y}). Wenn man nun für alle “wichtigen”
funktionalen Abhängigkeiten eine derartige Tabelle vorsieht, hat man
eine verlustfreie Zerlegung, und die einzelnen Relationen haben nach
Konstruktion nur eine nichttriviale Abhängigkeit. Die Frage nach den
“wichtigen” Abhängigkeiten läßt sich durch Rückgriff auf den Begriff
kanonische Überdeckung lösen.
Die genaue Vorgehensweise, anhand der wir zu einem gegebenen
Relationentyp (R, F ) eine Zerlegung in dritter Normalform konstruieren, ist wie folgt:
1. Wir wählen eine kanonische Überdeckung von F . Dieser Schritt ist
nichtdeterministisch, denn es kann i.a. mehrere kanonische Überdeckungen geben. Sei Fc diese Menge von Abhängigkeiten.
Es sei daran erinnert, daß bei einer kanonischen Überdeckung
keine Abhängigkeit und kein Attribut in den Abhängigkeiten überflüssig ist.
Wir unterstellen, daß Fc in der normierten Darstellung vorliegt,
bei der die linken Seiten der Abhängigkeiten eindeutig sind.
2. Zu einer Abhängigkeit X→Y ∈ Fc bilden wir den Relationentyp
( X∪Y, { A→B | A→B ∈ Fc ∧ A∪B ⊆ X∪Y } ).
Sei S die Menge der so entstandenen Relationentypen.
3. Sofern keine der Relationentypen in S ein Superschlüssel für R ist,
bilden wir einen beliebigen Identifizierungsschlüssel K für R und
fügen zu S die Relation (K, ∅) hinzu.
4. In der Menge S können wir nun solche Relationentypen (Ri , Fi )
löschen, die ganz in einem “größeren” Relationentyp enthalten sind,
d.h. für die gilt ∃ (Rj , Fj ) ∈ S: Ri ⊆ Rj
Anmerkung zu Schritt 3: Daß nicht immer automatisch eine der
Relationentypen in S einen Superschlüssel für R umfaßt, mag auf den
ersten Blick überraschen. Ein Beispiel für solche Relationentypen sind
“Verbindungstabellen”, die eine m:n-Beziehung realisieren, die nur
zwei Attribute X und Y haben und bei denen {X, Y}, also der komplette Relationentyp R, der einzige Identifizierungsschlüssel ist. Die
260
Entwurf redundanzfreier Datenbankschemata
Abhängigkeit R→R ist aber trivial und daher in der kanonischen Überdeckung nicht enthalten.
Es gibt aber auch Beispiele mit nichttrivialen Abhängigkeiten, z.B.
R = {A, B, C, D, E, F, G} und F = { A→BC, D→EF }. Hier ist ADG
der einzige Identifizierungsschlüssel. Diese Attributmenge ist aber in
keinem der Relationentypen Ri enthalten, denn ADG→R wird von den
o.g. Abhängigkeiten impliziert und ist daher in der kanonischen Überdeckung nicht enthalten.
Anmerkung zu Schritt 4: Ein Beispiel hierfür ist der Relationentyp
PLZBuch. Eine kanonische Überdeckung ist {{Ort, Straße}→PLZ,
PLZ→Ort}; in den beiden ersten Schrittes unseres Algorithmus entstehen daraus die Relationentypen {Ort, Straße, PLZ} und {PLZ,
Ort}. Der zweite ist Teilmenge des ersten, wird also in Schritt 4 wieder eliminiert.
Auf diese Eliminierung könnte man übrigens auch verzichten, die
eliminierten Relationentypen sind auch alle in 3NF. Allerdings wären
die zugehörigen Relationen natürlich redundant, und Redundanzvermeidung ist ja gerade das Ziel der Normalformen.
Der obige Algorithmus wird auch Synthesealgorithmus genannt,
weil hier zunächst die funktionalen Abhängigkeiten betrachtet werden
und auf Basis einer kanonischen Überdeckung sofort die Relationentypen zusammengesetzt werden. Im Gegensatz dazu ist das Verfahren,
mit dem wir die Boyce-Codd-Zerlegung hergestellt haben, ein Dekompositionsverfahren, bei dem schrittweise immer wieder neue Relationentypen bestimmt werden.
Behauptung: Eine mit dem Synthesealgorithmus erzeugte Zerlegung
ist verlustfrei und unabhängig und alle entstandenen Relationentypen
sind in 3NF.
Beweis: Daß es sich hier um eine Zerlegung von R handelt, ergibt sich
aus den Eigenschaften einer Überdeckung, d.h. alle Attribute aus R treten in den Abhängigkeiten in Fc und somit auch wieder in wenigstens
einem der Relationentypen in S auf.
Die Unabhängigkeit der Zerlegung läßt sich leicht zeigen: Nach der
Entwurf redundanzfreier Datenbankschemata
261
Konstruktion der Zerlegung sind alle funktionalen Abhängigkeiten aus
Fc lokal prüfbar, vgl. Schritte 2 - 4 des Synthesealgorithmus. Da Fc
eine kanonische Überdeckung ist, gilt weiter Fc+ = F + , d.h. die Zerlegung ist unabhängig.
Die Verlustfreiheit beweisen wir wie folgt: Seien ri = πRi (r) die
zu den Relationentypen gehörenden Relationen. Zu zeigen ist, daß
bei einem Verbund aller ri keine Tupel entstehen, die nicht in der
ursprünglichen Relation r vorhanden waren.
Nach Konstruktion enthält S immer einen Relationentyp K, der ein
Superschlüssel für R ist, also K+ = R bzw. K→R. Diese Abhängigkeit
wird von den Abhängigkeiten in der Überdeckung impliziert. Wenn
man K+ mit dem in Abschnitt 10.3.5 angegebenen Algorithmus berechnet, konstruiert man in einer Kette von Ableitungsschritten immer größere Attributmengen Ki (mit K0 = K), wobei irgendwann Kn
= R gilt. Bei jedem Schritt wird die Menge der von K abhängigen
Attribute erweitert, indem die Erweiterungsregel und eine einsetzbare
Abhängigkeit Xi →Yi mit Xi ⊆ Ki ausgenutzt werden.
Wir nutzen nun die zu K gehörige Relation k als Ausgangsbasis für
unsere Verbundbildung. Offensichtlich ist |k| = |r|, k enthält schon
alle in r auftretenden Wertekombinationen in den Schlüsselattributen
K. Wir bilden nun schrittweise den Verbund mit einer Relation, die die
Attribute Xi ∪Yi enthält; sei dies ri , somit
ki = ri 1 ki−1
Wir nehmen zunächst an, daß Ri =Xi ∪Yi ist. Der vorstehende Verbund
ist verlustfrei, da die Attribute Xi die Verbundattribute und Identifizierungsschlüssel von ri sind. Es gilt also |ki | = |ki−1 |. Ferner ist K
Superschlüssel für ki . Durch Induktion über i zeigt man leicht, daß
|k0 | = |kn | ist. Die Zahl der Tupel erhöht sich also bei keinem Schritt.
Wegen der Kommutativität und Assoziativität des Verbundoperators kommt dann, wenn man die Verbunde in einer anderen Reihenfolge bildet, am Ende das gleiche Ergebnis heraus; allerdings können
bei einer anderen Reihenfolge Zwischenergebnisse auftreten, die mehr
Tupel als r enthalten.
Es bleibt bei der Bildung von ki der Fall zu behandeln, daß S keinen
262
Entwurf redundanzfreier Datenbankschemata
Relationentyp Ri mit Ri = Xi ∪Yi enthält. Dieser Relationentyp kann
in Schritt 4 des Synthesealgorithmus entfernt worden sein. Es muß
dann wenigstens einen Relationentyp Ri mit Ri ⊃ Xi ∪Yi geben. Wir
verwenden dann zunächst statt ri die Relation πXi ∪Yi (ri ) für die Verbundbildung und bilden ganz zum Schluß noch einmal den Verbund
kn 1 ri . Offensichtlich gilt:
ri = πXi ∪Yi (ri ) 1 ri
d.h. unser künstlich eingeführter Zwischenschritt ändert wegen der
Kommutativität und Assoziativität des Verbundoperators nichts am
Gesamtergebnis.
Die 3NF beweisen wir wie folgt: Der Relationentyp (K, ∅), den wir
ggf. in Schritt 3 des Synthesealgorithmus hinzugenommen haben, ist
trivialerweise in 3NF. Für die restlichen Relationentypen zeigen wir,
daß die Annahme, sie seien nicht in 3NF, zu einen Widerspruch führt.
Sei also (Ri , Fi ) ein Relationentyp, der durch eine Abhängigkeit
Xi →Yi in Fc entstanden ist, also Ri = Xi ∪ Yi .
Xi
Yi
A
U
Abbildung 10.9: Beweissituation
Angenommen, Ri ist nicht in 3NF, dann existiert eine Abhängigkeit
U→A in Fi , worin U kein Identifizierungsschlüssel und A ein Attribut
ist, das zu keinem Identifizierungsschlüssel gehört.
A muß entweder in Xi oder Yi liegen. A kann nicht in Xi liegen, denn
Xi ist Identifizierungsschlüssel für Ri : Nach Konstruktion gilt Xi →Ri ,
und wegen der Linksminimalität der Abhängigkeiten in Fc ist keine
echte Teilmenge von Xi Identifizierungsschlüssel für Ri .
Nehmen wir also A∈Yi an. U kann keine echte Teilmenge von Xi sein,
Entwurf redundanzfreier Datenbankschemata
263
dies widerspräche der Konstruktion von Fc (genauer gesagt der Linksminimalität der Abhängigkeit Xi →A). U muß also wenigstens ein Attribut aus Yi enthalten, s. Skizzierung der Lage in Bild 10.9. Nach unseren bisherigen Annahmen gilt: Xi →U wird von Fc impliziert, U→A ist
in Fc enthalten. Beide Abhängigkeiten implizieren zusammen Xi →A.
Dies widerspricht aber der Annahme Xi →Yi ∈ Fc und A ∈ Yi : eine
kanonische Überdeckung enthält keine überflüssigen Attribute in den
Abhängigkeiten.
10.7
Überwachung funktionaler Abhängigkeiten
Wir hatten schon oben erwähnt, daß funktionale Abhängigkeiten als
Integritätsbedingungen anzusehen sind und innerhalb eines Informationssystems überwacht werden müssen. Man kann zwei grundlegend
verschiedene Ansätze unterscheiden:
– Die Applikationen sind verantwortlich: Sofern z.B. freie Dateneingaben möglich sind, muß die Applikation entsprechende Tests
durchführen und die Eingaben im Fehlerfall zurückweisen. Alternativ kann man die Dateneingabeschnittstellen oder Kommandos
so gestalten, daß inkonsistente Zustände gar nicht erzeugt werden
können.
Ein prinzipieller Schwachpunkt dieses Ansatzes ist, daß er unsicher ist. Zum einen sind die Konsistenzprüfungen im ApplikationsCode “versteckt” und nicht automatisch überprüfbar; selbst wenn
die Absicht bestand, entsprechende Prüfungen einzubauen, kann
dies durch Programmierfehler nicht korrekt realisiert worden sein.
Wenn man ferner ein Datenbanksystem als eine relativ offene Basis
zur Entwicklung von Applikationen ansieht, stellt sich die Notwendigkeit, das Wissen über die notwendigen Konsistenzprüfungen unter allen Applikationsprogrammierern zu verbreiten, als kritischer
Punkt dar.
– Das DBMS ist verantwortlich: Das DBMS muß hier eine geeignete Schnittstelle anbieten, über die ihm mitgeteilt werden kann (im
264
Entwurf redundanzfreier Datenbankschemata
Rahmen der Schemadefinition), welche Abhängigkeiten überwacht
werden sollen. Für Identifizierungsschlüssel (insb. Primärschlüssel
und “eindeutige” Attribute) sind derartige Schnittstellen üblicherweise vorhanden.
Das DBMS muß unzulässige Einfügungen und Änderungen
dementsprechend mit einer Fehlermeldung ablehnen. Da es zu einer Relation mehrere funktionale Abhängigkeiten geben kann und
Einfügungen auch mengenorientiert erfolgen können, ist die Struktur der Fehlermeldung notwendigerweise recht komplex.
Es stellt sich allerdings die Frage, ob ein DBMS nicht besser Konzepte und Schnittstellen anbieten sollte, die das Problem
der Korrektheit der Daten allgemeiner angehen (z.B. TriggerMechanismen). Funktionale Abhängigkeiten sind nur einer von
mehreren Typen von Korrektheitsbedingungen
Hinsichtlich des Laufzeitaufwands zur Kontrolle der Abhängigkeiten sind natürlich Identifizierungsschlüssel, die als Primärschlüssel realisiert werden, unübertroffen günstig. Bei allen anderen Verfahren muß
im Prinzip immer dann, wenn eine Abhängigkeit X→Y vorliegt und ein
Tupel t erzeugt werden soll, gesucht werden, ob schon in den Attributen X die Wertekombination t[X] vorliegt. Damit eine solche Suche effizient durchgeführt werden kann, muß i.a. ein Sekundärindex für X oder
eine vergleichbare Datenstruktur vorhanden sein; der Platzbedarf und
Pflegeaufwand hierfür ist vergleichbar mit einer zusätzlichen Relation
mit dem Typ (X∪Y, {X→Y}), wie sie bei Boyce-Codd-Zerlegungen entsteht. Generell ist daher anzustreben, möglichst alle Abhängigkeiten
nach einer Boyce-Codd-Zerlegung auf einen Primärschlüssel abzubilden.
10.8
Weitere Normalformen
10.8.1
Die erste Normalform
Die erste Normalform besteht nur aus dem Kriterium, daß alle Attribute unstrukturierte, “atomare” Wertebereiche haben müssen, also
Entwurf redundanzfreier Datenbankschemata
265
Zahlen, Boolesche Werte, Zeichenketten51 usw., aber keine Arrays, Listen oder Mengen. Letztere kann man auch als mehrwertige Attribute
auffassen.
Die Forderung nach atomaren Attributen ist einerseits dadurch motiviert, daß die resultierenden statischen Datenstrukturen deutlich effizienter sind als dynamische. Weiter müßten die Abfragesprachen sonst
syntaktisch und semantisch deutlich komplizierter sein, weil jetzt ja
auch einzelne Elemente innerhalb eines Datenwerts adressierbar sein
müssen (z.B. für eine Abfrage wie “liefere alle Tupel, die im Feld A
[das einen Array-Typ hat] als 3. Element eine 5 haben”).
Die erste Normalform haben wir bisher schon immer stillschweigend vorausgesetzt, sie liegt ja schon der Denkwelt der relationalen
Algebra zugrunde. Während alle anderen Normalformen immer irgendeine Form von Redundanz adressieren (bzw. verbieten), ist dies
bei der ersten Normalform nicht der Fall; sie ist eher eine Art syntaktisches Kriterium.
Sofern von der Anwendung her Attribute mehrwertig sind, muß
man ein Tupel, in dem ein mehrwertiges Attribut mit n Werten auftritt, durch n Tupel ersetzen, in denen jeweils einer der Werte auftritt
und der Rest des Tupels jeweils gleich ist. Als Beispiel betrachten wir
ein Bücherverzeichnis; ein Buch kann mehrere Autoren haben:
Tabelle: bücherverzeichnis
ISBN Titel
12345 Software Engineering
..
..
Autoren
Naur, P.; Randell, B.
..
Jahr
1968
..
Das mehrwertige Attribut Autoren muß durch ein atomares ersetzt
werden, um z.B. Abfragen wie “welche Bücher hat Autor X (mit-)
verfaßt” korrekt beantworten zu können:
51
Man könnte hier ketzerisch fragen, ob Zeichenketten nicht eigentlich doch eine
Struktur haben und z.B. als Array angesehen werden können...
266
Entwurf redundanzfreier Datenbankschemata
Tabelle: bücherverzeichnis2
ISBN Titel
12345 Software Engineering
12345 Software Engineering
..
..
Autor
Naur, P.
Randell, B.
..
Jahr
1968
1968
..
In der Regel stellen die bei der Umwandlung mehrwertiger Attribute entstehenden gleichen Teile der Tupel Redundanzen dar, die
das Boyce-Codd-Kriterium verletzen. In unserem Beispiel liegt die
Abhängigkeit ISBN→{Titel, Jahr} vor, während {ISBN, Autor} einziger Identifizierungsschlüssel ist; das Boyce-Codd-Kriterium ist somit
verletzt.
Die Boyce-Codd-Zerlegung weist hier die Besonderheit auf, daß alle Attribute außer dem ursprünglichen Identifizierungsschlüssel und
dem mehrwertigen Attribut aus der zu zerlegenden Relation (hier:
bücherverzeichnis2) entfernt werden müssen und die “neue” Relation bilden; intuitiv wird man eher diese neue Relation als Nachfolger
der ursprünglichen Relation empfinden als den kleinen Rest der ursprünglichen Relation. In unserem Beispiel erhalten wir also:
Tabelle: autoren
ISBN Autor
12345 Naur, P.
12345 Randell, B.
..
..
Tabelle: bücherverzeichnis3
ISBN Titel
Jahr
12345 Software Engine- 1968
ering
..
..
..
Im Endeffekt muß man i.a. statt eines mehrwertigen Attributs eine
eigene Relation benutzen, die neben dem Identifizierungsschlüssel der
Ausgangsrelation das mehrwertige Attribut in der atomaren Variante
enthält.
Unter dem Namen NF2 (non first normal form) DBMS sind auch
DBMS entstanden, bei denen einzelne Attribute als Werte Relationen
enthalten können; auf diese DBMS gehen wir hier aus Platzgründen
und wegen der geringen praktischen Relevanz nicht ein.
Entwurf redundanzfreier Datenbankschemata
10.8.2
267
Die zweite Normalform
Die zweite Normalform fordert, daß kein Nichtschlüsselattribut von
einer echten Teilmenge eines Identifizierungsschlüssel abhängen darf.
Unser vorstehendes bücherverzeichnis2 war nicht in zweiter Normalform, da z.B. Titel von ISBN abhängt und da {ISBN} eine echte
Teilmenge des Identifizierungsschlüssels {ISBN, Autor} ist. Zulässig
bei der zweiten Normalform sind Abhängigkeiten X→Y, bei denen
– X ein Nichtschlüsselattribut enthält oder
– Y ein Schlüsselattribut ist
M.a.W. schließt die zweite Normalform nur eine spezielle Form von
Redundanzen aus. Die zweite Normalform ist daher nicht hinreichend
im Sinne der Redundanzvermeidung und wird hier nur der Vollständigkeit halber erwähnt.
10.8.3
Mehrwertige Abhängigkeiten und die vierte Normalform
Mehrwertige Abhängigkeiten stellen eine weitere Form von Konsistenz
bzw. Redundanz dar, die sich mit den bisherigen Begriffen nicht fassen
läßt. Als Beispiel modifizieren wir das Beispiel aus Abschnitt 10.8.1 dahingehend, daß wir nicht mehr ein Verzeichnis unterschiedlicher Bücher
(im Sinne von Buchtiteln) haben, sondern den Bestand einer Bibliothek, in der mehrere Exemplare eines Buchs stehen können. Jedes Exemplar ist durch eine Katalognummer (Attribut KatNr) identifiziert.
Wenn z.B. von einem Buch mit 2 Autoren 3 Exemplare vorhanden sind,
könnte, eine Relation bibliothek, deren Relationentyp Bibliothek
sei, folgenden Inhalt haben:
268
Entwurf redundanzfreier Datenbankschemata
Tabelle: bibliothek
KatNr ISBN Titel
2744
12345 Software
2744
12345 Software
2745
12345 Software
2745
12345 Software
2746
12345 Software
2746
12345 Software
..
..
..
Engineering
Engineering
Engineering
Engineering
Engineering
Engineering
Autor
Naur, P.
Randell, B.
Naur, P.
Randell, B.
Naur, P.
Randell, B.
..
Jahr
1968
1968
1968
1968
1968
1968
..
Diese Relation hat die Abhängigkeiten KatNr→ISBN und
ISBN→{Titel, Jahr} und den Identifikationsschlüssel {KatNr,
Autor}. Wenn wir nun das letzte der 6 Tupel weglassen, sind die
vorstehenden Abhängigkeiten nach wie vor erfüllt, der Datenbestand
aber dennoch nicht mehr korrekt, denn das dritte Exemplar des Buchs
hat einen Autor weniger als die anderen. Das Konsistenzkriterium
ist hier, daß zu jedem Wert von ISBN eine Gruppe von Werten des
Attributs Autor “gleichmäßig auftritt” (die Gruppen entsprechender
Tupel sind in der vorstehenden Tabelle durch zusätzliche Trennstriche
gekennzeichnet).
Wenn t ein Tupel der Relation bibliothek ist und i = t[ISBN] die
in t auftretende ISBN, dann gehört zu i folgende Gruppe von Werten
von Autor:
πAutor (σISBN=i (bibliothek))
In unserem obigen Beispiel ist πAutor (σISBN=12345 (bibliothek)) =
{“Naur, P.”, “Randell, B.”}. Diese Abfrage liefert also alle Autoren,
die bei irgendeinem Exemplar des Buchtitels mit ISBN 12345 genannt
werden.
Das “gleichmäßige Auftreten” der Wertegruppe bedeutet, daß die
Menge σISBN=i (bibliothek) in mehrere gleichgroße Teilmengen aufgeteilt werden kann, für die folgendes gilt:
– Jede Teilmenge hat in Z = Bibliothek - {Autor} die gleichen Werte (und enthält die Tupel, die genau ein Buchexemplar repräsentie-
Entwurf redundanzfreier Datenbankschemata
269
ren). Wenn t1 ein Element einer solchen Teilmenge ist, dann kann
man die Teilmenge angeben als
σZ=t1[Z] (bibliothek)
– Im Attribut Autor treten alle geforderten Werte auf, d.h.
πAutor (σZ=t1[Z] (bibliothek)) = πAutor (σISBN=t1[ISBN] (bibliothek))
Die Notation σZ=t1[Z] soll bedeuten, daß diejenigen Tupel selektiert
werden, deren Werte in Z mit denen von t1 übereinstimmen.
Man nennt die vorstehende Integritätsbedingung eine mehrwertige
Abhängigkeit. Bild 10.10 zeigt die Struktur einer mehrwertigen
Abhängigkeit der Attribute B von den Attributen A an einem allgemeiner gehaltenen Beispiel.
Tabelle: r
R-(A∪B)
xx
xx
xx
yy
yy
yy
uu
uu
vv
vv
A
a1
a1
a1
a1
a1
a1
a2
a2
a2
a2
B
b1
b2
b3
b1
b2
b3
b3
b4
b3
b4
Abbildung 10.10: Beispiel für eine mehrwertige Abhängigkeit A→→B
In diesem Beispiel wird dem Wert a1 in Attribut A die Wertemenge
{b1, b2, b3} in B zugeordnet und dem Wert a2 die Wertemenge {b3,
b4}. Die einzelnen Wertemengen können also völlig verschieden sein
(auch die einzelnen Buchtiteln zugeordneten “Mengen von Autoren”
sind individuell verschieden).
Allgemein ist eine mehrwertige Abhängigkeit wie folgt definiert:
270
Entwurf redundanzfreier Datenbankschemata
Definition: Sei R ein Relationentyp und seien A, B ⊆ R zwei Attributmengen, Z = R - (A∪B) ∪ A52 .
B ist mehrwertig abhängig von A (notiert als A→→B) ⇐⇒ ∀
Relation r mit dem Relationentyp R, ∀ t1, t2 ∈ r :
t1[A] = t2[A] ⇒ πB (σZ=t1[Z] (r)) = πB (σZ=t2[Z] (r))
Im Relationentyp Bibliothek liegt die mehrwertige Abhängigkeit ISBN→→Autor vor. Wenn wir als weiteres mehrwertiges Attribut Stichwort hinzunehmen, hätten wir eine zweite mehrwertige
Abhängigkeit ISBN→→Stichwort. Wenn ein Buch 2 Autoren und 5
Stichworte hat, müssen 10 Tupel für das Buch vorhanden sein: jeder
Autor kombiniert mit jedem Stichwort. Mehrwertige Abhängigkeiten
drücken letztlich aus, daß die Gruppe der Werte der abhängigen Attribute frei kombiniert werden mit den “vorderen” Tupelabschnitten
(vgl. Bild 10.10), daß also eine Art lokaler Verbund gebildet wird.
Formal kann man dies so ausdrücken:
A→→B ⇐⇒ ∀ Relation r mit dem Relationentyp R,
∀a ∈ πA (r) gilt mit ra = σA=a (r):
πR−(A∪B) ∪ B (ra) = πR−(A∪B) (ra) 1 πB (ra)
Wenn man also nur die Tupel mit dem Wert a in A betrachtet und die
Spalten A wegläßt, dann ist der Rest der Verbund aus der Menge der
“links” auftretenden Abschnitte (also πR−(A∪B) (ra)) und der Menge der
“rechts” auftretenden Abschnitte (also πB (ra)).
Durch genaues Hinsehen erkennt man, daß die funktionalen
Abhängigkeiten ein Sonderfall der mehrwertigen Abhängigkeiten sind:
die Menge πB (σZ=t1[Z] (r)) besteht dann nämlich nur noch aus einem
einzigen Tupel, und zwar t1[Z].
Triviale mehrwertige Abhängigkeiten. Triviale mehrwertige
Abhängigkeiten sind solche, die immer aufgrund der Definition gelten
und die somit nichts über den Datenbestand aussagen.
52
vgl. Bild 10.10. A∩B ist nicht unbedingt leer. Unter der Bedingung A∩B = ∅
ist aber Z = R - B.
Entwurf redundanzfreier Datenbankschemata
271
Behauptung: A ⊇ B ⇒ A→→B.
Zu zeigen ist, daß eine Tupelmenge σA=a (r) durch die Attribute B
in gleichmäßige Untergruppen aufgeteilt wird. Wegen A ⊇ B sind in
dieser Tupelmenge in B nur gleiche Werte vorhanden, d.h. alle Untergruppen enthalten genau ein Tupel und unterscheiden sich nur in den
Attributen R - A. Dem Wert a in A wird genau ein Wert in B zugeordnet (nämlich a projiziert auf B). Hiermit ist die Bedingung für die
mehrwertige Abhängigkeit erfüllt.
Formaler Beweis: Durch Einsetzen in der Definition. Es sei t1[A] =
t2[A]. Zu zeigen ist πB (σZ=t1[Z] (r)) = πB (σZ=t2[Z] (r)). B⊆A impliziert
Z = R-(A∪B) ∪ A = R.
Hieraus folgt für ein Tupel t∈r:
σZ=t[Z] (r) = σR=t (r) = {t} und
πB (σZ=t[Z] (r)) = {t[B]}.
Aus t1[A] = t2[A] folgt wegen B⊆A t1[B] = t2[B]. Somit gilt
πB (σZ=t1[Z] (r)) = πB (σZ=t2[Z] (r)).
Behauptung: A ∪ B = R ⇒ A→→B.
Die Annahme A ∪ B = R impliziert B ⊇ R - A. Intuitiv kann man sich
die Behauptung für den Fall B = R - A damit erklären, daß innerhalb
einer Tupelmenge σA=a (r) die Wertetupel in den restlichen Attributen
(R - A) alle verschieden sein müssen, denn in A steht nach Konstruktion
überall a. In den restlichen Attributen tauchen also keine Duplikate
auf, es werden daher gar keine Untergruppen gebildet. Die Bedingung
für die mehrwertige Abhängigkeit ist daher trivialerweise erfüllt. Für
Obermengen von R - A gilt die vorstehende Argumentation erst recht.
Formaler Beweis: Übung (ähnlich wie voriger formaler Beweis).
Anwendungsprobleme. Mit mehrwertigen Abhängigkeiten kann
man leicht unangemessene Konsistenzkriterien erstellen. Dies sei am
folgenden Beispiel illustriert. Wir erweitern unsere Relation bibliothek um ein Feld AkadG, das den akademischen Grad des Autors angibt. Offensichtlich gilt die funktionale Abhängigkeit Autor→AkadG.
Hieraus und aus ISBN→→Autor kann man
272
Entwurf redundanzfreier Datenbankschemata
ISBN→→AkadG
ableiten. Diese mehrwertige Abhängigkeit ist aber unsinnig und zusammen mit der davon unabhängigen Abhängigkeit ISBN→→Autor
sogar falsch. Der Fehler liegt darin, daß die Werte in Autor und AkadG
gerade nicht frei kombinierbar sind. Richtig wären die folgende Menge
von funktionalen und mehrwertigen Abhängigkeiten:
ISBN→→{Autor, AkadG}
Autor→AkadG
D.h. eine ISBN bestimmt eine Menge von Paaren von Werten der
Attribute Autor und AkadG.
Die vierte Normalform. Nichttriviale mehrwertige Abhängigkeiten stellen offensichtlich unerwünschte Redundanzen dar. Es liegt nahe, sie analog zur Boyce-Codd-Normalform zu verbieten:
Definition: Sei (R, M ) ein Relationentyp, M die Menge der für R
gültigen mehrwertigen Abhängigkeiten. (R, M ) ist in vierter Normalform ⇐⇒ ∀ X→→Y ∈ R gilt:
– X→→Y ist trivial
oder
– X→R, d.h. X ist Superschlüssel von R
Der obige Relationentyp Bibliothek ist nicht in vierter Normalform, weil die mehrwertige Abhängigkeit ISBN→→Autor nicht trivial
und {ISBN} kein Superschlüssel von R ist.
Beseitigt werden kann eine störende nichttriviale mehrwertige
Abhängigkeit durch das gleiche Dekompositionsverfahren, das wir
schon bei der Boyce-Codd-Zerlegung kennengelernt haben. Im Fall
des Relationentyps Bibliothek würde also ein separater Relationentyp mit den Attributen ISBN und Autor gebildet und das Attribut
Autor in Bibliothek entfernt. (Der verkleinerte Relationentyp ist
übrigens noch nicht korrekt und muß weiter zerlegt werden. Übungsaufgabe: Wie?)
Entwurf redundanzfreier Datenbankschemata
273
Glossar
Abhängigkeit, funktionale: einer Attributmenge B von einer Attributmenge A: Konsistenzbedingung; wenn zwei Tupel in A die gleichen
Werte haben, haben sie auch in B die gleichen Werte
Abhängigkeit, mehrwertige: einer Attributmenge B von einer Attributmenge A: Konsistenzbedingung; für jeden Wert w in A kann die Menge
der Tupel, die in A den Wert w haben, als Kreuzprodukt einer Menge
von Tupeln über dem Schema B und einer Menge von Tupeln über
den restlichen Attributen dargestellt werden.
Abhängigkeit, transitive: funktionale Abhängigkeit a → B, bei der A kein
Identifizierungsschlüssel ist
Änderungsanomalie: Folgeproblem einer redundanten Datenspeicherung;
bei Änderung eines Sachverhalts müssen viele Tupel verändert werden
Armstrong-Axiome: Satz von grundlegenden Rechenregeln, durch die
funktionale Abhängigkeit abgeleitet werden können
Boyce-Codd-Kriterium: Korrektheitsbegriff für Schemata; auch BoyceCodd-Normalform (BCNF) genannt; verbietet alle Abhängigkeiten außer den trivialen und Schlüsselabhängigkeiten
Boyce-Codd-Zerlegung: Verfahren zum verlustfreien Zerlegen eines Schemas, das das Boyce-Codd-Kriterium nicht erfüllt; die entstehenden
Teilschemata erfüllen das Boyce-Codd-Kriterium
Einfügeanomalie: Folgeproblem einer falschen Datenmodellierung mit
transitiven Abhängigkeiten; beschreibt das Phänomen, daß ggf. künstliche Tupel mit Nullwerten benutzt werden müssen, um bestimmte
Daten abspeichern zu können
Hülle, transitive (einer Menge funktionaler Abhängigkeiten F ): Menge
aller aus F ableitbaren Abhängigkeiten
Löschanomalie: Folgeproblem einer falschen Datenmodellierung mit transitiven Abhängigkeiten; beschreibt das Phänomen, daß ggf. Daten
ungewollt gelöscht werden
Normalform, dritte: Korrektheitsbegriff für Schemata; verbietet alle
Abhängigkeiten außer den trivialen, den Schlüsselabhängigkeiten und
transitiven, bei denen die abhängigen Attribute Teilmenge eines Identifizierungsschlüssels sind
Normalform, vierte: Korrektheitsbegriff für Schemata; verallgemeinert
das Boyce-Codd-Kriterium dahingehend, daß alle mehrwertigen
274
Entwurf redundanzfreier Datenbankschemata
Abhängigkeiten außer den trivialen und den Schlüsselabhängigkeiten
verboten sind
Synthesealgorithmus: Verfahren zur Berechnung einer verlustfreien und
unabhängigen Zerlegung eines Schemas, so daß die Teilschemata in
dritter Normalform sind
Überdeckung, kanonische: einer Menge funktionaler Abhängigkeiten F :
minimale Menge von funktionalen Abhängigkeiten, die zu F äquivalent ist, d.h. die gleiche transitive Hülle wie F hat
Verlustfreiheit: einer Zerlegung eines Schemas:
Zerlegung: eines Schemas S: Aufteilung der Attribute von S in mehrere,
nicht notwendig disjunkte Teilschemata
Zerlegung, unabhängige: eines Schemas S: besagt, daß alle funktionalen
Abhängigkeiten von S durch die “lokalen” Abhängigkeiten der Teilschemata impliziert werden; lokal sind solche Abhängigkeiten, deren
Attribute im dem Teilschema enthalten sind
Literaturverzeichnis
[BaM72] Bayer, R.; McCreight, E.M.: Organization of large ordered
indexes; Acta Informatica 1, p.173-189; 1972
[Co70] Codd, E.F.: A relational model for large shared data banks;
CACM 13:6, p.377-387; 1970/06
[El92] Elmagarmid, A. (ed.): Database transaction models for advanced applications; Morgan Kaufmann; 1992
[Fu05] Fuhr, N.: Information Retrieval (Skriptum zur Vorlesung
im SS 05); Universität Duisburg; http://www.is.informatik.uniduisburg.de/courses/ir ss05/folien/irskall.pdf
[Ke00] Kelter, U.: Das Konzept der Kernfächer in der universitären
Ausbildung in Praktischer Informatik; GI SoftwaretechnikTrends 20:1, p.7-9; 2000/02
[UML-IS06] Unified Modeling Language: Infrastructure, Version 2.0;
OMG, Dokument formal/05-07-05; 2006
[Vo99] Vossen, G.: Datenmodelle, Datenbanksprachen und Datenbank-Management-Systeme; Oldenbourg; 1999
[AMU] Kelter, U.: Lehrmodul “Analysemuster (Stichworte)”; 2006
[DMER] Kelter, U.: Lehrmodul “Datenmodellierung mit ER-Modellen”; 2005
[SASM] Kelter, U.: Lehrmodul “Systemanalyse und Systemmodellierung”; 2003
[SAR] Kelter, U.: Lehrmodul “Software-Architekturen”; 2003
[TAE] Kelter, U.: Lehrmodul “Transformation von Analyse-Datenmodellen in Entwurfsdokumente”; 2003
275
276
Stichwortverzeichnis
[TRD] Kelter, U.: Lehrmodul “Transportdateien und die SGML”;
2004
Stichwortverzeichnis
F + , 236
≈, 236
| .. |, 97
X+ , 236
3-Ebenen-Schema-Architektur, 39, 47,
112, 116
3-Schichten-Architektur, 16, 47
3-Wege-Verbund, s. Verbundberechnung
3NF, 251
Abfrage
interne Darstellung, 170
Intervall-∼, 157, 161
Korrektheitsüberprüfung, 170, 171
Optimierung, 170
Verarbeitung, 170
Zwischenergebnis, 163, 167, 173,
174, 179, 180
Abfragesprache, 170
Abhängigkeit, 228
Ableitung, 232
Analyse, 229
funktionale, 227, 228, 264, 267
graphische Darstellung, 228
Identifizierungsschlüssel, 230
Integritätsbedingung, 230
mehrwertige, 261, 263, 264, 267
Menge von ∼en
Äquivalenz, 235
kanonische Überdeckung,
s.
Überdeckung
transitive Hülle, s. transitive
Hülle
normierte Darstellung, 238, 239
relationsübergreifende, 246
Superschlüssel, 230
transitive, 242, 267
triviale, 228, 264
Überwachung, 235, 257
Verletzung, 231
Administration, 85
Änderungsanomalie, 223, 267
Äquivalenz, 172, 173, 175, 187
Aggregation, 137, 152
Bedingungen, 140
Applikations-Framework, 45
Architektur, 67
Archiv, 27
Armstrong-Axiome, 232, 267
abgeleitete Axiome, 234
graphische Darstellung, 233
Assoziativgesetz, 176
Attribut, 86, 117
Reihenfolge, 87
Wertebereich, 88
Wertzuweisung, 87
Ausführungsplan, 173, 183, 187
Kosten, 173
Auswertungsfunktion, 26
B*-Baum, 63, 65, 112, 157
B-Baum, 65
Ausgleich zwischen Knoten, 60, 63
Einfügung, 58
Löschung, 60
Merkmale, 56
Optimierungsziele, 53, 55, 56, 63
277
278
Ordnung, 56, 65
Suche, 58
Suchgeschwindigkeit, 56, 64
Teilen von Knoten, 59, 62
Überlauf, 58, 59, 65
Unterlauf, 60, 65
Verschmelzen von Knoten, 60, 61,
63
Backup, 27
Basisdatentyp, 51
Basistabelle, 152
Baum, s. Suchbaum
BCNF, 241
Bereichskalkül, 120, 128
Betriebssystem, 33
Block, 74
Blockadreßtabelle, 158
Blockübertragung, 53
Blockungsfaktor, 161
Boyce-Codd-Kriterium, 241, 266, 267
Boyce-Codd-Zerlegung, 243, 267
closure, 236
Codierung, 35
Concurrency Control, 31, 41, 47
Dateimanagementsystem, 74
Dateisystem, 19, 20, 33, 45, 47
journaling, 29
Arraystruktur, 34
indexsequentielles, 34
satzorientiertes, 34
sequentielle Struktur, 34
variable Satzlänge, 34
Verzeichnisstruktur, 34
zeichenorientiertes, 34
Daten, 14
externe Darstellung, 17
alternative, 17
formatierte, 35
Layout-∼, 18
unscharfe, 43
unsichere, 45
Stichwortverzeichnis
Datenbank, 20, 86
Datenbankmanagementsystem, 19, 47
Datenbankmodell, 38, 47
hierarchisches, 47
konventionelles, 85
Netzwerk-, 47
nichtkonventionelles, 38
relationales, 85, 86
Datenbankschema, 221, 231
Entwurfsfehler, 222, 224
Datenbanksprache, 85
Datenbanksystem, 20
Datendefinitionssprache, 38, 47
Datenintegration, 32, 48
Datenmodell, 221
navigierendes, 170
Datenmodellierung, 23
Datentransport, 27
Datenunabhängigkeit, 33
Datenverlust, 221, 224
Datenverwaltungssystem, 18, 48
Auswahl, 19
Dienstprogramme, 22
Laufzeitkern, 22
DB2, 130
DBMS, 19
Administration, 67
erweiterbares, 20
Laufzeitkern, 67
DBS, 20
deduktive Datenbank, 19
Dienstprogramm, 22
directory [S,I], s. Verzeichnis
Distributivgesetz, 176
Division, 103, 117, 124
Dokumentarchivierungssystem, 19
Dokumenttypdefinition, 36
DTD, 36, 208
Duplikate, 87, 89, 132
Duplikateliminierung, 184
DVS, 18
Editor, 36
Stichwortverzeichnis
Einfügeanomalie, 224, 267
Entwurfsdatenbank, 19
equi-join, 103
Erweiterungsregel, 233
Fakten, 15, 45
Formatierung, 191
Fremdschlüssel, s. Schlüssel
funktionale Abhängigkeit, s. Abhängigkeit
gADT, 51
generischer abstrakter Datentyp, 51, 65
directory [S,I], 52
Typ-Parameter, 51
Geo-Datenbank, 19
Gleichheitsverbund, 103
Grammatik, 208
Gruppierung, 137, 139
Hash-Verfahren, 157
erweiterbares, 158, 167
Hauptspeicher, 74
Heterogenität von Rechnern, 30
hierarchisches Datenbankmodell, 38
Hülle, s. transitive Hülle
transitive, 267
Identifizierungsschlüssel, s. Schlüssel
Implementierungsebenen von Datenbankobjekten, 206, 211
Index, 40, 80, 83, 157
Indexblock, 157
Indexknoten, 64
Information, 14, 15
Repräsentation, 16, 44
Information Retrieval, 42, 44
Informationssystem, 16
Inkonsistenz, 223
Instanz-von-Beziehung, 198, 216
Integritätsbedingung, 90, 230
dynamische, 90
statische, 90
Überprüfung, 90
279
Interaktivität, 43
invertierter Datenbestand, 159, 168
IR-System, 19, 24, 28, 42
Kalkül, s. relationale Kalküle
kanonische Überdeckung, s. Überdeckung
Katalog, 146, 152
Kommutativgesetz, 175
Konsistenz, 222, 225, 226, 265
Korrekheitsüberwachung, 24
Korrektheit, s. Konsistenz
Kostenmaß, 175
Kostenschätzung, 183
Kreuzprodukt, 185
Projektion, 184
Selektion, 184
Verbund, 185
Kreuzprodukt, 96, 101, 103, 131, 175–
178, 180, 181, 185
Längenfeld, 80
Laufzeitkern, 22, 67, 83
Layout-Daten, 18, 191
linksminimal, 237
Löschanomalie, 224, 267
lokale Überwachbarkeit, 246
Medienadresse, 74, 75
Mehrbenutzerzugriff, 29, 69
mehrwertige Abhängigkeit, 263
mehrwertiges Attribut, 259
memory-mapped IO, 23
Mengenoperationen, 123, 175, 176
Meta-CASE, 215, 218
Meta-Metadaten, 202–204, 219
Metadaten, 189, 190, 219
administrative, 191
entitätsbezogene, 195
Hierarchie, 203, 204
in Datenbanken, 189, 190
in der Dokumentverwaltung, 189,
191
280
in Programmen, 189
instantiierbare, 196–198
Instanzbildung, 197
Nutzung, 192
persistente, 190
semantische, 190
Speicherung, 192, 193, 206
transiente, 190
Typ-Annotationen, 209
typbezogene, 195, 209
vs. Nutzdaten, 192, 194
Metamodell, 214
UML∼ - Ebene M0, 213
UML∼ - Ebene M1, 213, 217
UML∼ - Ebene M2, 214, 218
Metaschema, 202, 219
Metasprache erster Stufe, 194
Metasprache zweiter Stufe, 195
Metatyp, 202
Misch-Verbund, s. Verbundberechnung
Modellierung, 16
Multimedia-Datenbank, 19
natural join, 101
nested loop join, 163
Netzwerk-Datenbankmodell, 38
Normalform, 32, 48, 222, 241
non first normal form, 260
Boyce-Codd-, 241
dritte, 251, 267
Zerlegung, 252
erste, 258
vierte, 266, 267
zweite, 261
normierte Darstellung, s. Abhängigkeit
Notationskonventionen, 89
Nullwert, 103, 142, 144, 153
Aggregationsoperatoren, 146
Vergleich, 145
Nutzdaten, 53, 189, 219
Objektsprache, 194
OLAP-System, 19
Stichwortverzeichnis
OLTP, 19, 48
OLTP-System, 24, 26, 37, 41
Versionierung, 27
Operationsaufruf
entfernter, 71
Optimierer, 173
Optimierung, 82, 108, 171, 187
Abarbeitung von Ausdrücken, 172
algebraische, 173, 175, 187
Algorithmus, 181
Ansätze, 171
Heuristik, 179
interne, 173, 187
Kostenmaß, 175
Kostenschätzung,
s.
Kostenschätzung
Kriterien, 174
Meßgrößen, 174
Projektion, 163
relative, 174
Selektion, 160
Verbundberechnung, 163
von Elementaroperationen, 155,
171
zusammengefaßte
Operationen,
180
Ordnung, s. B-Baum
Parallelität, 31
Persistenz, 18
Primärindex, 58, 81, 83, 157
Primärschlüssel, s. Schlüssel
Projektion, 93, 117, 122, 132, 176–178,
181, 184
Prozeßarchitektur, 68
1-Prozeß, 69
von Informationssystemen, 70
Pseudotransitivitätsregel, 235
QMF, 130
Rechteverwaltung, 85
rechtsminimal, 237
Stichwortverzeichnis
Recovery, 28, 48
Redundanz, 221, 223, 242, 260
referentielle Integrität, 113
Reflexivitätsregel, 233
Relation, 39, 88
virtuelle, 171
relationale Algebra, 91, 117, 127, 133,
170
äußerer Verbund, 103
Ausdrücke, 108
Auswertung, 108
Differenz, 94
Division, 103
Gleichheitsverbund, 102
Kreuzprodukt, 96
natürlicher Verbund, 100
Projektion, 93
Schnitt, 94
Theta-Verbund, 102
Umbenennung, 95
Vereinigung, 94
relationale Kalküle, 86, 120
relationale Vollständigkeit, 108, 126
relationales Datenbankmodell, 38
Relationenformat, 88
Relationenschema, 88, 117
Relationentyp, 88
als Menge von Attributen, 89
Normalform, 241
Notation, 231
Qualitätskriterien, 241
Relevanz, 25
remote procedure call, 70
Rolle, 32
RTK, 120
sr , 160
Satz, 83
feste Länge, 79
Inhalt, 52, 63
Realisierung, 79
Schlüsselwert, 52
variable Länge, 80
281
Schaden, 28
Schema, 48, 85, 146, 190, 196–198, 214
Änderung, 151
externes, 41
generische DVS-Funktionen, 197
Konfigurierung, 203
internes, 40, 190
konzeptuelles, 40
Schichtenmodell, 73
Schlüssel, 109, 110, 113, 117
als Integritätsbedingungen, 111
Fremdschlüssel, 114, 116, 117, 149,
165, 185
Identifizierungsschlüssel, 24, 39,
110, 117, 148, 185, 230, 258
Auswahlkriterien, 114
künstlicher, 113
Prüfung, 111
Wiederverwendung
von
Schlüsselwerten, 115
Primärschlüssel, 57, 112, 113, 116,
117, 149
Auswahl, 112
Schlüsselattribut, 110
Schlüsselkandidat, 115–117
Sekundärschlüssel, 116, 117
Sortierschlüssel, 115–117
Suchschlüssel, 159
Superschlüssel, 110, 116, 117, 230,
232, 236
Schlüsselkandidat, s. Schlüssel
Schlüsselwert, 34, 52, 78, 110
Schlüsselwertbereich, 55, 78
Intervall, 55
secondary key, 116
Segment, 73
Seite, 73, 75, 79, 83
Sekundärindex, 81, 83, 159, 162, 165,
168, 258
Aktualisierung, 159
Sekundärschlüssel, s. Schlüssel
Selbstreferentialität, 193, 219
Änderung von Metadaten, 201, 202
282
Stichwortverzeichnis
bei
administrativen Metadaten,
200
bei Metatypen, 206
bei schwach strukturierten Daten,
209
bei Sprachen, 208
in relationalen Datenbanken, 199
in XML, 208
UML, 212
Selektion, 91, 117, 121, 132, 133, 176,
177, 179, 181, 184
Bedingung mit all-Quantor, 106
komplexe ∼sbedingung, 176
Selektivität, 161, 168
Semantik, 15, 45
semantische Modellierung, 16
SEQUEL, 130
Serverprozeß, 70, 83
Kommunikationsaufwand, 71
Sicherheit, 70, 128
RTK-Ausdrücke, 125
Sicht, 32, 41, 152, 153
Sichtenauflösung, 171, 187
sort key, 115
Sortierschlüssel, s. Schlüssel
Spalte, 86, 117
Speichermedium
Einkapselung, 21
persistentes, 18, 21
Speichersatz, 73, 83
Sperrverfahren, 31
Sprachebenen, 194
SQL, 130, 153
ALL-Operatoren, 137
ALTER TABLE-Kommando, 151
AVG, 138
CASCADE, 150
CHAR, 147
COUNT, 138
CREATE DOMAIN-Kommando, 148
CREATE TABLE-Kommando, 147
CREATE VIEW-Kommando, 152
DATE, 148
DEC, 147
DEFAULT, 148
DELETE-Kommando, 142
DISTINCT, 132
DROP-Kommando, 152
FLOAT, 148
FOREIGN KEY, 149
FROM-Klausel, 131
GROUP BY-Klausel, 138
HAVING-Klausel, 141
INSERT-Kommando, 141
INT, 148
IS NULL, 146
LIKE, 134
MAX, 138
MIN, 138
NATURAL JOIN, 135
NO ACTION, 150
NOT, 134, 136, 146
NULL, 145
ON DELETE, 151
ON UPDATE, 151
ORDER BY, 137
PRIMARY KEY, 149
SELECT-Klausel, 132
SET DEFAULT, 151
SET NULL, 151
SOME-Operatoren, 137
SUM, 138
UNIQUE, 148
UPDATE-Kommando, 144
VALUES-Klausel, 142
VARCHAR, 147
WHERE-Klausel, 131
API, 131
Attributdefinition, 147
geschachtelte Abfragen, 136, 141,
143, 144
Integritätsbedingungen, 148
interaktive Sprache, 131
Tupelvariable, 135
SQL/Data System, 130
SQL1, 130
Stichwortverzeichnis
SQL2, 130
SQL3, 131
SQL86, 130
SQL92, 130
SRTK, 126
Standardeditoren, 45
Suchbaum, 51
Balancierung, 59
Effizienz, 50, 60
Verzweigungsgrad, 63
Vielweg-∼, 54, 55
Suche, 25
exakte, 25
in Dateien, 37
vage, 25, 42, 44
Superschlüssel, s. Schlüssel
Syntax, 15, 35
Synthesealgorithmus, 254, 268
Systemabsturz, 28
t[A], 93
Tabelle, 86, 117
tag, 36
Textprozessor, 37
Transaktion, 41, 48
transitive Hülle, 235, 236
Algorithmus, 237
Transitivitätsregel, 233
Trennschlüsselwert, 55
Tupel, 88, 118
Tupel-Kalkül, 120, 121, 128
sichere Ausdrücke, 125
Syntax von Ausdrücken, 124
Tupelvermehrung, 225, 228
Typ-Annotationen, 209, 219
Typ-Parameter, 51
Typkonstruktor, 51
Überdeckung
kanonische, 237, 238, 268
Berechnung, 238
Eindeutigkeit, 240
Minimalität, 240
283
Überlauf, s. B-Baum
Umbenennung, 95
unabhängig, 247
Unterlauf, s. B-Baum
V(A,r), 161, 185
Verbund, 118, 123, 135, 175–177, 180–
182, 185
äußerer, 103, 118
Gleichheits-, 102, 118
natürlicher, 100, 118
Theta-, 102, 118
Verbundattribute, 101
Verbundberechnung
3-Wege-Verbund, 167
blockorientiertes Iterieren, 164
einfaches Iterieren, 163, 167
Misch-Verbund, 166, 168
mit Index, 165
Verbundpartner, 101
Vereinigungsregel, 234
Verlustfreiheit, s. Zerlegung
Versionierung, 27
Verteilung, 30
Verzeichnis, 50, 52, 65
∼-Operationen, 52
Vielweg-Suchbaum, 55, 65
view, 41, 152
Vollständigkeit, 107
wechselseitiger Ausschluß, 31
Wissen, 15, 45
XML, 19, 36
Zeile, 86, 118
Zerlegung, 226, 268
Boyce-Codd-∼, 243
Synthesealgorithmus, 254
unabhängige, 247, 249, 254, 268
verlustbehaftete, 226
verlustfreie, 226, 231, 232, 244, 249,
255, 268
Zerlegungsregel, 235
284
Zugriffskontrollen, 29, 69
Administration von Rechten, 29
Zugriffsmethode, 75, 83
Zugriffsstruktur, 76, 83
Direktzugriffsstruktur, 77, 79
sequentielle, 76, 77
Verzeichnisstruktur, 77
Stichwortverzeichnis
Herunterladen