online im PDF-Format - DBAI

Werbung
Skriptum zur Vorlesung
DATENBANKSYSTEME
VO 181.038 (alter Studienplan)
VO 181.146 (neuer Studienplan)
WS 2002
Gerald Pfeifer
Michael Schrefl
Katrin Seyr
Markus Stumptner
0.2
Inhaltsverzeichnis
I Allgemeines
1
1
Einleitung
1.1 Das Datenbanksystem . . . . . . . . . . . . . . . . . . . . . . . .
1.1.1 Die Hardware . . . . . . . . . . . . . . . . . . . . . . . .
1.1.2 Die Software . . . . . . . . . . . . . . . . . . . . . . . .
1.1.3 Die Daten . . . . . . . . . . . . . . . . . . . . . . . . . .
1.1.4 Die Benutzer . . . . . . . . . . . . . . . . . . . . . . . .
1.2 Warum ein Datenbanksystem? . . . . . . . . . . . . . . . . . . .
1.2.1 Von Einzellösungen zu Datenbanksystemen . . . . . . . .
1.2.2 Funktionalität von Datenbanksystemen . . . . . . . . . .
1.2.2.1 Persistente Datenhaltung . . . . . . . . . . . .
1.2.2.2 Hintergrundspeicherverwaltung . . . . . . . . .
1.2.2.3 Recovery . . . . . . . . . . . . . . . . . . . . .
1.2.2.4 Concurrency Control . . . . . . . . . . . . . .
1.2.2.5 Ad-hoc-Abfragen . . . . . . . . . . . . . . . .
1.2.2.6 Datenschutz . . . . . . . . . . . . . . . . . . .
1.2.3 Komponenten eines Datenbanksystems . . . . . . . . . .
1.2.4 Vorteile des Einsatzes von Datenbanksystemen . . . . . .
1.3 Architektur eines Datenbanksystems . . . . . . . . . . . . . . . .
1.4 Die Datenmodellierung . . . . . . . . . . . . . . . . . . . . . . .
1.4.1 Begriffe . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.4.2 Datenmodelle im Datenbankentwurf . . . . . . . . . . . .
1.5 Der Datenbank-Life-Cycle“ . . . . . . . . . . . . . . . . . . . .
”
1.5.1 Die Anforderungsanalyse . . . . . . . . . . . . . . . . . .
1.5.2 Der konzeptionelle Entwurf . . . . . . . . . . . . . . . .
1.5.3 Der logische Entwurf . . . . . . . . . . . . . . . . . . . .
1.5.4 Der physische Entwurf . . . . . . . . . . . . . . . . . . .
1.5.5 Verteilter Entwurf . . . . . . . . . . . . . . . . . . . . . .
1.5.6 Datenbankimplementierung, -überwachung und -wartung .
Literaturverzeichnis
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
2
2
3
3
4
5
6
7
7
8
9
11
12
12
13
16
17
18
18
19
19
20
22
23
24
24
1
i
INHALTSVERZEICHNIS
0.ii
II Datenmodellierung
2
3
1
Konzeptionelle Datenmodelle und das ER Modell
2.1 Modellierungskonzepte konzeptioneller Datenmodelle . . . . . . .
2.2 Elementare ER-Konstrukte . . . . . . . . . . . . . . . . . . . . . .
2.2.1 Grundlegende Objekte: Entities, Beziehungen und Attribute
2.2.2 Komplexität einer Beziehung . . . . . . . . . . . . . . . . .
2.2.3 Existenz einer Entity in einer Beziehung . . . . . . . . . . .
2.2.4 Grad einer Beziehung . . . . . . . . . . . . . . . . . . . .
2.2.5 Attribute einer Beziehung . . . . . . . . . . . . . . . . . .
2.3 Erweiterte ER-Konstrukte . . . . . . . . . . . . . . . . . . . . . . .
2.3.1 Die Generalisierung . . . . . . . . . . . . . . . . . . . . .
2.3.2 ER-Constraints . . . . . . . . . . . . . . . . . . . . . . . .
2.3.2.1 Exklusionsbedingungen . . . . . . . . . . . . . .
2.4 Objektorientierte Datenmodellierung . . . . . . . . . . . . . . . . .
2.4.1 Objektorientierte Konzepte . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
2
3
3
6
7
8
9
10
10
11
12
13
13
Das Relationenmodell
3.1 Formalisierung des Relationenmodells . . . . . . . . . . .
3.2 Operationen auf Relationen . . . . . . . . . . . . . . . . .
3.2.1 Die Mengenoperationen . . . . . . . . . . . . . .
3.2.2 Die Selektion . . . . . . . . . . . . . . . . . . . .
3.2.2.1 Erweiterung der Selektion . . . . . . . .
3.2.3 Die Projektion . . . . . . . . . . . . . . . . . . .
3.2.4 Der Verbund . . . . . . . . . . . . . . . . . . . .
3.2.4.1 Der natürliche Verbund (natural join) . .
3.2.4.2 Das Kartesische Produkt . . . . . . . . .
3.2.4.3 Der Gleichverbund (equi-join) . . . . .
3.2.4.4 Der Theta-Verbund (theta-join) . . . . .
3.2.5 Die Division . . . . . . . . . . . . . . . . . . . .
3.2.6 Der Semiverbund (semijoin) . . . . . . . . . . . .
3.3 Nullwerte . . . . . . . . . . . . . . . . . . . . . . . . . .
3.3.1 Auswertung von Nullwerten . . . . . . . . . . . .
3.3.2 Äußerer Verbund (outer join) . . . . . . . . . . . .
3.4 Übersetzung des ER ins Relationenmodell . . . . . . . . .
3.5 NF2 -Relationen . . . . . . . . . . . . . . . . . . . . . . .
3.6 Weitere Sprachen für das Relationenmodell . . . . . . . .
3.6.1 Der Relationenkalkül . . . . . . . . . . . . . . . .
3.6.1.1 Der Relationenkalkül mit Tupelvariablen
3.6.1.2 QBE — Query By Example . . . . . . .
3.7 Übungsbeispiele . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
4
4
5
6
6
7
7
7
9
10
11
12
13
14
14
15
16
16
18
18
18
21
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
INHALTSVERZEICHNIS
4
5
0.iii
SQL
4.1 Interaktives SQL . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.1.1 Allgemeines . . . . . . . . . . . . . . . . . . . . . . . . .
4.1.2 Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . .
4.1.3 Abfragen . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.1.3.1 Grundkonstruktion einer SQL-Abfrage . . . . . .
4.1.3.2 Mengenoperationen . . . . . . . . . . . . . . . .
4.1.3.3 Gruppierung und Aggregatfunktionen . . . . . . .
4.1.3.4 Teilabfragen . . . . . . . . . . . . . . . . . . . .
4.1.4 Nullwerte . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.1.4.1 Der Outer Join in SQL . . . . . . . . . . . . . . .
4.1.5 Datendefinition . . . . . . . . . . . . . . . . . . . . . . . .
4.1.5.1 Erzeugen von Relationenschemata . . . . . . . .
4.1.5.2 Globale Integritätsbedingungen . . . . . . . . . .
4.1.5.3 Ändern von Relationenschemata . . . . . . . . .
4.1.5.4 Entfernen von Relationenschemata . . . . . . . .
4.1.6 Datenmanipulation . . . . . . . . . . . . . . . . . . . . . .
4.1.6.1 Einfügen von Daten . . . . . . . . . . . . . . . .
4.1.6.2 Löschen von Daten . . . . . . . . . . . . . . . .
4.1.6.3 Ändern von Daten . . . . . . . . . . . . . . . . .
4.1.7 Benutzersichten . . . . . . . . . . . . . . . . . . . . . . . .
4.1.8 Zugriffskontrolle . . . . . . . . . . . . . . . . . . . . . . .
4.1.9 Transaktionsverwaltung . . . . . . . . . . . . . . . . . . .
4.1.10 Definition von Dateiorganisationsformen und Zugriffspfaden
4.1.11 Abstrakte Datentypen . . . . . . . . . . . . . . . . . . . . .
4.1.12 Rekursion in SQL-3 . . . . . . . . . . . . . . . . . . . . .
4.1.13 Trigger in SQL-3 . . . . . . . . . . . . . . . . . . . . . . .
4.2 Embedded SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2.1 Prinzip der Einbindung . . . . . . . . . . . . . . . . . . . .
4.2.2 Cursor . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.3 SQL-2 versus SQL-3 Standard . . . . . . . . . . . . . . . . . . . .
4.4 Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
2
2
2
4
5
7
7
8
10
13
14
14
15
16
16
16
16
17
17
18
19
20
20
20
22
25
26
26
27
27
30
Datalog
5.1 Motivation . . . . . . . . . . . . . . . . . . . . .
5.2 Die Syntax von Datalog . . . . . . . . . . . . . .
5.2.1 Einschränkungen zur Syntax von Datalog
5.3 Semantik von Datalog . . . . . . . . . . . . . . .
5.3.1 Logische Semantik von Datalog . . . . .
5.3.2 Operationale Semantik von Datalog . . .
5.4 Erweitertes Datalog mit Negation . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
1
2
3
3
5
9
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
0.iv
5.5
6
7
8
INHALTSVERZEICHNIS
5.4.1 Graphendarstellung . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.4.2 Semanik von Datalog mit Negation . . . . . . . . . . . . . . . . . .
Übungsbeispiele . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Funktionale Abhängigkeiten
6.1 Definition von funktionalen Abhängigkeiten . . . . . . . . .
6.2 Ableitungsregeln für funktionale Abhängigkeiten . . . . . .
6.3 Äquivalenz von Systemen von funktionalen Abhängigkeiten
6.4 Inklusionsabhängigkeiten . . . . . . . . . . . . . . . . . . .
6.4.1 Definition von Inklusionsabhängigkeiten . . . . . .
6.4.2 Ableitungsregeln für Inklusionsabhängigkeiten . . .
6.5 Übungsbeispiele . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Normalformen
7.1 Erste und Zweite Normalform . . . . . . . . . . . . . . . . . . . . . . .
7.2 Die Dritte Normalform . . . . . . . . . . . . . . . . . . . . . . . . . . .
7.3 Die Boyce-Codd Normalform . . . . . . . . . . . . . . . . . . . . . . .
7.4 Zerlegungen von Relationenschemata . . . . . . . . . . . . . . . . . . .
7.4.1 Verbundtreue Zerlegung in 3NF bzw. BCNF . . . . . . . . . . . .
7.4.2 Verbund- und abhängigkeitstreue Zerlegung in 3NF bzw. BCNF .
7.4.3 Berechnung von Überdeckungen für eingebettete Abhängigkeiten
7.4.3.1 Der Algorithmus RBR (Reduction By Resolution) . . .
7.4.4 Der Synthesealgorithmus . . . . . . . . . . . . . . . . . . . . . .
7.5 Übungsbeispiele . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Physisches Datenbankdesign
8.1 Grundlegende Begriffe . . . . . . . . . . . . . . . . . . . . .
8.1.1 Clustering . . . . . . . . . . . . . . . . . . . . . . . .
8.1.1.1 Clustering-Index . . . . . . . . . . . . . . .
8.1.1.2 Geclusterte Speicherung von Datensätzen .
8.1.2 Primär- und Sekundärorganisation . . . . . . . . . . .
8.2 Speicherstrukturen für Relationen . . . . . . . . . . . . . . .
8.2.1 Kriterien zur Auswahl von Speicherstrukturen . . . . .
8.2.1.1 Ungeordnete Dateien . . . . . . . . . . . .
8.2.1.2 Indexsequentielle Dateien . . . . . . . . . .
8.2.1.3 Clustered . . . . . . . . . . . . . . . . . . .
8.2.1.4 Hashorganisation . . . . . . . . . . . . . .
8.2.1.5 B ∗ -Baum . . . . . . . . . . . . . . . . . .
8.2.2 Füllgrad . . . . . . . . . . . . . . . . . . . . . . . . .
8.2.3 Zugriffszeitverhalten . . . . . . . . . . . . . . . . . .
8.2.4 Physische Datenorganisation in kommerziellen DBMS
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
10
11
14
.
.
.
.
.
.
.
1
1
3
5
9
9
9
11
.
.
.
.
.
.
.
.
.
.
1
1
3
5
5
8
11
13
15
15
17
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
1
2
2
3
3
3
4
5
5
6
7
8
9
10
INHALTSVERZEICHNIS
8.2.4.1
8.2.4.2
8.2.4.3
0.v
INGRES . . . . . . . . . . . . . . . . . . . . . . . . . . .
ORACLE . . . . . . . . . . . . . . . . . . . . . . . . . .
MS-SQL Server . . . . . . . . . . . . . . . . . . . . . . .
III Das Datenbankmanagementsystem
9
1
Optimierung
9.1 Logische Abfragenoptimierung . . . . . . . . . . . . . . .
9.1.1 Algebraische Optimierung . . . . . . . . . . . . .
9.1.1.1 Zusammenfassen gleicher Teilausdrücke
9.1.1.2 Regeln für Join und kartesisches Produkt
9.1.1.3 Regeln für Selektion und Projektion . .
9.1.2 Ein einfacher Optimierungsalgorithmus . . . . . .
9.2 Join-Algorithmen . . . . . . . . . . . . . . . . . . . . . .
9.2.1 Nested-loop Join . . . . . . . . . . . . . . . . . .
9.2.2 Join mit Hilfe von Indexen . . . . . . . . . . . . .
9.2.3 Hash-Join . . . . . . . . . . . . . . . . . . . . . .
9.2.4 Clustering . . . . . . . . . . . . . . . . . . . . . .
9.3 Der Semijoin (Semiverbund) . . . . . . . . . . . . . . . .
9.4 Übungsbeispiele . . . . . . . . . . . . . . . . . . . . . . .
10 Concurrency Control
10.1 Begriffsklärungen . . . . . . . . . . . . . . . . . . . . .
10.1.1 Synchronisationsprobleme . . . . . . . . . . . .
10.1.2 ACID Eigenschaften von Transaktionen . . . . .
10.1.3 Ausführung mehrerer Transaktionen . . . . . . .
10.1.4 Konfliktrelation einer Ausführung . . . . . . . .
10.1.5 Serialisierbarkeit . . . . . . . . . . . . . . . . .
10.1.6 Test auf Serialisierbarkeit . . . . . . . . . . . .
10.2 Sperrprotokolle . . . . . . . . . . . . . . . . . . . . . .
10.2.1 Gültige Ausführungen . . . . . . . . . . . . . .
10.2.2 Wohlgeformte Transaktionen . . . . . . . . . . .
10.2.3 Das 2-Phasen-Sperrverfahren (2-Phase-Locking)
10.2.4 Deadlock . . . . . . . . . . . . . . . . . . . . .
10.2.5 Das Baumprotokoll . . . . . . . . . . . . . . . .
10.2.6 Das Hierarchische Sperrprotokoll . . . . . . . .
10.3 Zeitstempelverfahren (Time Stamping) . . . . . . . . . .
10.4 Transaktionen in SQL . . . . . . . . . . . . . . . . . . .
10.5 Übungsbeispiele . . . . . . . . . . . . . . . . . . . . . .
10
10
10
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
2
3
3
3
5
7
7
8
9
9
10
11
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
3
5
6
7
9
10
10
11
12
13
14
14
15
17
19
21
0.vi
INHALTSVERZEICHNIS
11 Wiederanlauf (Recovery)
11.1 Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11.1.1 Zielsetzung . . . . . . . . . . . . . . . . . . . . . . . . .
11.1.2 Reihenfolge von Ausführungen . . . . . . . . . . . . . .
11.1.3 Nichtwiederherstellbare Ausführung . . . . . . . . . . . .
11.1.4 ACA Ausführungen . . . . . . . . . . . . . . . . . . . .
11.1.5 Strikte Ausführung von Transaktionen . . . . . . . . . . .
11.2 Pufferverwaltung . . . . . . . . . . . . . . . . . . . . . . . . . .
11.2.1 Privater Arbeitsbereich . . . . . . . . . . . . . . . . . . .
11.2.2 Write Ahead-Protokoll . . . . . . . . . . . . . . . . . . .
11.3 Wiederanlaufverfahren mit Logprotokoll . . . . . . . . . . . . . .
11.3.1 Das Logprotokoll . . . . . . . . . . . . . . . . . . . . . .
11.3.2 Wiederanlauf nach einem Transaktionsabbruch . . . . . .
11.3.3 Wiederanlauf nach einem Systemabsturz . . . . . . . . .
11.3.4 Checkpoints . . . . . . . . . . . . . . . . . . . . . . . .
11.3.5 Wiederanlauf mit Checkpoints nach einem Systemabsturz
11.3.6 Wiederanlauf nach einem Plattenfehler . . . . . . . . . .
11.4 Schattenkopieverfahren (shadow paging) . . . . . . . . . . . . . .
11.4.1 Die Grundidee . . . . . . . . . . . . . . . . . . . . . . .
11.4.2 Die Realisierung . . . . . . . . . . . . . . . . . . . . . .
11.5 Übungsbeispiele . . . . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
1
3
3
4
4
6
8
9
9
9
11
11
12
12
14
16
16
16
19
Teil I
Allgemeines
1
Kapitel 1
Einleitung
1.1 Das Datenbanksystem
Ein Datenbanksystem (DBS) ist ein computerisiertes System, das Information speichert und
bei Bedarf zur Verfügung stellt. Unter Information verstehen wir in diesem Zusammenhang
nicht nur den reinen Wert der Daten, sondern auch deren Bedeutung für die Benutzer. Das
Datenbanksystem ist Teil eines Informationssystems. Unter diesem Oberbegriff werden alle
Systeme zusammengefasst, die einerseits Informationen über bestimmte Anwendungen bzw.
Außenweltsituationen (z.B. customer relationship management einer Firma, eine Bibliothek,
Börsenkurse usw.) speichern und (zentral) verwalten. Andererseits ermöglichen sie aber auch
das Arbeiten mit diesen Informationen nach bestimmten Gesichtspunkten bzw. mit verschiedenen Zielsetzungen, insbesondere auch von anderen Programmen aus.
Definition 1.1 [Vossen 1999] Ein Informationssystem ist ein Werkzeug zur Erfassung und
Kommunikation von Information zum Zwecke der Erfüllung der Anforderungen seiner Benutzer, der (Geschäfts-) Aktivitäten ihres Unternehmens und zur Erreichung der Unternehmensziele. Daher unterstützt ein Informationssystem die Unternehmensaktivitäten durch Bereitstellung der benötigten Information oder durch Automatisierung der mit den Aktivitäten
zusammenhängenden Vorgänge. Es umfasst sämtliche zu diesem Zweck im Unternehmen vorhandenen Ressourcen, d.h. die Daten, die Datenbanksoftware, die nötige Rechner-Hardware,
die Personen, die die Daten nutzen und verwalten, die relevante Anwendungssoftware sowie
die Programmierer, die diese entwickeln.
Grob gesehen interagieren vier Komponenten in einem Informationssystem: Hardware,
Software, die Daten und die Benutzer (siehe Abbildung 1.1). Die Software (das Datenbankmanagementsystem, DBMS) und die Daten (die Datenbank, DB) bilden gemeinsam das eigentliche Datenbanksystem.
1
KAPITEL 1. EINLEITUNG
1.2
Datenbankmanagementsystem
Datenbank
Daten
Daten
Applikationsprogramme
Endbenutzer
Abbildung 1.1: Vereinfachte Sicht eines Informationssystems
1.1.1 Die Hardware
Auf die Hardware werden wir im Weiteren nicht näher eingehen, da dies den Rahmen dieser Lehrveranstaltung sprengen würde. Wir wollen an dieser Stelle nur aufzählen, welche
Hardware für den Betrieb eines Datenbanksystems notwendig ist:
• Das Rechnersystem: Prozessoren, Caches, Hauptspeicher, Buffer, die zur Ausführung
der Datenbanksystemsoftware notwendig sind.
• Der Sekundärspeicher: meist Platten- und Bandsysteme, die einerseits die Daten und
andererseits Datenstrukturen zum schnellen Zugriff (Indexe) und zur Datensicherung
(Logs) lokal speichern und den dazugehörigen Input/Output Devices. Weiters sind noch
Backup-Geräte zur Sicherung der Daten notwendig.
• ein Kommunikationssystem/Rechnernetz, wenn das Datenbanksystem nicht im singleuser Betrieb laufen soll.
1.1.2 Die Software
Das Datenbankmanagementsystem (DBMS) ist jener Teil der Software, der zwischen den eigentlichen Daten und den Benutzern dieser Daten liegt und alle Anfragen der Benutzer verarbeitet. Es stellt jene Einrichtungen zur Verfügung, die notwendig sind, um neue Daten
anzulegen, Daten zu löschen, Daten abzufragen und Daten zu verändern. Das DBMS ist auch
dafür zuständig, alle hardwarespezifischen Details vor dem Benutzer zu verbergen und so
transparent zu machen. Dazu gehören z.B. die Anzahl der Platten oder generell die konkrete
Datenstruktur der gespeicherten Daten sowie die Anzahl der Prozessoren und Speichergrößen,
die zur Datenverarbeitung eingesetzt werden. Weiters realisiert ein DBMS die üblicherweise
erwartete Datenbankfunktionalität wie persistente Datenhaltung, Hintergrundspeicherverwaltung, Recovery (Wiederanlauf) und Concurrency Control (Synchronisation).
KAPITEL 1. EINLEITUNG
1.3
Heutzutage existiert eine Vielfalt von DBMSen sowohl kommerzieller als auch freier Natur, deren Einsatz von Handhelds bis hin zu Großrechnern und massiven Clustern reicht. Daher ist sowohl Multi-user Betrieb als auch Single-user Betrieb zu ermöglichen. In einem
Single-user System wird zu einem bestimmten Zeitpunkt von maximal einem Benutzer auf
die Daten zugegriffen, während in einem Multi-user System viele Benutzer gleichzeitig auf
die Daten zugreifen. Beispiele für Multi-user Systeme sind Buchungssysteme von Fluglinien
oder Anwendungen im Bankenbereich. Eine weitere Aufgabe von DBMSen im Multi-user
Betrieb ist, den Benutzern die Sicht eines single-user Betriebs auf die Daten zu geben. Probleme, die in diesem Zusammenhang entstehen, werden in Kapitel 10 behandelt.
Die Software besteht heutzutage aber nicht nur aus dem DBMS, sondern auch aus Entwicklungsumgebungen, Designhilfen, Report Writern und so weiter. Die Behandlung dieser
Werkzeuge würde jedoch den Umfang dieser Lehrveranstaltung sprengen.
1.1.3 Die Daten
Die Daten werden vom DBMS in einer Datenbank abgelegt. Eine Datenbank ist also eine Art
Behälter, der eine Menge von logisch zusammengehörigen Daten enthält. In einem DBMS
können mehrere verschiedene Datenbanken enthalten sein und eine Applikation kann auch
auf mehrere Datenbanken zugreifen. Die Beschreibung der Daten einer Datenbank mit Hilfe
eines Datenmodells wird als Datenbankschema bezeichnet. Das Datenbankschema ist von
den eigentlichen Daten zu unterscheiden, der Ausprägung der Datenbank. Die Ausprägung
umfasst die Gesamtheit der Daten, die in einer bestimmten Datenbank zu einem bestimmten Zeitpunkt vorhanden sind, und wird auch als Datenbankzustand bezeichnet. Eine kurze
Einführung in die Datenmodellierung geben wir in diesem Kapitel im Abschnitt 1.4, eine
genaue Beschreibung folgt in Kapitel 2.
Unter einer integrierten Datenhaltung verstehen wir den Umstand, dass die Datenbank als
Sammlung von unterschiedlichen Datenfiles oder Tabellen gesehen werden kann, zwischen
denen Redundanz so weit als möglich eliminiert wird. Das war einer der Gründe, warum
sich Datenbanksysteme im Laufe der Zeit immer größerer Beliebtheit erfreuten. Ein weiterer
war, dass es relativ einfach möglich ist, die Daten mehreren Benutzern für unterschiedliche
Zwecke und in unterschiedlichen Sichtweisen zur Verfügung zu stellen, wodurch die Wartung
und Aktualisierung der Daten wesentlich erleichtert wird.
1.1.4 Die Benutzer
Die Benutzer eines DBS können wir in drei Gruppen einteilen: in Datenbank- und Datenadministratoren, Applikationsprogrammierer und Endbenutzer.
Die Datenadministratoren (DA) führen die Datenmodellierung durch, die Datenbankadministratoren (DBA) sind für die Implementierung und technische Realisierung der in der
Phase der Datenmodellierung getroffenen Entscheidungen zuständig. In kleineren Projekten sind Datenbankadministrator, Datenadministrator und Anwendungsprogrammierer oft ei-
KAPITEL 1. EINLEITUNG
1.4
Produktion
Verkauf
Fakturierung
Zugriffsoperationen
Zugriffsoperationen
Zugriffsoperationen
Angestellte
Kunden
Kunden
Teile
Teile
Teile
Abbildung 1.2: Die Einzellösung
ne Person. In großen Anwendungen, wie zum Beispiel im Bankenbereich oder bei Fluglinien, sind eine Gruppe von Datenbankadministratoren nur für die technische Umsetzung,
die Performance des DBS und für die Wartung des Systems im Fehlerfall (Soft- bzw. Hardware-Fehler) zuständig. Die Datenadministratoren sind für die Daten an sich zuständig. Sie
entscheiden, welche Daten in welcher Form gespeichert werden, welche Verfahren zur Datenwartung eingesetzt werden und wer in welcher Form auf die Daten zugreifen darf.
Die Applikationsprogrammierer sind für die Entwicklung der Anwendungen, die auf die
Daten im DBS zugreifen, zuständig. Diese Applikationen werden üblicherweise in den heute
gängigen objektorientierten oder prozeduralen Programmiersprachen wie Java, C++, C, oder
Pascal (Delphi) geschrieben. Vielfach wird dabei über genormte Schnittstellen wie ODBC
(Open DataBase Connectivity) oder JDBC (Java DataBase Connectivity) mit dem DBS kommuniziert, d.h., der Code kann unabhängig vom konkreten DBMS, das letztendlich verwendet
wird, geschrieben werden. Eine andere Möglichkeit ist, die entsprechenden Features der einzelnen DBMS-Anbieter und die vom DBMS zur Verfügung gestellten Schnittstellen für die
jeweiligen Programmiersprachen direkt zu verwenden.
Die Endbenutzer schließlich greifen entweder über die im letzten Punkt beschriebenen
Applikationen auf die Daten zu oder über ein Interface, das vom DBMS zur Verfügung gestellt wird. Jedes DBMS stellt eine gewisse Anzahl von eingebauten Modulen zur Verfügung,
mittels derer die Endbenutzer direkt auf die Daten zugreifen können. Eines dieser Module ist
üblicherweise eine interaktive Abfragesprache, wobei derzeit am häufigsten SQL oder eine
Abart von SQL anzutreffen sind.
1.2 Warum ein Datenbanksystem?
In diesem Abschnitt geben wir zuerst einen kurzen historischen Abriss zur Entstehung von
integrierter Datenverarbeitung und damit zur Entwicklung von Datenbanksystemen, danach
besprechen wir die Funktionalität von Datenbanksystemen und zum Schluss werden wir kurz
die Vorteile, die die Verwendung von Datenbanksystemen mit sich bringt, beschreiben.
KAPITEL 1. EINLEITUNG
1.5
Produktion
Verkauf
Fakturierung
Zugriffsoperationen
Zugriffsoperationen
Zugriffsoperationen
Personen
Datei
Teile
Datei
Abbildung 1.3: Die Integrierte Datenverarbeitung
1.2.1 Von Einzellösungen zu Datenbanksystemen
Informationssysteme sollen leicht wartbar, leicht erweiterbar und ihre Bedienung leicht erlernbar sein. Seit den ersten Implementierungen von Informationssystemen wurden diesbezüglich
große Fortschritte gemacht.
Die ersten computerunterstützten Informationssysteme wurden in Form von Einzell ösungen (siehe Abbildung 1.2), als einzelne Anwendungsprogramme mit privaten Dateien, realisiert. Diese Programme verwendeten unmittelbar das zugrundeliegende Dateisystem auf
dem jeweiligen Rechner. Gleichartige Daten wurden in Dateien (Files) gespeichert, die selbst
wieder aus einzelnen Datensätzen (Records) bestanden. Diese wiederum waren aus Einträgen
oder Feldern zusammengebaut, die somit die kleinste Dateneinheit darstellten. Diese Systeme
waren schwer wartbar, da mehrfach verwendete Daten redundant gespeichert wurden.
Diese Redundanz sowohl der gespeicherten Daten als auch des Programmcodes (da für jede Anwendung entsprechende Zugriffsfunktionen implementiert wurden) behinderte sowohl
den Betrieb als auch die Wartung solcher Systeme. Daher wurden bei der Integrierten Datenverarbeitung (siehe Abbildung 1.3) Dateien mit Hilfe von Dateisystemen in mehreren Anwendungsprogrammen verwendet und in sogenannten Data Dictionaries Verzeichnisse über
die Verwendung von Daten in Programmen zentral geführt. Programme und Dateien waren
jedoch voneinander abhängig. Änderungen in der Organisationsform einer Datei (z.B. der
Sortierreihenfolge der Datensätze) oder eine Änderung des Satzaufbaus machten eine Änderung aller Programme notwendig, die diese Datei benutzten, auch dann, wenn für diese die
Änderung inhaltlich bedeutungslos war.
Heute werden Informationssysteme meist mit Hilfe von Datenbanksystemen (siehe Abbildung 1.4) realisiert, die unabhängig von bestimmten Anwendungsprogrammen existieren und eine klare Trennungsebene zwischen Anwendungsprogrammen und Daten darstellen. Einerseits ermöglicht diese Trennung die sogenannte physische Datenunabhängigkeit,
d.h. Programme und Ad-hoc-Abfragen sind von den konkreten Speicher- oder Zugriffsmethoden unabhängig. Andererseits stellen DBMSe ein Datenmodell“, also eine Sprache zur
”
KAPITEL 1. EINLEITUNG
1.6
Produktion
Verkauf
Fakturierung
Zugriffsoperationen
Zugriffsoperationen
Zugriffsoperationen
Datenbanksystem
Personen
Datei
Teile
Datei
Abbildung 1.4: Das Datenbanksystem
Beschreibung der Datenstrukturen zur Verfügung, die es möglich macht, einzelne Programme
auf speziellen logischen Darstellungen der gespeicherten Datenbank arbeiten zu lassen, sodass bestimmte Änderungen der Datenbasis selbst vor den Anwendungsprogrammen versteckt
werden können, ein Zustand, den wir logische Datenunabh ängigkeit bezeichnen. Zusammengefasst ergeben sich folgende Vorteile:
• Redundanz ist weitgehend vermeidbar,
• ein konsistenter Datenbankzustand gemäß Integritätsbedingungen ist gesichert,
• flexibler Gebrauch der Daten wird ermöglicht.
Konventionelle Datenbanksysteme unterstützen die gemeinsame Verwendung von Daten zwischen mehreren Anwendungen. Objektorienierte Datenbanksysteme (siehe Abbildung 1.5) erweitern diese Idee der gemeinsamen Benutzung“ auf Operationen über diese
”
Daten. Das Schema einer objektorientierten Datenbank besteht aus einer Menge von Objektklassen. Eine Objektklasse beschreibt eine Datenstruktur und eine Menge von auf dieser Datenstruktur definierten Operationen. Objekte der zu beschreibenden Welt werden als Instanzen
von Objektklassen repräsentiert. Ein solches Objekt darf nur über die für seine Objektklasse
definierten Operationen modifiziert werden.
1.2.2 Funktionalität von Datenbanksystemen
In diesem Abschnitt beschreiben wir die wichtigsten Eigenschaften von Datenbanksystemen
aus Benutzersicht, als da sind: persistente Datenhaltung, Hintergrundspeicherverwaltung, Recovery (Wiederanlauf), Concurrency Control (Synchronisation), Unterstützung von Ad-hocAbfragen und Datenschutz/Zugriffskontrolle.
KAPITEL 1. EINLEITUNG
1.7
Produktion
Verkauf
Fakturierung
oo Datenbanksystem
Personen
Teile
Operationen
Operationen
Daten
Daten
Abbildung 1.5: Das Objektorientierte Datenbanksystem
1.2.2.1 Persistente Datenhaltung
Ein Datenbankmanagementsystem muss Mechanismen zur Verfügung stellen, die eine persistente Speicherung von Daten sicherstellen. Unter Persistenz verstehen wir, dass die Daten
in der Datenbank über die Ausführungszeit von Anwendungsprogrammen hinaus erhalten
bleiben, im Gegensatz zu Daten, die entweder in Programmvariablen von Anwendungsprogrammen gehalten werden oder Input- bzw. Output-Daten sind, und daher flüchtige (transiente) Daten genannt werden. Input-Daten sind jene Daten, die in das System meist interaktiv
über ein Terminal oder mittels OCR (Banküberweisungen) eingegeben werden. Input-Daten
können persistente Daten verändern oder selbst zu persistenten Daten werden, sind aber nicht
Teil der Datenbank an sich. Ähnlich verhält es sich mit Output-Daten, die meist über Drucker
oder Bildschirm ausgegeben werden. Sie leiten sich zwar oft von den persistenten Daten ab,
sind aber nicht Teil der Datenbank.
Die Daten werden üblicherweise auf einem Hintergrundspeicher (Sekundärspeicher, z.B.
Platte) persistent gehalten; Daten, die ausschließlich im Hauptspeicher (Primärspeicher) gehalten werden, sind flüchtig, d.h. sie überleben die Programmausführung nicht. Für den Benutzer eines Datenbankmanagementsystems ist nicht sichtbar, welche Daten sich während der
Benutzung der Datenbank nur im Sekundärspeicher befinden und welche vom DBMS kurzfristig zusätzlich im Primärspeicher gehalten werden.
1.2.2.2 Hintergrundspeicherverwaltung
Ein Datenbankmanagementsystem unterstützt die Verwaltung großer Datenmengen, die üblicherweise nicht zur Gänze im Primärspeicher Platz finden. Die Datenbank wird persistent
im Hintergrundspeicher (oder Sekundärspeicher) gehalten. Nachdem Programme nur auf Daten im Primärspeicher direkt zugreifen können, werden Ausschnitte der Datenbank zeitweise
auch in einem Teil des Primärspeichers, dem Datenbankpuffer, verwaltet.
1.8
KAPITEL 1. EINLEITUNG
Nachdem ein Plattenzugriff etwa um einen Faktor zehntausend länger dauert als ein Hauptspeicherzugriff, sind spezielle Techniken notwendig, um unnötige Plattenzugriffe zu vermeiden. Üblicherweise werden daher nicht einzelne Datensätze zwischen den Speichermedien
transferiert, sondern ganze Bereiche. Die Speichermedien sind in Bl öcke gegliedert, und es
werden aus Effizienzgründen jeweils alle Datensätze, die sich in einem Block befinden, übertragen.
Spezielle Puffer-Ersatz-Strategien werden verwendet, um bei Platzmangel im Datenbankpuffer zu entscheiden, welche Blöcke wieder auf die Platte ausgelagert werden sollen. Dabei
kommen verschiedene Strategien zum Einsatz, wie z.B. least recently used“ oder least fre”
”
quently used“. Wenn wir den Haupt- und Hintergrundspeicher mit unserem Schreibtisch und
der Ablage im Büro vergleichen, dann lässt sich die Pufferstrategie mit der gewählten Vorgehensweise vergleichen, nach der wir auf dem Schreibtisch durch das Wegräumen von Akten
Platz für neue Akten schaffen.
Aus Effizienzgründen ist es wichtig, wie die Datensätze den Blöcken im Sekundärspeicher zugeordnet sind. Angenommen wir verteilen jene Unterlagen, die wir für eine wichtige
Tätigkeit brauchen, auf fünf verschiedene Ordner, die überdies sehr viel andere Unterlagen
enthalten, dann müssen wir jedesmal, wenn wir diese Tätigkeit verrichten, für alle fünf Ordner am Schreibtisch Platz finden. Außerdem verbrauchen die restlichen Unterlagen, die wir
in jenem Fall gar nicht benötigen, viel Platz in den Ordnern. Sogenannte Cluster-Techniken
gruppieren Datensätze so, dass Datensätze — unter Umständen auch verschiedener Dateien
— auf die oft gemeinsam zugegriffen wird, physisch benachbart gespeichert werden.
Weiters werden verschiedene Indextechniken verwendet, um Daten auf dem Hintergrundspeicher rasch zu finden. Wie etwa Indexeinträge in Büchern auf die Buchseite verweisen,
in denen ein Stichwort erwähnt wird, so verweisen Indexeinträge in Datenbanken auf jene
Blöcke, in denen Datensätze mit bestimmten Feldwerten vorkommen. Eine genaue Behandlung dieser Thematik geben wir in Kapitel 8.
1.2.2.3 Recovery
Datenbankmanagementsysteme unterstützen Änderungen der Datenbank durch Transaktionen. Eine Transaktion ist eine Folge von Aktionen, das sind Lese- und Schreibzugriffe auf
Daten der Datenbank, die eine Datenbank von einem konsistenten Zustand in einen anderen
konsistenten Zustand überführt.
Die Recovery Einheit eines Datenbankmanagementsystems gewährleistet die Atomarität
und die Dauerhaftigkeit (Persistenz) von Transaktionen. Atomarit ät bedeutet, dass alle Aktionen einer Transaktion ausgeführt werden oder keine. Dauerhaftigkeit bedeutet, dass alle Effekte einer einmal erfolgreich abgeschlossenen Transaktion trotz etwaiger anschließend
auftretender Hard- und Softwarefehler erhalten bleiben.
Fehler, die ein Datenbankmanagementsystem abfangen muss, sind unter anderem:
1. vom Anwendungsprogramm erkannte logische Fehler (z.B. Konto nicht gedeckt“),
”
KAPITEL 1. EINLEITUNG
1.9
2. vom System erkannte Fehler (z.B. zyklisches Warten mehrerer Programme auf die Freigabe einer Ressource),
3. der Verlust des Hauptspeicherinhalts (z.B. Stromausfall) und
4. der Verlust der Daten des Plattenspeichers (z.B. Disk Crash).
Der Start, der erfolgreiche Abschluss bzw. der Abbruch einer Transaktion werden dem
Datenbankmanagementsystem durch die speziellen Befehle begin transaction, commit transaction bzw. abort transaction angezeigt.
Beispiel 1.1 Ein typisches Beispiel einer Transaktion ist die Überweisung eines Geldbetrages von einem Gehaltskonto auf ein Sparbuch. Atomarität bedeutet in diesem Fall, dass die
Überweisung zur Gänze durchgeführt wird (Abbuchung vom Gehaltskonto und Aufbuchung
auf das Sparbuch) oder gar nicht (weder Abbuchung noch Aufbuchung). Tritt während der
Überweisung nach der Abbuchung, aber noch vor der Aufbuchung ein Systemabsturz ein,
so möchten wir als Kunden davon ausgehen können, dass sich nach dem Wiederanlauf der
gesamte Geldbetrag noch auf dem Gehaltskonto befindet.
Angenommen, wir zahlen einen Millionengewinn im Lotto auf unser Konto ein. Dann
stellt die Dauerhaftigkeit von Transaktionen sicher, dass der Gewinn auch nach einem Systemneustart immer noch auf dem Konto liegt.
Für den Wiederanlauf verwenden die meisten relationalen Datenbankmanagementsysteme
ein Logprotokoll. In diesem Logprotokoll wird der Start (begin transaction), das Ende (end
transaction) und der Abbruch (abort transaction) von Transaktionen verzeichnet, sowie die
von Transaktionen durchgeführten Modifikationen (Einfügen, Löschen und Ändern von Datensätzen). Zu jeder Änderung wird der alte Datensatz (before image) und der neue Datensatz
(after image) im Logprotokoll verzeichnet. Beim Wiederanlauf werden alle nicht beendeten Transaktionen (commit transaction fehlt im Logprotokoll) unter Verwendung der BeforeImages zurückgesetzt und alle bereits erfolgreich abgeschlossenen Transaktionen (commit
transaction steht im Logprotokoll) nachgefahren. Das Logprotokoll sollte sich nicht auf dem
selben Hintergrundspeicher (z.B. der selben Platte) wie die Datenbank befinden, denn im
Falle eines Plattenfehlers wären das Logprotokoll wie auch die Datenbank verloren. Im Falle eines Systemabsturzes allein wäre die Speicherung des Logs und der Datenbank auf der
selben Platte ausreichend. Damit wir das Logprotokoll nicht in die Vergangheit zurück bis
zur erstmaligen Verwendung des Datenbanksystems aufbewahren müssen, können wir zu bestimmten Zeitpunkten auch ein Backup der Datenbank anlegen. Eine genauere Beschreibung
der unterschiedlichen Algorithmen zum Wiederanlauf geben wir in Kapitel 11.
1.2.2.4 Concurrency Control
Die Concurrency Control Einheit eines Datenbankmanagementsystems ermöglicht mehreren Benutzern, eine Datenbank gemeinsam zur selben Zeit zu benutzen, ohne ihre Konsistenz zu gefährden. Das traditionell verwendete Korrektheitskriterium für die parallele (oder
KAPITEL 1. EINLEITUNG
1.10
t
T1
T2
read(Konto,a)
read(Konto,b)
a := a + 2.000
b := b − 65
write(Konto,a)
write(Konto,b)
Abbildung 1.6: Verzahnte Ausführung von Transaktionen
verzahnte) Ausführung von Transaktionen im Mehrbenutzerbetrieb ist die Serialisierbarkeit.
Die Serialisierbarkeit besagt, dass das Ergebnis der beliebigen Parallelausführung mehrerer
Transaktionen dem Ergebnis irgendeiner Hintereinanderausführung dieser Transaktionen entspricht.
Beispiel 1.2 Angenommen, wir wollen unsere Telefonrechnung bezahlen. Wir gehen zur
Bank und füllen den Zahlschein aus, womit die Abbuchung vom Konto durchgeführt wird.
Diese Abbuchung wird nun zufällig gleichzeitig mit der Gehaltsbuchung auf das Konto durchgeführt, d.h., es gibt zwei verschiedene Transaktionen, die zur selben Zeit auf dieselben Daten zugreifen. Betrachten wir dazu die schematische Darstellung in Abbildung 1.6, die eine
mögliche verzahnte Ausführung zeigt. Angenommen, der aktuelle Kontostand beträgt 150,-.
Zunächst liest Transaktion T1 (die Gehaltsbuchung) den aktuellen Kontostand in eine Programmvariable a (150,-), danach liest Transaktion T2 (die Telefonrechnung) den aktuellen
Kontostand in eine Programmvariable b (150,-). Dann erhöht T 1 die Programmvariable a
auf 2.150,- und T2 vermindert die Programmvariable b auf 85,-. Schließlich wird von T 1 der
neue Kontostand 2.150,- und von T2 der neue Kontostand 85,- in die Datenbank geschrieben.
Nachdem beide Transaktionen abgeschlossen wurden, ist der Kontostand Euro 85,-. Jede der
beiden möglichen Hintereinanderausführungen der beiden Transaktionen (T 1 vor T2 oder T2
vor T1 ) hätte einen Kontostand von Euro 2.085,- ergeben. Das heißt, die angegebene verzahnte Ausführung ist nicht serialisierbar, und daher nicht korrekt, wie wir leicht anhand des
obigen Beispiels sehen können.
Um die Serialisierbarkeit von Transaktionen zu gewährleisten, verwenden die meisten
Datenbankmanagementsysteme ein Sperrverfahren. Dabei legt eine Transaktion auf Datenobjekte, die sie schreiben oder lesen soll, eine Sperre. Besitzt eine Transaktion auf einem
Datenobjekt eine Sperre und fordert eine andere Transaktion für dieses Datenobjekt ebenfalls
eine Sperre an, so wird diese Sperre nur dann gewährt, wenn die neu angeforderte Sperre mit
der bereits bestehenden Sperre verträglich ist. Ist sie dies nicht, so muss die die neue Sperre
anfordernde Transaktion auf die Freigabe der bestehenden Sperre warten.
KAPITEL 1. EINLEITUNG
1.11
Meist werden zwei Typen von Sperren verwendet: geteilte Lesesperren und exklusive
Schreibsperren. Lesesperren verschiedener Transaktionen für dasselbe Datenobjekt sind miteinander verträglich; eine Schreibsperre einer Transaktion ist mit keiner Sperre einer anderen
Transaktion für dasselbe Datenobjekt verträglich.
Beispiel 1.3 Bezugnehmend auf Beispiel 1.2 mit den beiden Transaktionen auf dem Gehaltskonto bedeutet das, dass die Transaktion T1 , sobald sie den Wert des Kontos lesen will, diesen
Wert exklusiv sperrt, da sie eine Schreiboperation ausführen will. Die Transaktion T 2 muss,
wenn sie den Kontostand lesen will, warten, da eine exklusive Sperre vorliegt und daher keine
andere Transaktion auf diesen Datenwert zugreifen kann. Erst wenn T 1 den Wert nach erfolgreichem Schreiben wieder freigegeben hat, kann T2 den neuen Wert lesen. Das garantiert,
dass eine zu einer seriellen Ausführung äquivalente Ausführung durchgeführt wird.
Das Sperren von Datenobjekten ist alleine jedoch nicht ausreichend, um die Serialisierbarkeit mehrerer parallel ausgeführter Transaktionen zu gewährleisten. Es muss darüber hinaus
ein Sperrprotokoll eingehalten werden. Das am meisten gebräuchliche Sperrprotokoll ist das
2-Phasen-Sperrprotokoll. Eine Transaktion erfüllt das 2-Phasen-Sperrprotokoll, wenn es nach
der ersten Freigabe einer Sperre keine neue Sperre mehr anfordert.
Weiters garantiert die Concurrency Control Komponente die Isolation von Transaktionen.
Isolation bedeutet, dass Effekte einer Transaktion erst nach ihrem erfolgreichen Abschluss für
andere Transaktionen sichtbar werden.
Die Isolation von Transaktionen wird durch das strikte 2-Phasen-Sperrprotokoll gewährleistet, wobei eine Transaktion dieses erfüllt, wenn es alle Sperren erst am Ende der Transaktion freigibt, was in der Praxis bei kommerziellen Datenbankmanagementsystemen der Fall
ist. Eine genaue Behandlung der in diesem Abschnitt vorgestellten Konzepte werden wir in
Kapitel 10 geben.
Die in den letzten beiden Abschnitten vorgestellten Eigenschaften von Transaktionen —
Atomarität, Konsistenz (Serialisierbarkeit), Isolation und Dauerhaftigkeit — werden oft als
ACID-Eigenschaften (atomicity, consistency, isolation, durability) bezeichnet.
1.2.2.5 Ad-hoc-Abfragen
Zum Zeitpunkt des Entwurfs einer Datenbank sind üblicherweise nicht alle zu erwartenden
Abfragen bekannt. Datenbankmanagementsysteme bieten die Möglichkeit, ad hoc neue Abfragen interaktiv an das Datenbanksystem zu stellen, ohne dass dafür neue Anwendungsprogramme geschrieben werden müssen. Ein gutes Datenbankmanagementsystem unterstützt
einfach formulierbare und deklarativ gestellte Abfragen. Deklarativ bedeutet, dass nur die
Bedingungen angegeben werden müssen, die die zu selektierenden Daten erfüllen. Es ist
nicht nötig, ein prozedurales Vorgehen anzugeben, wie diese Daten in der Datenbank gesucht
werden müssen. Weiters wird ein gutes Datenbankmanagementsystem die gestellte Abfrage optimieren, d.h. einen unter Berücksichtigung der Art der Abfrage und der vorhandenen
Speicher- und Indexstrukturen optimalen Zugriffsplan ermitteln. Die meisten relationalen
1.12
KAPITEL 1. EINLEITUNG
Datenbanksysteme stellen SQL (Structured Query Language) als interaktive Datenbankabfragesprache zur Verfügung. Wir werden in Kapitel 4 genauer darauf eingehen, die Optimierung
von Abfragen behandeln wir in Kapitel 9.
1.2.2.6 Datenschutz
Datenbankmanagementsysteme bieten die Möglichkeit, den Zugriff auf Ausschnitte der Datenbank für einzelne Benutzer oder Benutzergruppen zu beschränken. Dabei kann hinsichtlich
der Art des Zugriffs zwischen Lese-, Änderungs-, Einfüge- und Löschzugriffen unterschieden
werden. Wichtig in diesem Zusammenhang ist, wie granular Zugriffsrechte vergeben werden
können: z.B. für die gesamte Datenbank, für einzelne Tabellen einer relationalen Datenbank,
oder für ausgewählte Zeilen und Spalten einer Tabelle.
1.2.3 Komponenten eines Datenbanksystems
Ein Datenbanksystem besteht aus den folgenden Komponenten:
Abfragenübersetzer (query parser): übersetzt die Anweisungen einer Abfragesprache in
eine niedere Sprache (z.B. Relationale Algebra, Kapitel 3).
Abfragenoptimierer (query optimizer, strategy selector): formt das Ergebnis des Abfragenübersetzers in eine effiziente Abfrage mit gleichem Ergebnis um(Kapitel 9).
Zugangs- und Integritätsmanager: verhindert unberechtigte Zugriffe und überprüft die Einhaltung vorgegebener Integritätsbedingungen.
Puffermanager (buffer manager): führt den Datentransfer vom Sekundär- in den Primärspeicher und umgekehrt durch.
Dateimanager (file manager): verwaltet die Dateien und deren Datenstrukturen auf dem Sekundärspeicher.
Wiederanlaufeinheit (recovery unit): stellt nach Transaktions-, System- oder Hardwarefehlern einen konsistenten Zustand der Datenbank her (Kapitel 11).
Mehrbenutzerkontrolleinheit (concurrency control unit): verhindert, dass sich mehrere Benutzer oder Programme, die das Datenbanksystem gleichzeitig verwenden, gegenseitig
stören (Kapitel 10).
Das Datenbankmanagementsystem greift über die oben beschriebenen Komponenten auf
die Datenbank selbst zu, deren Daten über die folgenden Datenstrukturen verwaltet werden:
Dateien (data files): speichern die Daten selbst.
KAPITEL 1. EINLEITUNG
1.13
Benutzer
Abfragenübersetzer
Wiederanlaufmanager
Abfragenoptimierer
Benutzertransaktion
Logdatei
Mehrbenutzerkontrolle
Sperrenverzeichnis
Puffermanager
Puffer (Hauptspeicher)
Dateimanager
Statische Dateien
Indexe
Systemdaten
Platte(Hintergrundspeicher)
Benutzerdaten
Abbildung 1.7: Komponenten eines Datenbanksystems
Datenverzeichnisse (data dictionary): enthält Informationen über die Bedeutung der gespeicherten Daten und deren Aufbau (Struktur der Dateien, Zugriffsbeschränkungen,
. . . ).
Indexe (indices): werden für den effizienten Zugriff auf bestimmte Daten benötigt (Kapitel 8).
Statische Dateien (statical data): enthalten Informationen über die im Datenbanksystem gespeicherten Daten, die etwa vom Abfragenoptimierer verwendet werden können.
1.2.4 Vorteile des Einsatzes von Datenbanksystemen
Am Ende dieses Abschnittes möchten wir auf die Vorteile des Einsatzes von Datenbanksystemen in Informationssystemen eingehen, die aufgrund einer zentralisierten Verwaltung der
Daten entstehen:
• Redundanzen können reduziert bzw. verhindert werden.
In Systemen, die ihre Daten nicht in einer Datenbank organisieren, hat jede Applikation oft ihre eigenen Datenfiles. Wenn nun mehrere Applikationen dieselben Daten
KAPITEL 1. EINLEITUNG
1.14
verwenden, hat das zur Folge, dass die Daten oftmals mehrfach gespeichert werden,
wie wir in Abbildung 1.2 gesehen haben. Bei der Verwendung eines Datenbanksystems
können Datenadministratoren diesen Redundanzen begegnen und bei der Erstellung eines Datenmodells verhindern. Wir möchten jedoch an diesem Punkt sehr wohl darauf
hinweisen, dass es in in der Praxis manchmal technische oder organisatorische Gründe
gibt, nicht alle Redundanzen auszuräumen. Wichtig ist dabei jedoch, dass die Datenadministratoren sich dieser Probleme bewusst sind und etwa im DBMS Vorkehrungen
treffen, dass z.B. bei Änderung der Daten diese an allen Stellen, an denen sie redundant
gespeichert sind, aktualisiert werden.
• Inkonsistenz kann (bis zu einem gewissen Grad) verhindert werden.
Für die Entstehung von Inkonsistenzen gibt es vor allem eine Ursache, die wir bei einem
ordentlichen Design einer Datenbank verhindern sollten: redundante Daten. Wenn Kundennummer und Kundenname nicht nur an einer Stelle miteinander gespeichert sind,
sondern an mehreren, dann kann es notwendig sein, dass nach einer Namensänderung
der Name des Kunden an mehreren Stellen geändert werden muss und nicht nur bei den
Stammdaten des Kunden. Wenn das nicht geschieht, dann werden die Daten inkonsistent. Es ist auf jeden Fall möglich, Inkonsistenz zwischen den Daten auf Applikationsebene abzufangen und so sicherzustellen, dass die redundant gespeicherten Daten
an allen Stellen geändert werden. Dabei stellt sich jedoch das Problem, dass in allen
Applikationen auf diesen Umstand Rücksicht genommen werden muss. Daher stellen
die meisten kommerziellen Datenbankmanagementsysteme Trigger zur Verfügung (siehe Kapitel 4). Trigger ermöglichen es, aktiv auf Änderungen des Datenbestandes zu
reagieren und weitere Änderungen selbst durchzuführen. So ist es den Datenbankadministratoren leicht möglich, die Änderung eines Namens abzufangen und sicherzustellen,
dass diese Änderung auch an allen Stellen, an denen der Name sonst noch vorkommt,
durchgeführt wird.
• Die Daten können mehrfach verwendet werden.
Durch die Trennung von Applikationen und den eigentlichen Daten, die nun im Datenbanksystem gehalten werden, können mehrere Applikationen auf einen einzigen Datenbestand zugreifen, und auch neue Applikationen können so entwickelt werden, dass
sie auf schon bestehende Daten zugreifen. Wir können die gespeicherten Daten auch
sehr leicht erweitern, und etwa zusätzlich zur Telefonnummer und Adresse der Kunden
auch eine Email-Adresse speichern, ohne dass wir alle schon bestehenden Applikationen ändern müssen.
• Standardisierungen können sichergestellt werden.
Durch die zentrale Kontrolle der Administratoren über die Daten kann auf die Einhaltung von Standards bei der Datenorganisation Rücksicht genommen werden. Zu
KAPITEL 1. EINLEITUNG
1.15
solchen Standards gehören z.B. innerbetriebliche, industrielle, nationale oder internationale Standards. Der Vorteil einer standardisierten Datenhaltung ist, dass z.B. Datenaustausch und Datentransfer verhältnismäßig leicht realisierbar sind.
• Datensicherheit ist leicht realisierbar.
Da die Datenbankadministratoren allein für alle technischen Belange der Datenbank
zuständig sind, können sie Einfluss darauf nehmen, wie und von wem auf die Daten zugegriffen wird. Das Datenbankmanagementsystem stellt Mechanismen zur Verfügung,
mit denen unterschiedlichen Benutzern unterschiedliche Zugriffsrechte (zum Lesen,
Ändern, Löschen oder neu Anlegen) vergeben werden können. Weiters sind unterschiedliche Benutzersichten definierbar, wodurch z.B. Abteilungsleiter nur die Daten
der ihnen unterstellten Mitarbeiter einsehen können. Wir möchten aber auch darauf
hinweisen, dass die Datensicherheit erst bei der Verwendung von zentral gespeicherten
Daten zu einem richtigen Problem wird.
• Datenintegrität wird sichergestellt.
Sicherstellung der Datenintegrität bedeutet, dass die Daten bezüglich bestimmter Kriterien fehlerfrei sind. Es ist natürlich nicht möglich, absolute Korrektheit der Daten sicherzustellen, denn wir können uns bei der Dateneingabe irren und z.B. als Adresse der
Abteilung für Datenbanken und Artificial Intelligence den Karlsplatz 13 angeben, statt
Favoritenstraße 9-11. Durch eine zentrale Kontrolle der Daten und Einschränkung der
Änderungsmöglichkeiten der vielen Benutzer ist es einfacher, diese Art der Fehler zu
verhindern. Es ist aber möglich, bestimmte Zusammmenhänge im Datenbankmanagementsystem zu modellieren und somit sicherzustellen, dass diese nicht verletzt werden.
Wir könnten z.B. sagen, dass alle Assistenten der TU Wien jeweils genau einem Institut zugeordnet sind. Wenn wir nun das Institut löschen wollen, da es aufgelassen wird,
dann muss dies verhindert werden, solange noch Assistenten diesem Institut zugeordnet
sind.
Weiters ist es möglich Regeln zu definieren, anhand derer beim Ändern der Daten Integritätsbedingungen überprüft werden. So können wir z.B. verlangen, dass das Geburtsjahr der MitarbeiterInnen eines Betriebes nicht mehr als 80 Jahre vom momentanen Jahr
zurückliegt.
• Widersprüchliche Anforderungen können ausgeglichen werden.
Daten- und Datenbankadministratoren, die einen Überblick über die unterschiedlichen
Anforderungen des Unternehmens haben, haben die Möglichkeit, auf diese Anforderungen einzugehen. So kann etwa durch die Art der Datenspeicherung eine Performancesteigerung für bestimmte wichtige Applikationen zugunsten von weniger wichtigen
durchgeführt werden.
Alle hier genannten Vorteile beruhen auf der Erreichung von Datenunabhängigkeit, die
wir im nächsten Abschnitt vorstellten werden.
KAPITEL 1. EINLEITUNG
1.16
externe Ebene
ext.
Schema 1
ext.
... Schema
n
Daten-Definition
logische Datenunabhängigkeit
Daten-Manipulation
konzeptionelle Ebene
physische Datenunabhängigkeit
interne Ebene
Daten-Administration
Abbildung 1.8: ANSI/SPARC Architektur eines Datenbanksystems
1.3 Architektur eines Datenbanksystems
Moderne Datenbanksysteme unterstützen die ANSI/X3/SPARC Architektur für Datenbanksysteme. Diese vom Standards Planning and Requirements Committee des American National
Standards Institute vorgeschlagene Architektur stellt drei verschiedene Sichtweisen auf ein
Datenbanksystem und die darin gespeicherten Daten vor (siehe Abbildung 1.8):
• Die Interne Ebene ist der physischen Speicherung am nächsten, entspricht ihr jedoch
nicht ganz. Wir betrachten hier nicht die Speicherstruktur auf dem Niveau von Bl öcken
oder Seiten, sondern als interne Records“ oder Datensätze. Beschrieben wird die in”
terne Ebene durch das interne Schema der Daten. Dieses Schema enthält nicht nur die
Beschreibung von Art und Aufbau der unterschiedlichen gespeicherten Datenstrukturen, sondern auch von speziellen Zugriffsmechanismen (Indexe), sowie der Anordnung
der Datensätze. Weiters wird auf der internen Ebene die Zuordnung der Datensätze auf
Sekundärspeicher-Medien verzeichnet. Diese Ebene stellt somit als Schnittstelle zur
eigentlichen Datenbank die Abbildung von logischem in physikalischen Adressraum
unter Zuhilfenahme von Betriebssystemfunktionen zur Verfügung. Wir gehen auf die
Speicherstrukturen in Datenbankmanagementsystemen in Kapitel 8 genauer ein.
• Die konzeptionelle Ebene beschreibt die logische Struktur, die logische Gesamtsicht der
Daten einer Datenbank im konzeptionellen Schema. In diesem Schema beschreiben wir
die Daten und ihre Beziehung zueinander mit den Mitteln der Datenmodellierung (siehe Abschnitt 1.4). Weiters enthält das konzeptionelle Schema Integritätsbedingungen,
Sicherheitsregeln und die Definition von Triggern.
Die Trennung zwischen der internen und der konzeptionellen Ebene führt zur physischen Datenunabhängigkeit. Diese bedeutet, dass unabhängig von der konkreten physischen Organisation der Daten die logische Organisation der Daten gleich bleibt. Wenn
wir z.B. aus Performancegründen Indexe oder Cluster einführen, hat das keine Auswirkungen auf die logische Struktur der Daten und die Anwendungsprogramme, die auf
KAPITEL 1. EINLEITUNG
1.17
der Datenbank arbeiten, müssen nicht verändert werden. Die einzige Auswirkung der
Änderung ist eine möglicherweise veränderte Laufzeit. Unterstützt ein Datenbankmanagementsystem physische Datenunabhängigkeit, können wir die Datenbank zunächst
nur nach inhaltlichen Gesichtspunkten entwerfen und implementieren. Anschließend
können wir die Speicherorganisations- und Zugriffsstrukturen der Dateien so modifizieren, dass die wichtigsten Anwendungen und Anfragen schneller ausgeführt werden,
ohne diese umschreiben zu müssen. Hat sich mit der Zeit das typische Anfragenprofil
an die Datenbank geändert, können wir wiederum eine optimale interne Organisationsform der Daten festlegen, ohne Anwendungsprogramme modifizieren zu müssen.
• Die Externe Ebene umfasst alle individuellen Sichten der einzelnen Benutzer, Benutzergruppen oder Anwendungen auf die Datenbank. Jedes externe Schema beschreibt dabei
eine dieser Sichten (Views) und enthält dabei genau jenen Ausschnitt der Datenbank
den der jeweilige Benutzer, die Benutzergruppe oder die Anwendung sehen will bzw.
darf.
Die Trennung zwischen konzeptioneller und externer Ebene wird auch als logische Datenunabhängigkeit bezeichnet. Dadurch werden Anwendungen, die auf ein externes
Schema zugreifen, von einer Änderung des logischen Aufbaus der Daten des konzeptionellen Schemas entkoppelt. Eine Restrukturierung des konzeptionellen Schemas bedingt keine Änderung der Anwendungen, die auf externe Schemata zugreifen. Eine Erweiterung des konzeptionellen Schemas einer relationalen Datenbank um neue Tabellen
oder neue Spalten von Tabellen, sowie eine Verkleinerung des konzeptionellen Schemas betreffen nur jene Anwendungen, die die hinzugefügten oder entfernten Tabellen
bzw. Spalten tatsächlich benutzen. Unterstützt ein Datenbankmanagementsystem logische Datenunabhängigkeit, können wir während des Betriebes des Datenbanksystems
neue Tabellen oder Spalten hinzufügen, ohne dass alte Anwendungen geändert werden
müssen.
Durch die ANSI SPARC-Architektur sind auch die Aufgabenprofile der Datenbankadministratoren und der Anwendungsadministratoren festgelegt, die wir schon besprochen haben. Die Datenbankadministratoren sind für die Verwaltung des logischen und des physischen
Schemas verantwortlich. Anwendungsadministratoren sind jeweils für die Verwaltung eines
oder mehrerer externer Schemata verantwortlich.
1.4 Die Datenmodellierung
In diesem Abschnitt werden die wichtigsten Begriffe zur Datenmodellierung erklärt, die danach in Kapitel 2 eingehend behandelt werden.
KAPITEL 1. EINLEITUNG
1.18
Anforderungen
Konzeptioneller Entwurf
z.B.:
Entity-Relationship-,
UML-Diagramme
Konzeptionelles Schema
konzeptionelles Datenmodell
z.B.:
Relationales Modell
(Normalisierung)
Logischer Entwurf
systemunabhängig
systemabhängig
Logisches Schema
logisches Datenmodell
z.B.:
Indexe,
Cluster
Physischer Entwurf
Physisches Schema
physisches Datenmodell
Abbildung 1.9: Der Datenbankentwurfsprozess
1.4.1 Begriffe
Ein Datenmodell besteht aus einer Menge von Modellierungskonstrukten zur Beschreibung
des Inhalts, der Struktur und der Bedeutung von Daten und einer Menge von auf diesen Modellierungskonstrukten definierten Operatoren zur Datenmanipulation. Ein Datenmodell stellt
dementsprechend eine Datendefinitionssprache (Data Definition Language, DDL) und eine
Datenmanipulationssprache (Data Manipulation Language, DML) zur Verfügung.
Datenmodellierung bezeichnet den Vorgang des Entwurfs eines Datenbankschemas für
die Verwaltung der Daten eines Informationssystems. Unter Universe of Discourse (oder
Problembereich) wird jener Weltausschnitt verstanden, der in der Datenbank repräsentiert
werden soll.
1.4.2 Datenmodelle im Datenbankentwurf
Im Datenbankentwurf werden verschiedene Datenmodelle entsprechend der ANSI/X3/SPARCArchitektur verwendet. Konzeptionelle Datenmodelle stellen problemnahe Modellierungskonzepte für die ersten Schritte des Datenbankentwurfs zur Verfügung und dienen zur Kommunikation zwischen Endbenutzern und Datenbankentwicklern. Physische Datenmodelle
stellen maschinennahe Konzepte zur Verfügung und dienen zur Beschreibung der Organisation von Daten in Dateien, sowie zur Beschreibung von Zugriffsstrukturen, die ein rasches
Einfügen, Suchen, Löschen und Ändern von Daten ermöglichen. Logische Datenmodelle dienen der Überbrückung der Kluft zwischen konzeptionellen und physischen Datenmodellen.
Sie werden oft auch als Implementierungsmodelle bezeichnet, da sie von Datenbankmanagementsystemen direkt unterstützt werden. Das logische Datenmodell steht dem Entwickler
zur Definition eines Datenbankschemas zur Verfügung und wird weitgehend automatisch vom
KAPITEL 1. EINLEITUNG
1.19
Datenbankmanagementsystem in ein physisches Datenbankschema übersetzt.
Konzeptionelle, logische und physische Datenmodelle sind in verschiedenen Phasen des
Datenbankentwurfs relevant (vgl. Abbildung 1.9).
In den letzten Jahrzehnten wurden Implementierungsmodelle immer näher an konzeptionelle Modelle herangebracht. Das Netzwerkmodell und das Hierarchische Modell wurden vor
allem in den 70er Jahren als Implementierungsmodelle verwendet und waren sehr nahe an
physische Modelle angelehnt. Das seit den 80er Jahren immer mehr eingesetzte Relationenmodell steht als logisches Modell zwischen physischen und konzeptionellen Modellen. Die
seit den 90er Jahren entwickelten objektorientierten Datenbankmanagementsysteme kommen
mit einem objektorientierten Implementierungsmodell den konzeptionellen objektorientierten
Modellen bereits weit entgegen, sind aber zur Zeit hinsichtlich der unterstützten Modellierungskonzepte meist noch eingeschränkt.
1.5 Der Datenbank-Life-Cycle“
”
Der Datenbank-Life-Cycle“ beinhaltet alle zum Design, der Erstellung und Wartung einer
”
Datenbankapplikation notwendigen Entwicklungsschritte. Der Prozess beginnt mit der Anforderungsanalyse (Requirementsanalyse), die gemeinsam mit den Kunden durchgeführt wird,
der Erstellung des konzeptionellen Schemas, des logischen Schemas und zuletzt des physischen Schemas. Nach der Fertigstellung des Designs beginnt die Implementierungsphase,
danach kommt die Wartungsphase.
In diesem Skriptum verwenden wir als roten Faden das virtuelle Unternehmen R EINE (Restaurant at the End of the InterNEt). R EINE ist ein virtuelles Unternehmen, das Leistungen im
Bereich der Gastronomie erbringt. Kunden können über das Internet Leistungen aussuchen
und bestellen, die dann geliefert werden. Im Gegensatz zu bereits existierenden Unternehmen,
die z.B. Pizzas ausliefern, soll R EINE vielfältigere Leistungen erbringen, denn auch wenn es
für den Kunden wie ein einziges Unternehmen aussieht, so besteht es eigentlich aus einer
Vielzahl von Unternehmen (Restaurants, Weinbauern, Catering Services, Transportunternehmen), die durch ihre gemeinsame Vermarktung gegenüber den Kunden eine bessere Leistung
erbringen können. Aufgrund der Komplexität dieses Anwendungsbeispieles werden wir aber
jeweils nur einen Teil der Gesamtanwendung betrachten, der sich für die Erklärung der vorgestellten Theorie eignet.
1.5.1 Die Anforderungsanalyse
In der ersten Phase des Zyklus müssen wir als Entwickler mit den Kunden (sowohl mit den
Erzeugern als auch den Benutzern der Daten) gemeinsam eine Spezifikation für die Anforderungen erstellen. An dieser Stelle müssen wir sowohl die Art der Daten und deren natürliche
Beziehungen untereinander analysieren als auch die zu verwendende Hard- und Software besprechen, da diese oft vom Kunden vorgegeben werden.
KAPITEL 1. EINLEITUNG
1.20
name
adresse
Kunde
n
knr
haube
bestellt
rnr
verkauft
1
adresse
n
Restaurant
name
typ
m
Speise
name
preis
Abbildung 1.10: Beispiel eines Entity-Relationship-Diagramms
Beispiel 1.4 In diesem Schritt müssen wir uns überlegen, welche Daten (Objekte des Problembereichs) wir für R EINE und seine Unternehmen speichern. Auf jeden Fall benötigen wir
Unternehmen, Produkte, Kunden, Bestellungen und Rechnungen sowie eventuell Mitarbeiter.
Diese Konzepte kristallisieren sich während der ersten Projektbesprechungen mit den Kunden
heraus.
1.5.2 Der konzeptionelle Entwurf
Beim konzeptionellen Entwurf wird ausgehend von den Anforderungen ein konzeptionelles
Schema entworfen, das Objekte des Problembereichs mit ihren Eigenschaften und Beziehungen zu anderen Objekten in einem konzeptionellen Datenmodell erfasst. Der konzeptionelle
Entwurf der Daten ist unabhängig davon, ob die Daten in verteilter Form (Verteilte Datenbank) oder in einer einzigen zentralen Datenbank gespeichert sind.
Das heute am weitesten und in vielen Varianten verbreitete konzeptionelle Datenmodell
ist das Entity-Relationship-Modell von Chen (1976). Es fand vor allem auf Grund seiner anschaulichen graphischen Darstellung des Datenbankschemas in Form des Entity-RelationshipDiagramms (ER-Diagramms) großen Anklang. Im ursprünglich von Chen vorgestellten Modell werden Objekte des Problembereichs auf Grund gemeinsamer Eigenschaften zu Objekttypen (Entities) zusammengefasst. Ein Objekttyp wird graphisch durch ein Rechteck repräsentiert und stellt in Form von Ovalen die allen Objekten dieses Typs gemeinsamen Merkmale
(Attribute) dar. Eine minimale Menge von Merkmalen, deren Werte ein Objekt eines Objekttyps eindeutig identifizieren, wird als Schlüssel bezeichnet. Der Primärschlüssel, das ist
ein Schlüssel, der beim Entwurf besonders ausgezeichnet wird, wird durch Unterstreichen
gekennzeichnet. Weiters werden Beziehungstypen (Relationships) zwischen Objekttypen modelliert, die angeben, dass Objekte dieser Typen zueinander in Beziehung stehen. Beziehungs-
KAPITEL 1. EINLEITUNG
1.21
name
adresse
legt
1
Kunde
n
Bestellung
knr
bnr
datum
lieferadresse
Abbildung 1.11: ER-Diagramm der Sicht der Kunden
legt
Kunde
1
n
Bestellung
n
für
verkauft
m
Restaurant
1
n
Speise
Abbildung 1.12: Integriertes ER-Diagramm (ohne Attribute)
typen werden durch Rauten dargestellt, die durch Kanten mit den betreffenden Objekttypen
verbunden sind. Eine an der Kante zwischen einem Objekttyp und dem Beziehungstyp angegebene Zahl gibt an, mit wievielen Objekten dieses Objekttyps ein bestimmtes Objekt des
jeweils anderen Objekttyps in Beziehung steht. Ein Objekttyp, dessen Objekte nicht eindeutig durch ihre Merkmale identifizierbar sind, sondern erst durch die Zuhilfenahme einer
Beziehung, heißt schwacher Objekttyp (weak entity) und wird durch ein doppelt umrahmtes
Rechteck dargestellt. Eine genaue Beschreibung der semantischen Strukturen des ER geben
wir in Kapitel 2.
Beispiel 1.5 Ein Beispiel eines ER-Diagrammes zur Modellierung von Restaurants, deren
Speisen und der Kunden, die Speisen bestellen, geben wir in Abbildung 1.10.
In großen Projekten sind meist mehrere Personen in die Analyse der Anforderungen involviert, die jeweils unterschiedliche Teilbereiche modellieren. Diese unterschiedlichen Sichten
auf das Gesamtproblem müssen im nächsten Schritt zu einem einheitlichen Modell integriert
werden. Dabei müssen Redundanzen und Inkonsistenzen eliminiert werden.
Beispiel 1.6 In Abbildung 1.10 haben wir den Bereich aus der Sicht der Restaurants modelliert. Die Sicht der Kunden hingegen zeigen wir in Abbildung 1.11, das integrierte Modell in
KAPITEL 1. EINLEITUNG
1.22
Restaurant
rnr name
1 Gußhaus
2 A Tavola
3 Green Cottage
adresse
Gußhausstraße 23, 1040 Wien
Weihburggasse 3-5, 1010 Wien
Kettenbrückengasse 3, 1050 Wien
Speise
name
Gemischter Vorspeisenteller
Penne all’ Arrabiata
Hühnerfleisch der tausend Geschmäcker
Eisei im gebackenen Nudelnest
Gebratener Rehrücken mit Serviettenknödel
haube
1
2
typ
Österreichisch
Toskanisch
Chinesisch
preis rnr
100
2
95
2
65
3
65
3
210
1
Abbildung 1.13: Transformation des ER-Modells in das Relationenmodell
Abbildung 1.12.
1.5.3 Der logische Entwurf
Beim logischen Entwurf wird das konzeptionelle Schema in ein logisches Schema transformiert, das in dem Implementierungsmodell des ausgewählten Datenbankmanagementsystem
beschrieben ist. Das heute am weitesten verbreitete Implementierungsmodell ist das Relationale Datenmodell von Codd (1970). Es beschreibt die Daten einer Datenbank in Form von
Tabellen. Das Relationale Datenmodell beschreiben wir eingehend in den Kapiteln 3 und 4, in
Kapitel 3 beschreiben wir die Transformation von einem ER-Modell in das Relationenmodell.
Beispiel 1.7 Abbildung 1.13 zeigt für R EINE beispielhaft die Tabellen für die Entities Speise
und Restaurant.
Aus dem ER-Diagramm und der Semantik der Beziehungen der Daten in der Anforderungsanalyse können wir Funktionale Abhängigkeiten (siehe Kapitel 6) ableiten. Funktionale
Abhängigkeiten stellen einerseits Abhängigkeiten zwischen Schlüsseln verschiedener Objekttypen dar, andererseits zwischen Schlüsseln und Nichtschlüsselattributen innerhalb eines Objekttyps. Ist zweiteres der Fall, so müssen wir mittels Normalisierung (siehe Kapitel 7) die
Tabellen in eine Normalform (3. Normalform oder Boyce-Codd Normalform) überführen, um
Anomalien beim Löschen oder beim Ändern von Daten zu vermeiden. Dabei teilen wir eine
Tabelle, die die Normalform verletzt, nach bestimmten Regeln in mehrere Tabellen auf. Einen
Algorithmus zur Normalisierung von Relationen geben wir ebenfalls in Kapitel 7.
KAPITEL 1. EINLEITUNG
Satzart
‘R’
‘S’
Block 1
R
S
S
R
Block 2
S
S
R
S
1.23
Satzinhalt
rnr name
name
2
A Tavola
Gemischte. . .
Penne all. . .
3
Green Cottage
Hühnerf. . .
Eisei im N. . .
1
Gußhaus
Gebratene. . .
Indexeintrag
1
2
3
adresse
haube
preis
Weihbur. . .
100
95
Kettenb. . .
2
65
65
Gußhaus. . .
1
210
typ
Toskanisch
Chinesisch
Österreichisch
Verweis
Block 2
Block 1
Block 1
Abbildung 1.14: Beispiel eines physischen Datenbankschemas
1.5.4 Der physische Entwurf
Der letzte Schritt beim Entwuf einer Datenbank ist der physische Entwurf. Beim physischen
Entwurf wird ein dem logischen Schema entsprechendes physisches Schema erstellt mit dem
Ziel, das Laufzeitverhalten zu optimieren. Die Umsetzung in ein physisches Schema mit einer bestimmten Organisationsform der Daten wird vom Datenbankmanagementsystem übernommen. Wir können als Entwickler jedoch meist eine von mehreren alternativ möglichen
Organisationsformen der Daten wählen (etwa, welche Daten physisch nahe beieinander gespeichert werden – Clustering) und zusätzlich gewünschte Indexstrukturen festlegen, welche
die Suche nach bestimmten Suchbegriffen beschleunigen. Die Wahl der Organisationsform
und der Indexstruktur richtet sich nach der Art und Häufigkeit der wichtigsten Anfragen an
die Datenbank (siehe Kapitel 8).
Beispiel 1.8 Abbildung 1.14 zeigt ein mögliches physisches Schema für die relationale Datenbank aus Beispiel 1.7. Die Daten über die Speisen eines Restaurants werden zusammen
mit den Daten des Restaurants in einer nach dem Namen des Restaurants sortierten Datei
gespeichert (eine Datei mit zwei Satzarten ‘R’ und ‘S’). Weiters ist die Datei nach der Restaurantnummer indiziert.
An dieser Stelle kann es passieren, dass wir aus Performancegründen bei gewissen Tabellen wieder eine Denormalisierung durchführen und sie wieder zusammenfassen müssen, da
1.24
KAPITEL 1. EINLEITUNG
die Struktur der Abfragen eine häufige Verknüpfung der Tabellen fordert und dies die zeitaufwendigste Operation bei der Abfrageverarbeitung in relationalen DBMS ist. Dieser Schritt ist
aber sehr gut abzuwägen, da wir die während des logischen Entwurfs eliminierten Anomalien
wieder in die Datenbank bekommen.
1.5.5 Verteilter Entwurf
Bei verteilten Datenbanken ist im Entwurfsprozess ein weiterer Schritt notwendig, nämlich
der Entwurf der Datenverteilung. Dieser besteht aus zwei Teilen, der Datenfragmentierung
und der Datenzuordnung. Das Fragmentierungsschema beschreibt in Form einer 1:1-Abbildung, wie der Datenbestand in einzelne Fragmente unterteilt wird. Fragmente sind logisch
zusammengehörende Teile der Daten, die physikalisch an einer oder an mehreren Stellen gespeichert sind. Das Zuordnungsschema beschreibt, an welcher Stelle die einzelnen Fragmente
bzw. gegebenenfalls deren Kopien physisch gespeichert sind. Das Zuordnungsschema kann
entweder eine 1:1-Abbildung der Fragmente auf die Speicherplätze sein, in diesem Fall erhalten wir einen nichtredundanten, verteilten Datenbankentwurf, oder aber eine 1:n-Abbildung,
wodurch wir einen verteilten und replizierten Datenbankentwurf erhalten.
Die Trennung der Fragmentierung von der Zuordnung ist wichtig, da die Fragmentierung
den logischen Entwurf der Daten betrifft, die Zuordnung den physischen. Intuitiv ist klar,
dass eine optimale Fragmentierungs- und Zuordnungsstrategie nicht möglich ist, wenn wir
beide Schritte völlig voneinander getrennt betrachten. In der Praxis ist jedoch eine Trennung
der beiden Bereiche vor allem in großen Problemkreisen unumgänglich. Weiters müssen Probleme, die durch die Redundanz der Daten im Falle einer replizierten Datenbank entstehen,
berücksichtigt werden, und die Unabhängigkeit von lokalen Datenbankmanagementsystemen
gegeben sein.
Ziele des Entwurfs der Datenverteilung sind minimale Antwortzeiten, minimale Kommunikationskosten und maximale Verfügbarkeit.
Beispiel 1.9 R EINE soll österreichweit angeboten werden. Momentan gibt es das Service
in Innsbruck und Umgebung, in Linz, in Salzburg und in Wien. Daher ist es sinnvoll, die
Daten in einer verteilten Datenbank zu verwalten. Die Fragmentierung der Daten betrifft
sowohl Anbieter und Angebote als auch die Kunden; die Zuordnung lösen wir durch die
Verwendung von vier Rechnern, die an den jeweiligen Orten stehen, wobei in Wien zentral
alle Kundendaten gespeichert werden.
1.5.6 Datenbankimplementierung, -überwachung und -wartung
Nach der Entwurfsphase müssen wir den Entwurf unter Verwendung einer Datendefinitionssprache (DDL) eines Datenbankmanagementsystems umsetzen. Mittels der Datenmanipulationssprache (DML) können wir die Datenbank mit Daten füllen, diese abfragen oder Indexe
und Cluster setzen. Wir stellen in diesem Skriptum in Kapitel 4 SQL (Structured Query Language) als eine Sprache vor, die sowohl DDL als auch DML Konstrukte enthält. In Kapitel 5
KAPITEL 1. EINLEITUNG
1.25
wird Datalog vorgestellt, deren DML rekursive Abfragen erlaubt. Solche rekursiven Abfragen
sind zwar im SQL-3 Standard möglich, allerdings in der Praxis in ORACLE oder Microsoft
SQL Server 2000 noch nicht implementiert.
Nach erfolgreicher Inbetriebnahme des Datenbanksystems müssen wir beobachten, wie es
sich im täglichen Betrieb verhält. Ist das Laufzeitverhalten unbefriedigend, werden wir das
System dahingehend verändern, dass es auch diese Erfordernisse erfüllt. Das System muss
gewartet werden und meist ändern sich die Anforderungen an das System mit der Zeit und der
Life-Cycle“ beginnt von neuem mit Redesign und Änderungen.
”
1.26
KAPITEL 1. EINLEITUNG
Literaturverzeichnis
[Chen, 1976] Chen, P. P-S.: The Entity-Relationship Model – Toward a Unified View of Data.
In Transactions ODS Bd. 1, März 1976, pp 9–36.
[Date et al. 1994] Date, C.J. and Darwen, H.: A Guide to the SQL Standard: A User Guide to the Standard Relational Language SQL. 3rd edition, Addison-Wesley Publishing
Company, 1994.
[Date 1995] Date, C.J.: An Introduction to Database Systems. 6th edition, Addison-Wesley
Publishing Company, 1995.
[Fortier 1999] Fortier, P.: SQL3 Implementing the SQL Foundation Standard. McGraw-Hill,
1999.
[Rumbaugh et al. 1991] Rumbaugh, J., Blaha, M., Premerlani, W., Eddy, F. and Lorensen,
W.: Object-Oriented Modeling and Design, Prentice Hall, Engelwood Cliffs, NJ, 1991.
[Teorey et al. 1986] Teorey, T.J., Yang, D., and Fry, J.P.: “A Logical Design Methodology for
Relational Databases Using the Extended Entity-Relationship-Model”, ACM Computing
Surveys, Vol.18, No. 2, pp.197-222, 1986.
[Teorey, 1999] Teorey, T.J.: Database Modeling & Design. Morgan Kaufmann, San Matteo,
California, 1999.
[Maier, 1983] Maier, D.: The Theory of Relational Databases. Computer Science Press,
Rockville, Maryland, 1983.
[Melton et al. 1994] Melton, J. and Simon, A.R.: Understanding the new SQL: A Complete
Guide. Morgan Kaufmann, San Matteo, California, 1994.
[Ullman, 1988 Bd. I] Ullman, J. D.: Principles of Database and Knowledge-Base Systems.
Volume I. Computer Science Press, Rockville, Maryland, 1988.
[Ullman, 1988 Bd. II] Ullman, J. D.: Principles of Database and Knowledge-Base Systems.
Volume II. Computer Science Press, Rockville, Maryland, 1988.
1
1.2
LITERATURVERZEICHNIS
[Vossen 1999] Vossen, G.: Datenbankmodelle, Datenbanksprachen und Datenbankmanagement-Systeme. 3. Auflage, R. Oldenbourg Verlag München Wien, 1999
Teil II
Datenmodellierung
1
Kapitel 2
Konzeptionelle Datenmodelle und das ER
Modell
Das Ziel bei der Entwicklung von konzeptionellen (semantischen) Datenmodellen war, grundlegende Strukturierungsformen für die Datenmodellierung zur Verfügung zu stellen, die weitgehend den natürlichen, in unserer Sprache auftretenden Begriffsstrukturen entsprechen.
Die semantischen Strukturen, die in der Anwendungsumgebung auftreten, sollen explizit
im Datenbankschema erfasst und dargestellt werden. Neben der Struktur der Daten sollte auch
deren Semantik im Datenbankschema ausgedrückt werden können.
Die wichtigsten konzeptionellen Datenmodelle sind:
• Entity-Relationship-Modell (ER) (Chen 1976), erweitert zum Extended-Entity-Relationship-Modell (EER) (Teorey, Yang, Fry 1986),
• SDM (Hammer, McLeod 1978),
• RM/T (Codd 1979),
• verschiedene objektorientierte Datenmodelle.
Weitere bekannte konzeptionelle Datenmodelle sind DAPLEX (Shipman 1979), TAXIS
(Mylopoulos, Bernstein und Wong 1980) und IFO (Abiteboul, Hull 1984).
Der Beginn der konzeptionellen Datenmodellierung geht auf die frühen sechziger Jahre (Bachman) zurück, als noch Dateisysteme zur Verwaltung der Daten herangezogen wurden. “Recordtypen” wurden als Rechtecke dargestellt und gerichtete Pfeile zwischen Rechtecken zeigten eine 1:n-Beziehung zwischen den Records an. Daraus entwickelte sich das
ER-Modell. Dieses zeichnet sich durch eine besonders einfache Darstellung aus und wird
daher bis heute von Datenbankdesignern zum Entwurf und zur Kommunikation mit den Endbenutzern verwendet.
Das ER-Modell wurde im Jahr 1976 von Chen [Chen, 1976] eingeführt. In der Sicht
des Entity-Relationship-Modells (Objekt-Beziehungs-Modell) besteht die Welt aus Entities
(Objekttypen) und Relationships (Beziehungen) zwischen diesen Objekttypen.
1
2.2
KAPITEL 2. KONZEPTIONELLE DATENMODELLE UND DAS ER MODELL
Im nächsten Abschnitt beschreiben wir allgemeine Abstraktionskonzepte, die sich in jedem konzeptionellen Datenmodell wiederfinden lassen. Danach gehen wir direkt auf das
Entity-Relationship-Modell ein, das bis heute am weitesten verbreitete konzeptionelle Datenmodell. In Abschnitt 2.2 werden wir die einfachen Konstrukte, die von Chen eingeführt
wurden, vorstellen. Diese Konstrukte verwenden wir, wenn wir im Stadium der Anforderungsanalyse mit den Kunden über den Problembereich reden. An dieser Stelle möchten
wir auch erwähnen, dass es verschiedene Arten der Notation für dieselben Konstrukte gibt.
Auch werden von den Tools der DBMS-Anbieter oft firmenspezifische Varianten oder Erweiterungen dieser Notation angeboten bzw. unterstützt. Wir übernehmen die Notation von
[Teorey et al. 1986], einem Artikel, in dem auch die Transformation vom ER-Modell in das
Relationenmodell beschrieben wird.1 In Abschnitt 2.3 beschreiben wir etwas ausgefeiltere
Konzepte, die eine sinnvolle Erweiterung des ER in Form des Extended-Entity-RelationshipModells (EER) erlauben, indem sie semantische Strukturen darstellen können, die im ER nicht
ausdrückbar sind.
2.1 Modellierungskonzepte konzeptioneller Datenmodelle
Wie schon in der Einleitung beschrieben, dient ein Datenmodell der Herstellung einer Abstraktion von Problemen zum Zwecke der Beschreibung derselben. Abstraktion wiederum
bedeutet, dass wir bestimmte Charakteristika und Eigenschaften einer Menge von Objekten
zu deren Beschreibung auswählen und gleichzeitig andere, nicht relevante ausschließen. Dadurch können wir uns bei der Modellierung auf die wesentlichen Teile des Problembereichs
konzentrieren. Allgemein können die folgenden drei Konzepte für die Modellierung in konzeptionellen Datenmodellen identifiziert werden:
1. Klassifikation
2. Aggregation
3. Verallgemeinerung
Durch die Klassifikation definieren wir bestimmte Konzepte als Klassen von Objekten
mit gemeinsamen Eigenschaften, d.h. wir führen mathematisch gesehen eine Mengenbildung
durch. Betrachten wir wieder unser Internetrestaurant R EINE: Wir können die Restaurants der
realen Welt zu einer Klasse Restaurants zusammenfassen, wobei es wiederum uns überlassen wird, ob wir alle Restaurants zu einer einzigen Klasse zusammenfassen, oder ob wir z.B.
für Heurigen eine eigene Klasse einführen oder für Ketten oder Fast-Food Lokale jeweils
eine eigene Klasse einführen. Derlei Entscheidungen müssen wir im Einzelfall anhand der
konkreten Anwendung treffen.
1
Diese Arbeit wird als Anhang zum Skriptum der Laborübung verteilt. Sie kann aber auch im Sekretariat der
Abteilung kopiert werden.
KAPITEL 2. KONZEPTIONELLE DATENMODELLE UND DAS ER MODELL
2.3
Mittels Aggregation definieren wir neue Klassen aus bereits existierenden, die danach
Komponenten der neuen Klassen sind. Ein einfaches Beispiel der Aggregation ist die Aggregation von Attributen zu Klassen. So können wir aus den Attributen restaurant name,
adresse, typ und haube die Klasse Restaurant definieren. Das Attribut adresse selbst
wiederum ist aus der Aggregation der Attribute strasse, ort, plz und land entstanden. Eine
weitere Art der Aggregation ist die Aggregation von zwei Klassen, die miteinander in Beziehung stehen. Auf diese Weise können wir eine Klasse Verkauft aus den Klassen Restaurant
und Speise aggregieren.
In der Verallgemeinerung (Generalisierung) können wir mehrere Klassen zu einer allgemeineren Klasse zusammenfassen, indem wir Gemeinsamkeiten hervorheben und Unterschiede vernachlässigen. So ist die Klasse Person eine Verallgemeinerung der Klassen Kunde und
Mitarbeiter. Attribute werden dabei entlang der Verallgemeinerungshierarchie vererbt: alle
Attribute der allgemeineren Klasse sind auch Attribute der spezielleren Klasse. In unserem
Fall könnte die Klasse Person die Attribute name, geburtsdatum und adresse haben. Damit
besitzen sowohl die Klasse Kunde als auch die Klasse Mitarbeiter diese Attribute. Allerdings sehen wir bei Mitarbeitern auch das Attribut svnr, die Sozialversicherungsnummer,
bzw. bei den Kunden eine Kundennummer knr vor.
2.2 Elementare ER-Konstrukte
Die in der Literatur und im Weiteren in diesem Skriptum verwendeten Begriffe sind folgendermaßen äquivalent:
auf Objektebene (= Exemplarebene = Instance level): Objekt = Entity-instance, Beziehung
= Relationship-instance
auf Objekttypebene (= Objektklassenebene = Schema level): Objekttyp = Entity, Beziehungstyp = Relationship
In der Literatur wird statt Entity oft der alte Begriff Entity-set verwendet, statt Entityinstance auch der Begriff Entity.
2.2.1 Grundlegende Objekte: Entities, Beziehungen und Attribute
Objekte bzw. Entity-instances repräsentieren jene wohlunterschiedenen Objekte des Problembereichs, über die Informationen gespeichert werden. Ein Objekt kann ein real existierendes
Objekt sein, z.B. eine Person, aber auch ein ideelles Objekt, z.B. eine Dienstleistung wie ein
Haarschnitt. Objekte mit denselben Eigenschaften werden zu Entities (Objekttypen) zusammengefasst (Klassifikation). Wir verwenden den englischen Begriff Entity, da die deutsche
Übersetzung Objekttyp nicht gebräuchlich und eher dürftig ist. Beispiele für Entities sind alle
Restaurants oder alle Speisen der Restaurants.
2.4
KAPITEL 2. KONZEPTIONELLE DATENMODELLE UND DAS ER MODELL
Konzept
Darstellung und Beispiel
Restaurant
Entity
Weak Entity
Speise
verkauft
Beziehung
Attribute
identifizierend
beschreibend
mehrwertig
rnr
name
typ
strasse
komplex
adresse
ort
plz
land
Abbildung 2.1: Elementare ER Konstrukte
Entities werden im ER durch ein Rechteck dargestellt, wobei die Bezeichnung der Entity
im Rechteck steht (Abbildung 2.1). Zur klaren Unterscheidung schreiben wir Namen von
Entities in diesem Text groß.
Beziehungen bzw. Relationship-instances zwischen Objekten haben als solche keine physische oder konzeptionelle Existenz, sondern ergeben sich aufgrund der vorhandenen Objekte.
Beziehungen zwischen Entities werden in der Klassifikation zu Relationships (Beziehungstypen) zusammengefasst. In diesem Fall verwenden wir die deutsche Bezeichnung Beziehungstyp, wobei wir aber das Beiwort -typ in weiterer Folge weglassen. Wenn wir von Beziehungen
auf Objektebene reden, dann werden wir uns an die englische Bezeichnung anlehnen und von
Instanzen einer Beziehung sprechen. Eine Beziehung zwischen zwei oder mehreren Entities
ist eine Aggregation zwischen diesen Entities. Die Beziehung wird dabei durch die Rolle der
an ihr beteiligten Entities beschrieben. Graphisch stellen wir Beziehungen in Form einer Raute dar, deren Ecken mit den beteiligten Entities verbunden sind. Die Rolle schreiben wir über
die Raute (Abbildung 2.1).
Attribute sind Charakteristika von Entities, die diese beschreiben. Die einzelnen Attribute
werden zu einer Entity aggregiert. Eine bestimmte Ausprägung eines Attributes bezeichnen
wir als Wert des Attributs. Graphisch stellen wir Attribute durch Ellipsen dar, die mit der
KAPITEL 2. KONZEPTIONELLE DATENMODELLE UND DAS ER MODELL
2.5
Entity, die sie charakterisieren, verbunden sind. Der Name des Attributs wird in die Ellipse
geschrieben. Zur Unterscheidung von Entitynamen schreiben wir die Attributnamen klein
(Abbildung 2.1).
Es gibt zwei Arten von Attributen: identifizierende und beschreibende. Identifizierende
Attribute oder Schlüssel sind jene Attribute, die einzelne Objekte einer Entity eindeutig kennzeichnen. Beschreibende Attribute oder Nicht-Schlüsselattribute stellen nicht eindeutige Charakteristika der Objekte dar und dienen zur weiteren Beschreibung. Schlüssel können aus einem oder aus mehreren Attributen bestehen. Jede Entity kann mehrere verschiedene Schlüssel
haben, wir stellen im ER aber immer einen ausgezeichneten Schlüssel, den Prim ärschlüssel,
durch Unterstreichung des Namens oder der Namen dar. Entities, deren Objekte nur mit Hilfe
einer anderen Entity oder mehreren anderen Entities, mit der bzw. denen sie in Beziehung
stehen, identifiziert werden können, nennen wir Weak Entities. Eine Weak Entity wird durch
doppelte Umrahmung dargestellt. Sie hat keine Attribute, die alleine den Schlüssel bilden,
obwohl sie dazu beisteuern können.
Attribute können mehrwertig sein, wie etwa der typ eines Restaurants. Mehrwertige Attribute werden durch eine doppelte Verbindung zur Entity gekennzeichnet. Weiters können
Attribute komplexe Werte annehmen, wie z.B. das Attribut adresse, das selbst aus mehreren
anderen Attributen aggregiert wird. Im ER können wir komplexe Attribute entweder dadurch
darstellen, dass sie selbst wieder Attribute haben (Abbildung 2.1), oder wir können die einzelnen Teile direkt an die Entity hängen.
Beispiel 2.1 Bei der Modellierung von R EINE sind wir in der Einleitung (Kapitel 1) auf die
Entities Restaurant, Speise, Kunde und Bestellung gestoßen.
Beispiele für Beziehungen in R EINE sind verkauft oder legt.
Die Entity Restaurant hat die Attribute name, adresse und typ. Schlüsselattribute sind
in diesem Fall name und adresse, da es möglich ist, dass es zwei oder mehrere Restaurants
mit demselben Namen gibt, etwa im Falle einer Kette. Der Einfachheit halber führen wir
ein Attribut rnr ein, d.h. eine Nummer, die ein Restaurant identifiziert. Dadurch führen wir
ein weiteres Schlüsselattribut ein, das für sich alleine die einzelnen Instanzen kennzeichnet;
diesen Schlüssel wählen wir als Primärschlüssel.
Die Objektmenge Speise wird durch die Attribute name und preis beschrieben. Der
Name einer Speise reicht aber alleine nicht zur Kennzeichnung aus, da dieselbe Speise in verschiedenen Restaurants einen unterschiedlichen Preis haben kann. Daher sehen wir, dass der
Name einer Speise nur gemeinsam mit der Nummer des jeweiligen Restaurants eindeutig ist.
Speise ist also eine Weak Entity, die den Schlüssel der Entity Restaurant zur eindeutigen
Kennzeichnung ihrer Objekte benötigt.
Das Attribut typ ist ein typisches Beispiel für ein mehrwertiges Attribut, da ein Restaurant
sowohl japanisch als auch koreanisch sein kann. Das Attribut adresse wiederum ist ein
schönes Beispiel eines komplexen Attributs, das sich aus den Attributen strasse, ort, plz
und land zusammensetzt.
KAPITEL 2. KONZEPTIONELLE DATENMODELLE UND DAS ER MODELL
2.6
Konzept
1:1
Darstellung und Beispiel
nach [Chen, 1976]
Restaurant
1
1
Mitarbeiter
Darstellung und Beispiel
nach [Teorey et al. 1986]
Restaurant
wird geleitet
1:n
Restaurant
1
n
Mitarbeiter
wird geleitet
Mitarbeiter
Restaurant
Mitarbeiter
hat
hat
n:m
Kunde
n
m
Speise
bestellt
Kunde
Speise
bestellt
Abbildung 2.2: Komplexität von Beziehungen
2.2.2 Komplexität einer Beziehung
Die Komplexität einer Beziehung zwischen Entities beschreibt, mit wievielen Instanzen der jeweils anderen Entity jede Instanz einer Entity in Beziehung stehen kann. Bei einer Beziehung
zwischen zwei Entities A und B gibt es die folgenden Möglichkeiten:
1:1 jedes Objekt von A zu genau einem Objekt von B und umgekehrt
1:n jedes Objekt von A zu einem oder mehreren von B, aber jedes Objekt von B nur zu einem
von A.
m:n jedes Objekt von A zu einem oder mehreren in B und umgekehrt.
Die Darstellung der Komplexität einer Beziehung nach Chen geschieht durch Anbringung
von Ziffern an den jeweiligen Entities. Dabei wird nur zwischen den Werten 1“ und viele
”
”
(n, m)“ unterschieden. Die genaue Anzahl der zugeordneten Objekte, d.h. die Kardinalität,
wird selten verwendet, da diese sich bei jeder Instanz einer Beziehung unterscheiden kann.
Teorey verwendet in [Teorey et al. 1986] nicht mehr die Werte, die wir neben die Entities
schreiben, sondern färbt die Hälften der Beziehung ein, die in einer zu-n“ Verbindung zu
”
einer Entity steht. In Abbildung 2.2 geben wir für jedes der eben vorgestellten Konstrukte ein
Beispiel in der Notation von Chen und jener von Teorey.
Beispiel 2.2 In R EINE hat jedes Restaurant genau einen Mitarbeiter als Geschäftsführer und
ein Mitarbeiter führt maximal ein Restaurant, was einer 1:1-Beziehung entspricht. Es gibt
auch Mitarbeiter, die kein Restaurant leiten, aber diesen Umstand können wir erst mit Hilfe
der optionalen Existenz aus dem nächsten Abschnitt darstellen.
KAPITEL 2. KONZEPTIONELLE DATENMODELLE UND DAS ER MODELL
Konzept
zwingend
2.7
Darstellung und Beispiel
Restaurant
Mitarbeiter
hat
optional
Restaurant
Mitarbeiter
wird geleitet
unbekannt
Kunde
Speise
bestellt
Abbildung 2.3: Existenz von Entities in Beziehungen
Ein Restaurant beschäftigt natürlich mehrere Mitarbeiter, aber ein Mitarbeiter kann nur in
einem Restaurant angestellt sein. Wir möchten hier auch darauf hinweisen, dass die Rolle der
Beziehung unterschiedlich bezeichnet werden kann, je nachdem in welche Richtung wir die
Beziehung lesen.
Kunden wiederum können mehrere Speisen bestellen und eine Speise kann von mehreren
Kunden bestellt werden.
2.2.3 Existenz einer Entity in einer Beziehung
Wie im letzten Abschnitt beschrieben, gibt die Komplexität einer Beziehung an, mit wievielen
Instanzen der anderen Entity jede Instanz der einen Entity in Beziehung stehen kann. Dabei
haben wir bis jetzt immer von einer“ oder von vielen“ Instanzen gesprochen. Wir haben
”
”
aber keine Möglichkeit auszudrücken, ob es immer mindestens eine Instanz geben muss, oder
ob es in der einen Entity eine Instanz geben kann, die mit keiner Instanz der anderen Entity in Beziehung steht. Das Konzept der Existenz einer Entity in einer Beziehung gibt uns die
Möglichkeit auch diesen Sachverhalt zu modellieren. Die Existenz einer Entity in einer Beziehung heißt obligatorisch, wenn es zu jeder Instanz dieser Entity mindestens eine Instanz der
mit ihr verbundenen Entity gibt, die mit ihr in Beziehung steht. Ist eine solche Instanz nicht
unbedingt nötig, so heißt sie optional. Graphisch stellen wir optionale Existenz mit einem
Kreis auf der Verbindung zur Entity, obligatorische mit einem senkrechten Strich dar (siehe
Abbildung 2.3).
Beispiel 2.3 Ein Restaurant in R EINE hat mehrere Mitarbeiter, aber mindestens einen, und
jeder Mitarbeiter ist genau einem Restaurant zugeordnet. In diesem Fall stellen wir die
KAPITEL 2. KONZEPTIONELLE DATENMODELLE UND DAS ER MODELL
2.8
Konzept
Darstellung und Beispiel
nach [Chen, 1976]
Darstellung und Beispiel
nach [Teorey et al. 1986]
m
unär
Kunde
Kunde
n
verwandt mit
binär
Lieferant
ternär
Mitarbeiter
1
n
Auto
verwandt mit
Lieferant
Auto
hat
hat
Bestellung
n
Bestellung
1
1
Auto
Mitarbeiter
liefert
Auto
liefert
Abbildung 2.4: Grad von Beziehungen
zwingende Existenz einer Instanz der Entities Restaurant und Mitarbeiter in der Beziehung hat durch einen senkrechten Strich in Abbildung 2.3 dar. Weiters sind manche Mitarbeiter Geschäftsführer eines Restaurants. Die optionale Existenz einer Instanz der Entity
Restaurant in der Beziehung wird geleitet stellen wir durch den Kreis in Abbildung 2.3
dar. In der Beziehung bestellt zwischen den Entities Kunde und Speise lassen wir die
Existenz von Instanzen offen.
2.2.4 Grad einer Beziehung
Der Grad einer Beziehung ist die Anzahl der Entities, die in dieser Beziehung miteinander verbunden sind. Eine Beziehung heißt n-äre Beziehung, wenn sie vom Grad n ist. Unäre, binäre
und ternäre Beziehungen sind Spezialfälle, wobei unäre und binäre Beziehungen die in der
realen Welt am häufigsten vorkommenden sind. Unäre Beziehungen, das sind Beziehungen
einer Entity mit sich selbst, heißen auch binär rekursive Beziehungen (siehe Abbildung 2.4).
Ternäre Beziehungen, also Beziehungen zwischen drei Entities, benötigen wir, wenn binäre
Beziehungen den Sachverhalt nicht ausreichend beschreiben. Kann jedoch eine ternäre Beziehung mit Hilfe von zwei oder drei binären Beziehungen ausgedrückt werden, so ist der
Einfachheit und Klarheit wegen die Darstellung durch binäre Beziehungen vorzuziehen.
Auch bei ternären Beziehungen wird die Komplexität entweder durch Angabe eines Wertes oder Einfärben der Ecken angegeben. Im Falle von ternären Beziehungen hat eine Entity
Komplexität eins“, wenn es zu Instanzen der beiden anderen Entities gemeinsam maximal
”
KAPITEL 2. KONZEPTIONELLE DATENMODELLE UND DAS ER MODELL
2.9
eine ihrer Instanzen gibt, sie hat Komplexität n“, wenn es zu Instanzen der beiden anderen
”
Entities gemeinsam mehrere Instanzen ihrer Entities geben kann.
Beispiel 2.4 Wollen wir für Kunden, die miteinander verwandt sind, einen Bonus einführen,
so müssen wir die Verwandtschaft mitmodellieren. Daraus erhalten wir eine unäre (binär
rekursive) Beziehung zwischen den Kunden.
Modellieren wir für R EINE den Bereich der Lieferungen, so identifizieren wir die Entities
Lieferant, Mitarbeiter und Auto. Eine Lieferfirma hat mehrere Mitarbeiter und Autos.
Daher gibt es zwischen den Entities Lieferant und Auto eine binäre Beziehung, ebenso wie
zwischen Lieferant und Mitarbeiter. Für eine konkrete Bestellung wird von der Lieferfirma ein Auto und ein Mitarbeiter abgestellt. Daher erhalten wir folgende ternäre Beziehung,
die wir in Abbildung 2.4 graphisch darstellen:
• Ein Mitarbeiter verwendet für eine Bestellung genau ein Auto.
• Ein Auto wird bei einer Bestellung von genau einem Mitarbeiter gefahren.
• Ein Mitarbeiter kann mit einem bestimmten Auto mehrere Bestellungen erledigen.
Insgesamt gibt es bei ternären Beziehungen vier verschiedene Möglichkeiten, die Komplexität zu kombinieren: drei zu 1“- Beziehungen, zwei zu 1“- Beziehungen und eine zu
”
”
”
n“- Beziehung, eine zu 1“- Beziehung und zwei zu n“- Beziehungen oder drei zu n“- Be”
”
”
ziehungen. Eine ausführliche Beschreibung dieser Möglichkeiten wird in [Teorey, 1999] und
[Teorey et al. 1986] (im Anhangzum Skriptum der Laborübung) gegeben.
2.2.5 Attribute einer Beziehung
Attribute können, wie wir gesehen haben, zu Entities aggregiert werden. Es gibt aber auch die
Möglichkeit, Attribute zu Beziehungen zu aggregieren. So können wir die Attribute anzahl
und datum zur Beziehung zwischen Kunde und Speise schreiben. Dadurch tragen wir dem
Umstand Rechnung, dass ein Kunde eine Speise mehrmals an unterschiedlichen Tagen bestellen kann. Würden wir diese Attribute zum Kunden aggregieren, würden wir ein mehrwertiges
Attribut erhalten und zudem die Information verlieren, welche Speise der Kunde zu welchem
Datum bestellt hat.
Attribute werden üblicherweise jedoch nur zu n:m-Beziehungen aggregiert, da im Falle
von 1:1-oder 1:n-Beziehungen zumindest auf einer der beiden Seiten der Beziehung ein einziges Objekt steht und damit die Mehrdeutigkeit kein Problem darstellt. Wollen wir in der
Beziehung zwischen Restaurant und Mitarbeiter auch das Einstellungsdatum modellieren, so können wir das Attribut datum zum Mitarbeiter aggregieren. Ändert sich der Grad der
Beziehung, d.h. soll es möglich sein, dass Mitarbeiter in mehreren Restaurants arbeiten, dann
müssen wir das Attribut datum vom Mitarbeiter zur Beziehung schieben.
Wenn wir Attribute zu n:m-Beziehungen aggregieren, müssen wir uns überlegen, ob wir
nicht an Stelle der Beziehung eine Weak Entity modellieren, zu der die Attribute aggregiert
KAPITEL 2. KONZEPTIONELLE DATENMODELLE UND DAS ER MODELL
2.10
datum
datum
anzahl
Kunde
Speise
Kunde
anzahl
Bestellung
Speise
bestellt
Abbildung 2.5: Attribute einer Beziehung vs. Weak Entity
werden. Jede n:m-Beziehung entspricht einer Weak Entity, die durch 1:n-Beziehungen mit
den beiden sie definierenden Entities verbunden ist (siehe Abbildung 2.5).
Beispiel 2.5 Im Falle der n:m-Beziehung bestellt mit den Attributen datum und anzahl
ist die Modellierung einer Weak Entity Bestellung sicher klarer, wie wir in Beispiel 2.5
zeigen.
2.3 Erweiterte ER-Konstrukte
2.3.1 Die Generalisierung
Das Konzept der Verallgemeinerung konnte mit den Mitteln des im letzten Abschnitt besprochenen ER-Modells nur sehr dürftig dargestellt werden, nämlich als eine spezielle 1:1Beziehung zwischen zwei Entities, die mit is-a gekennzeichnet wurde. So konnten wir die
Entities Mitarbeiter und Kunden, die viele gemeinsame Attribute besitzen, zu einer Entity Person verallgemeinern und mit jeweils einer 1:1-Beziehung verbinden. Die Attribute der
Person werden entlang der Verallgemeinerungshierarchie vererbt und spezielle Attribute – wie
die Sozialversicherungsnummer der Mitarbeiter – nur bei den speziellen Entities gespeichert.
Ein erweitertes Konstrukt hingegen, die Generalisierung, ermöglicht es uns, diesem Umstand
besser gerecht zu werden und außerdem noch einige andere Sachverhalte auszudrücken.
Die Generalisierung gibt an, dass mehrere Entities (Subtyp-Entities) mit bestimmten gemeinsamen Attributen zu einer Entity auf einer höheren Ebene (Supertyp-Entity) generalisiert
werden können. Die Disjunktheit der Generalisierung beschreibt, ob die einzelnen SubtypEntities disjunkt (disjoint) oder überlappend (overlapping) sind. Im Falle von überlappenden
Subtyp-Entities wurde früher auch von Subsets gesprochen, bei disjunkten Subtyp-Entities
von Generalisierung, wobei in diesem Fall die Supertyp-Entity durch ein den Subtyp-Entities
gemeinsames Attribut mit unterschiedlichen Werten partitioniert wird. Die Vollständigkeit in
der Generalisierung gibt an, ob die Subtyp-Entities die Supertyp-Entity vollständig abdecken
oder nur teilweise. Durch die beiden Eigenschaften der Disjunktheit und der Vollständigkeit
sind in Summe vier Kombinationen möglich.
Eine Subtyp-Entity kann ihrerseits wieder eine Supertyp-Entity bezüglich anderer Entities darstellen. Mehrere derartige Subtyp/Supertyp Strukturen werden auch als Generalisie-
KAPITEL 2. KONZEPTIONELLE DATENMODELLE UND DAS ER MODELL
Person
2.11
Person
o
is-a
Kunde
Mitarbeiter
d
Mitarbeiter
Schreibkraft
Angestellter
Manager
Abbildung 2.6: Beispiel einer Generalisierungshierarchie in R EINE
rungshierarchie bezeichnet, entlang der die Attribute jeweils von den Supertyp-Entities zu den
Subtyp-Entities weitergegeben werden.
Graphisch wird die Generalisierung durch eine Verbindung der Subtyp-Entities mit der
Supertyp-Entity dargestellt, wobei in einem Kreis angegeben wird, ob es sich um disjunkte
( d“) oder überlappende ( o“) Subtyp-Entities handelt. Weiters wird das Teilmengen Symbol
”
”
auf den Verbindungslinien aufgezeichnet. Im Falle einer vollständigen Überdeckung verwenden wir eine doppelte Linie als Verbindung zwischen der Supertyp-Entity und dem Kreis.
Beispiel 2.6 In R EINE werden verschiedenste Personendaten gespeichert. So können wir
zwischen Kunden und Mitarbeitern unterscheiden. Beide Entities sind Subtyp-Entities der
Entity Person, und da Mitarbeiter auch gleichzeitig Kunden sein können, haben wir zwei
überlappende Subtyp-Entities. Da wir keine anderen Personen außer Kunden und Mitarbeiter
speichern wollen, handelt es sich hierbei um eine totale überlappende Generalisierung. Die
Mitarbeiter selber können wir in die disjunkten Subtyp-Entities Manager, Angestellter und
Schreibkraft unterteilen. Da es auch Mitarbeiter gibt, die in keine dieser Kategorien fallen,
ist diese Generalisierung nicht vollständig (Abbildung 2.6).
2.3.2 ER-Constraints
Für die Modellierung des konzeptionellen Schemas einer Datenbank gibt es nicht nur die ERMethoden, sondern verschiedenste andere Denkansätze, wobei einige eine reichere Semantik
als das ER-Modell bieten. Einer dieser Ansätze ist das Binary Relationship Modell, das Basis
der Nijssens Information Analysis Method (NIAM) ist. Die Grundkonstrukte im BR-Modell
sind lexical object types, nonlexical object types und roles. Diese entsprechen im ER-Modell
Attributen, Entities und Relationships. Ein Vorteil dieses Modells ist, dass die Entscheidung,
2.12
KAPITEL 2. KONZEPTIONELLE DATENMODELLE UND DAS ER MODELL
Rechnung
+
Kreditkarte
Lieferant
Abbildung 2.7: Beispiel einer Exklusionsbedingung in R EINE
ob etwas ein Attribut oder eine Entity ist, so spät als möglich gefällt wird. Weiters gibt es die
semantischen Konzepte der Generalisierung, Komplexität von Beziehungen und Existenz von
Entities in Beziehungen (optional und zwingend). Eine wirkliche Erweiterung der Semantik im Binary Relationship Modell ist allerdings die Hinzunahme von Integritätsbedingungen
(integrity constraints) bei roles. Wir zeigen im nächsten Abschnitt, wie eine der Bedingungsarten, nämlich Exklusionsbedingungen (exclusion constraints), dem ER-Modell hinzugefügt
werden kann. Wir möchten aber sehr wohl darauf hinweisen, dass eine reichere Semantik im
konzeptuellen Modell nicht unbedingt zu einem besseren Entwurf führen muss, da das Modell
wesentlich komplexer und dadurch unverständlicher werden kann, als bei der Verwendung
einfacher semantischer Konzepte.
2.3.2.1 Exklusionsbedingungen
Üblicherweise wird, wenn eine Entity mit mehreren anderen Entities binär verbunden ist,
angenommen, dass einige oder alle diese Entities mit der ersten in Beziehung stehen. Die
Exklusionsbedingung ermöglicht es uns zu modellieren, dass von mehreren (im Besonderen
zwei) Entities immer nur eine in Beziehung zur ersten Entity tritt. Dargestellt wird die Exklusionsbedingung durch eine Verbindung der daran beteiligten Beziehungen, die mit einem
Kreis und einem +“ gekennzeichnet ist, wie wir in Abbildung 2.7 sehen können.
”
Beispiel 2.7 In R EINE werden zur Bezahlung der Rechnungen mehrere Möglichkeiten angeboten. Eine davon ist über Kreditkarte, eine weitere über Barbezahlung beim Lieferanten.
Daher müssen wir bei der Entity Rechnung einerseits eine Beziehung zur Entity Kreditkarte
und andererseits auch zur Entity Lieferant haben, wobei jedoch für jede Rechnung entweder nur der Verweis auf die Kreditkarte oder der Verweis auf den Lieferanten von nöten ist,
niemals aber beides. Diesen Umstand haben wir in Abbildung 2.7 dargestellt.
KAPITEL 2. KONZEPTIONELLE DATENMODELLE UND DAS ER MODELL
2.13
2.4 Objektorientierte Datenmodellierung
Objektorientierte Datenbankmanagementsysteme, die bis vor ein paar Jahren noch recht selten benutzt wurden, nehmen langsam aber sicher eine immer wichtigere Rolle auf dem Datenbanksektor ein. Dabei wurden wohlbekannte Konzepte der objektorientierten Programmierung mit neuen Ideen der Datenmodellierung verknüpft. Im objektorientierten Ansatz werden
Klassen als eine Menge von Methoden – Operationen auf bestimmten Klassen von Objekten –
gesehen, das ER-Modell hingegen beschränkt sich auf die Sicht von Klassen (Sub- und Supertyp) als Beziehung zwischen Objekten und ignoriert das dynamische Verhalten von Objekten.
Im folgenden Abschnitt werden wir kurz auf die wichtigsten objektorientierten Konzepte eingehen.
2.4.1 Objektorientierte Konzepte
Vier Charakteristika zeichnen den objektorientierten Ansatz aus: Identität, Klassifizierung,
Polymorphismus und Vererbung.
Identität: Die Daten werden in unterscheidbare Objekte aufgeteilt. Jedes Objekt (Instancelevel) besitzt eine eigene Identität aufgrund seiner inhärenten Existenz und nicht aufgrund von beschreibenden Eigenschaften, die es hat. So sind zwei Äpfel, die gleiches
Aussehen haben, dennoch zwei unterschiedliche Dinge, sie können z.B. von verschiedenen Personen gegessen werden.
Klassifizierung: Objekte mit denselben Datenstrukturen (Attributen) und demselben Verhalten werden zu einer Klasse zusammengefasst. Die Objekte haben für jedes Attribut eigene Werte, aber die Namen der Attribute und Methoden (Operationen) werden mit den
anderen Objekten der Klasse geteilt. Weiters umfasst die Klassifizierung auch die Konzepte der Datenabstraktion (selektive Betrachtung bestimmter Aspekte eines Problems)
und –kapselung (Trennung des externen Verhaltens eines Objekts von der konkreten
Implementierung).
Polymorphismus: Eine bestimmte Operation kann sich innerhalb verschiedener Klassen verschieden verhalten. Eine Operation copy etwa wird unterschiedliche Implementierungen für verschiedene Speichermedien wie Buffer oder Dateien auf der Platte besitzen.
Vererbung: Attribute und Operationen werden entlang der Klassenhierarchie vererbt. Jede
Klasse kann mehrere Unterklassen besitzen, die Attribute und Operationen ihrer Superklasse erben, und zusätzlich neue Attribute und Operationen definieren. Etwas problematisch und in verschiedenen objektorientierten Programmiersprachen unterschiedlich behandelt ist Mehrfachvererbung, wonach eine Klasse mehrere Superklassen haben
kann und daher von unterschiedlichen Seiten erbt.
2.14
KAPITEL 2. KONZEPTIONELLE DATENMODELLE UND DAS ER MODELL
Zu den am meisten verbreiteten objektorientierten Analyse- (OOA) und Design- (OOD)
Techniken gehören OOA nach Shlaer und Mellor (1988) und Coad und Yourdon (1990), OOD
nach Booch und die Object Modeling Technique (OMT) von Rumbaugh. Eine in letzter Zeit
immer weiter verbreitete Technik ist die Unified Modeling Language (UML), eine Weiterentwicklung und Zusammenführung von OMT und OOD.
Kapitel 3
Das Relationenmodell
In diesem Kapitel stellen wir das Relationenmodell vor, das heute die Grundlage vieler kommerzieller Datenbankmanagementsysteme, wie ADABAS, DB2, INFORMIX, INGRES, SYBASE, ORACLE, PROGRESS und UNIFY bildet und somit das am weitesten verbreitete
logische Datenmodell ist. Nach der Vorstellung des Relationenmodells und der darauf möglichen Operationen beschreiben wir kurz, wie eine Übersetzung des ER-Modells in das Relationenmodell durchzuführen ist. Am Ende des Kapitels stellen wir weitere Sprachen für das
Relationenmodell vor.
Das Relationenmodell wurde von E. F. Codd 1970 entwickelt. Es repräsentiert die Daten einer Datenbank als eine Menge von Relationen. Eine Relation können wir uns dabei
als Tabelle vorstellen, deren Zeilen Objekte der Anwendungsumgebung oder Beziehungen
zwischen Objekten der Anwendungsumgebung beschreiben. Der Tabellenkopf heißt Relationenschema, die einzelnen Spalten werden als Attribute bezeichnet, die einzelnen Zeilen als
Tupel.
3.1 Formalisierung des Relationenmodells
Ein Relationenschema R ist eine endliche Menge von Attributnamen {A 1 , A2 , ...An }. Attributnamen werden auch kurz als Attribute bezeichnet. Seien R und S zwei Relationenschemata, so bezeichnet RS die Menge aller Attributnamen aus R und S, wobei gleiche Namen nur
einmal vorkommen.
Zu jedem Attributnamen Ai gibt es eine Menge Di , 1 ≤ i ≤ n, den Wertebereich (domain)
von Ai , der auch mit Dom(Ai ) bezeichnet wird. Die Wertebereiche sind beliebige, nicht leere,
endliche oder abzählbar unendliche Mengen.
Sei D = D1 ∪ D2 ∪ D3 ∪ ... ∪ Dn . Eine Relation r(R) auf einem Relationenschema R ist
eine endliche Menge von Abbildungen {t1 , ..., tm } von R nach D, wobei für jede Abbildung
tj ∈ r(R), tj (Ai ) aus Di stammt, 1 ≤ i ≤ n, 1 ≤ j ≤ m. Die Abbildungen werden Tupel
genannt. Intuitiv stellt ein Relationenschema R eine Menge von gültigen Instanzen r(R) dar.
1
3.2
KAPITEL 3. DAS RELATIONENMODELL
Beispiel 3.1 In Kapitel 1 haben wir bei der Vorstellung des logischen Entwurfs schon ein
Beispiel (siehe Abbildung 1.13) für eine Relation gesehen. Dabei war Restaurant ein Relationenschema mit den Attributen rnr, name, adresse, haube und typ, Speise ein Relationenschema mit den Attributen name und preis. Die Relationenschemata sehen daher
folgendermaßen aus (warum bei der Relation Speise das Attribut rnr vorkommt, werden wir
am Ende dieses Abschnittes erklären; intuitiv deshalb, damit wir feststellen können, welche
Speise welchem Restaurant zugeordnet ist):
Restaurant = {rnr, name, adresse, haube, typ}
Speise = {name, preis, rnr}
Eine mögliche Relation für Restaurant und Speise zeigen wir in Abbildung 3.1.
Beispiel 3.2 Für das Relationenschema Restaurant={rnr, name, adresse, haube,typ} aus
Beispiel 3.1 können wir folgende Angaben machen:
• Dom(rnr) = Menge aller Integer.
• Dom(name) = Menge aller Namen.
• Dom(adresse) = Menge aller Adressen.
• Dom(haube) = {k | 0 ≤ k ≤ 4}.
• Dom(typ) = Menge aller Restauranttypen.
• Die Tabelle hat 9 Tupel. Eines von ihnen ist t mit:
• t(rnr) = 3,
• t(name) = Green Cottage,
• t(adresse) = Kettenbrückengasse 3, 1050 Wien,
• t(haube) = 2,
• t(typ) = chinesisch.
Der Wert eines Tupels t für ein Attribut A, t(A) = a, heißt A-Wert von t. Sei X eine
Teilmenge von R. Unter der Einengung des Tupels t auf die Attributmenge X ⊂ R, genannt
t0 (X), verstehen wir jenes Tupel t0 , das jedem A ∈ X genau dieselben Werte aus Dom(A)
zuordnet wie t.
Beispiel 3.3 Sei t das Tupel mit t(rnr) = 3, t(name) = Green Cottage, t(adresse) = Kettenbrückengasse 3, 1050 Wien, t(haube) = 2 und t(typ) = chinesisch.
• Der adresse-Wert von t ist t(adresse) = Kettenbrückengasse 3, 1050 Wien.
• Die Einengung von t auf die Attribute {name, adresse} ist das Tupel t 0 definiert als
t0 (name) = Green Cottage, t0 (adresse) = Kettenbrückengasse 3, 1050 Wien.
Ein Schlüssel (key) einer Relation r(R) ist eine Teilmenge K von R, sodass für je zwei
verschiedene Tupel t1 und t2 aus r(R) immer t1 (K) 6= t2 (K) gilt, und keine echte Teilmenge
K 0 von K diese Eigenschaft hat. S ist ein Oberschlüssel (superkey), wenn S einen Schlüssel
enthält. Jeder Schlüssel ist also auch ein Oberschlüssel, die Umkehrung gilt hingegen im
Allgemeinen nicht.
KAPITEL 3. DAS RELATIONENMODELL
Restaurant
rnr name
1 Gußhaus
2 A Tavola
3 Green Cottage
4 Drei Husaren
5 San Carlo
6 Toko-Ri
7 Steirereck
8 Carpaccio
9 Indian Pavillion
adresse
Gußhausstraße 23, 1040 Wien
Weihburggasse 3-5, 1010 Wien
Kettenbrückengasse 3, 1050 Wien
Weihburggasse 4, 1010 Wien
Mahlerstraße 3, 1010 Wien
Franz-Hochedlinger-Gasse 2, 1020 Wien
Rasumofskygasse 2, 1030 Wien
Paniglgasse 22, 1040 Wien
Naschmarkt Stand 74-75, 1040 Wien
3.3
haube
1
2
2
0
4
1
0
Speise
name
Gebratener Rehrücken mit Serviettenknödel
Gefüllte Perlhuhnbrust mit Maroniknöderln
Zarte Rotbarbe auf Wildreis
Gemischte Käseplatte
Gemischter Vorspeisenteller
Penne all’ Arrabiata
Hühnerfleisch der tausend Geschmäcker
Wolfsbarschfilet mit sichuanesischer Lauchsauce
Gebratene Seeteufel
Eisei im gebackenen Nudelnest
Geeiste Karfiolrahmsuppe
Gedünstetes Beiried in Zweigeltsauce
Tafelspitz mit Markscheiben, Cremespinat und gestürzten Erdäpfeln
Orangenblütenmousse in der Babyananas
Joghurt-Grießflammeri mit Beeren
Husarenpfannkuchen
Kleines Sushi
Großes Sushi
Gemischte Maki für 2 Personen
typ
österreichisch
toskanisch
chinesisch
österreichisch
italienisch
japanisch
international
italienisch
indisch
preis rnr
21
1
26
1
25
1
10
1
10
2
9,5
2
6,5
3
25
3
23
3
6,5
3
7
4
25
4
23
4
7
4
6,5
4
10
4
12
6
15
6
21
6
Abbildung 3.1: Beispiele einer Relation für Restaurant und Speise in R EINE
KAPITEL 3. DAS RELATIONENMODELL
3.4
Beispiel 3.4 Betrachten wir wieder das Relationenschema Restaurant aus Beispiel 3.1. Aus
der Tabelle mit den Entity-Instanzen ist ersichtlich, dass alle Attribute bis auf haube und typ
als Schlüssel in Frage kommen. Da ein Schlüssel aber auch zeitinvariant sein sollte, und wir
nicht wissen, ob wir nicht einmal zwei Restaurants mit demselben Namen in unsere Relation eintragen müssen, ist es sinnvoller, die Restaurantnummer rnr als Schlüssel zu wählen.
Genauso ist es möglich, dass an einer Adresse zwei Restaurants, z.B. ein Restaurant und ein
Schnellimbiss mit unterschiedlichem Namen eingerichtet werden können. Das Relationenschema für die Speise im ER haben wir als Weak Entity modelliert, da eine Speise mit einem
bestimmten Namen in mehreren Restaurants angeboten werden kann. Der Name ist daher nur
bezogen auf ein bestimmtes Restaurant eindeutig.
Schlüssel, die explizit zu einem Relationenschema angeführt sind, heißen ausgezeichnete
Schlüssel (designated keys). Im Allgemeinen wird dabei ein Schlüssel als Prim ärschlüssel
ausgezeichnet und im Relationenschema durch Unterstreichen der Schlüsselattribute gekennzeichnet.
Beispiel 3.5 Die Relationenschemata für Restaurant und Speise mit gekennzeichnetem
Primärschlüssel sehen wie folgt aus:
Restaurant = {rnr, name, adresse, haube, typ}
Speise = {name, preis, rnr}
3.2 Operationen auf Relationen
Um Operationen auf Relationen durchführen zu können, wurde von Codd im Jahr 1972 die
relationale Algebra eingeführt. Die wichtigsten Operationen der relationalen Algebra sind
Mengenoperationen, Selektion, Projektion, Division und die Verbundoperation (join).
Im folgenden bezeichnen r und s Relationen über den Relationenschemata R bzw. S.
3.2.1 Die Mengenoperationen
Zu den Mengenoperationen gehören
• Durchschnitt ( ∩“),
”
• Vereinigung ( ∪“) und
”
• Differenz ( −“ oder \“)
”
”
von Relationen, die über der gleichen Attributmenge mit derselben Anordnung (der identischen Reihenfolge der Attribute) definiert sind.
KAPITEL 3. DAS RELATIONENMODELL
3.5
Beispiel 3.6
r
(A
a1
a1
a2
B
b1
b2
b1
C)
c1
c1
c2
s
(A
a1
a2
a2
B
b2
b2
b2
C)
c1
c1
c2
r∩s=
(A B C)
a1 b 2 c1
r∪s=
(A B
a1 b 1
a1 b 2
a2 b 1
a2 b 2
a2 b 2
r−s=
(A B C)
a1 b 1 c1
a2 b 1 c2
s−r=
(A B C)
a2 b 2 c1
a2 b 2 c2
C)
c1
c1
c2
c1
c2
3.2.2 Die Selektion
Bei der Selektion werden Zeilen ausgewählt, die einem bestimmten Kriterium entsprechen.
Formal
σA=a (r) = {t ∈ r | t(A) = a}
Der Selektionsoperator ist kommutativ bezüglich der Komposition (Zusammensetzung):
σA1 =a (σA2 =b (r)) = σA2 =b (σA1 =a (r)).
Beispiel 3.7 Wieder zu unserem Beispiel mit den Restaurants. Wir selektieren alle jene Restaurants, die zwei Hauben haben.
σhaube=2 (Restaurant) =
rnr name
adresse
3 Green Cottage Kettenbrückengasse 3, 1050 Wien
4 Drei Husaren Weihburggasse 4, 1010 Wien
haube
2
2
typ
chinesisch
österreichisch
KAPITEL 3. DAS RELATIONENMODELL
3.6
3.2.2.1 Erweiterung der Selektion
Um die Kriterien, nach denen selektiert werden soll, etwas allgemeiner zu halten, können
wir in der erweiterten Selektion beliebige Vergleichsoperatoren verwenden und nicht nur mit
Konstanten vergleichen.
Sei Θ eine Menge von Vergleichsoperatoren θ ∈ Θ ein Operator aus dieser Menge und a
eine Konstante aus dem Wertebereich Dom(A) von A:
σAθa (r) = {t ∈ r | t(A)θa}
σA1 θA2 (r) = {t ∈ r | t(A1 )θt(A2 )}
Noch allgemeiner wird die Selektion, wenn wir erlauben, wohldefinierte Operatoren auf
den Attributwerten auszuführen, z.B. arithmetische Operationen auf Zahlwerten, und logische
Verknüpfungen von Attributen durch und“ (∧), oder“ (∨) und Negation (¬).
”
”
Beispiel 3.8 Nun selektieren wir in der Relation Restaurant alle jenen Restaurants, die mehr
als eine Haube, aber keine österreichische oder internationale Küche haben.
σhaube>1∧¬(typ=0 österreichisch 0 ∨typ=0 international 0 ) (Restaurant) =
rnr name
adresse
3 Green Cottage Kettenbrückengasse 3, 1050 Wien
haube
2
typ
chinesisch
3.2.3 Die Projektion
Bei der Projektion werden gewisse Spalten einer Tabelle ausgewählt; wir projizieren nach
einer Teilmenge der Attribute:
πX (r) = {t(X) | t ∈ r} für X ⊆ R
Alternativ kann, falls die Attribute des Relationenschemas geordnet betrachtet werden, die
Nummer des projizierten Attributs angegeben werden: z.B.:
π2,3,5 (Restaurant) = πname,adresse,typ (Restaurant)
Der Projektionsoperator ist kommutativ bezüglich der Selektion, wenn die Attribute, auf
denen selektiert wird, in den projizierten Attributen enthalten sind:
πA1 ,A2 (σA1 θa (r)) = σA1 θa (πA1 ,A2 (r))
Beispiel 3.9 Wir projizieren die Relation Restaurant nach den Attributen name, adresse
und haube.
πname,adresse,haube (Restaurant) =
KAPITEL 3. DAS RELATIONENMODELL
name
Gußhaus
A Tavola
Green Cottage
Drei Husaren
San Carlo
Toko-Ri
Steirereck
Carpaccio
Indian Pavillion
3.7
adresse
Gußhausstraße 23, 1040 Wien
Weihburggasse 3-5, 1010 Wien
Kettenbrückengasse 3, 1050 Wien
Weihburggasse 4, 1010 Wien
Mahlerstraße 3, 1010 Wien
Franz-Hochedlinger-Gasse 2, 1020 Wien
Rasumofskygasse 2, 1030 Wien
Paniglgasse 22, 1040 Wien
Naschmarkt Stand 74-75, 1040 Wien
haube
1
2
2
0
4
1
0
3.2.4 Der Verbund
3.2.4.1 Der natürliche Verbund (natural join)
Der Verbundoperator verknüpft zwei Relationen über ihre gemeinsamen Attribute:
r ./ s = {t(RS) | ∃tr ∈ r und ∃ts ∈ s : tr = t(R) und ts = t(S)}.
Der Verbundoperator ist kommutativ.
Beispiel 3.10 Nehmen wir wieder Bezug auf unsere Relationen Restaurant und Speise.
Der natürliche Verbund verknüpft beide Relationen über die gemeinsamen Attribute und gibt
daher jene Tupel aus, bei denen sowohl der Name name des Restaurants und der Name name
der Speise als auch die Restaurantnummer rnr des Restaurants und jene der Speise gleich
sind. In unserem Fall ist das die leere Menge.
Restaurant ./ Speise =
rnr
name
adresse
haube
typ
preis
3.2.4.2 Das Kartesische Produkt
Falls R ∩ S = {}, die beiden Relationenschemata also kein gemeinsames Attribut haben, so
liefert die Verknüpfung r ./ s das Kartesische Produkt, geschrieben als r × s“.
”
Beispiel 3.11 Betrachten wir die folgenden Relationen r und s:
r
(A
a1
a2
B)
b1
b1
s
(C
c1
c2
c2
D)
d1
d1
d2
KAPITEL 3. DAS RELATIONENMODELL
3.8
r × s = r ./ s =
(A B C D)
a1 b 1 c1 d 1
a1 b 1 c2 d 1
a1 b 1 c2 d 2
a2 b 1 c1 d 1
a2 b 1 c2 d 1
a2 b 1 c2 d 2
Wie wir oben gesehen haben, ist das Kartesische Produkt nur für den Fall definiert, dass
R ∩ S = {}. Wollen wir das Kartesische Produkt von Relationen bilden, die gemeinsame
Attribute haben, so müssen diese in einer der Relationen umbenannt werden. Ist etwa R =
{A, B, C} und S = {A, B, D}, so benennen wir die Attribute von S um sodass S = {A 0 , B0 , D}
oder kennzeichnen sie durch Voranstellen des Relationennamens, also S = {S.A, S.B, D}.
Projektionseigenschaften des Verbundoperators: Seien R und S zwei Relationenschemata q = s ./ r und r0 = πR (q), dann gilt: r0 ⊆ r. Joinen wir also eine Relation r
mit einer anderen und projizieren dann nach den ursprünglichen Attributen von r, so können
unter Umständen Tupel verloren gehen, wie wir anhand des folgenden Beispieles sehen.
Beispiel 3.12 Betrachten wir die folgenden Relationen r und s:
r
(A
a
a
B)
b
b0
r ./ s = q
(A B C)
a b c
s
(B
b
C)
c
πAB (q) = r0
(A
B)
a
b
Sei q eine Relation über RS und q0 = πR (q) ./ πS (q), so gilt: q0 ⊇ q. In anderen Worten,
ist q eine Relation mit den Attributmengen R und S und projizieren wir q zuerst nach diesen
zwei Attributmengen, um die Ergebnisse danach wieder miteinander zu verbinden, so erhalten
wir unter Umständen mehr Tupel als in der ursprünglichen Relation.
Gilt q0 = q, dann sagen wir, die Relation q(RS) ist verlustfrei zerlegbar (decomposes
losslessly) in r(R) = πR (q) und s(S) = πS (q).
Eine Relation q = r ./ s ist dann verlustfrei zerlegbar, wenn die Join-Attribute zwischen
den Relationen r und s Schlüssel in einer der beiden Relationen sind.
Dieses Kriterium wird später für die korrekte Zerlegung von Relationenschemata benötigt
(siehe Kapitel 7).
KAPITEL 3. DAS RELATIONENMODELL
3.9
Beispiel 3.13 Sei R = AB, S = BC und q der Gestalt:
q
(A
a
a
B
b
b’
C)
c
c’
bzw.
q
(A
a
a
a’
B
b
b’
b
C)
c
c’
c’
q0
(A
a
a
B
b
b’
C)
c
c’
Im ersten Fall ist q verlustfrei zerlegbar, denn
r
(A
a
a
B)
b
b’
s
(B
b
b’
C)
c
c’
Im zweiten Fall ist q nicht verlustfrei in r und s zerlegbar: q0 = r ./ s enthält 2
überschüssige Tupel:
r
(A
a
a
a’
B)
b
b’
b
s
(B
b
b’
b
C)
c
c’
c’
q0
(A
a
a
a
a’
a’
B
b
b’
b
b
b
C)
c
c’
c’
c’
c
3.2.4.3 Der Gleichverbund (equi-join)
Seien R und S Relationen, R ∩ S = {}. Ai ∈ R, Bi ∈ S, und Dom(Ai ) = Dom(Bi ), 1 ≤ i ≤
n. Der Gleichverbund von r und s über den Attributen A1 , ..., An und B1 , ..., Bn , notiert als
r [ A1 = B1 , ..., An = Bn ] s ist die Relation:
q(RS) = {t | ∃ts ∈ s ∧ ∃tr ∈ r : t(R) = tr , t(S) = ts und t(Ai ) = t(Bi ), 1 ≤ i ≤ n}.
D.h., wir setzen jeweils zwei Attribute aus den Relationen r und s gleich, was natürlich
nur möglich ist, wenn der Wertebereich dieser Attribute übereinstimmt.
Wie beim Kartesischen Produkt müssen auch hier gemeinsame Attribute umbenannt werden, falls R ∩ S 6= {}.
Beispiel 3.14 Wir wollen nun wissen, welche Speisen in welchem Lokal angeboten werden,
wenn wir wieder die Relationen Restaurant und Speise aus Abbildung 3.1 betrachten. Da
zwei Attribute in den beiden Relationen denselben Namen haben, müssen wir zumindest eines
KAPITEL 3. DAS RELATIONENMODELL
3.10
umbenennen. Wir benennen die Attribute der Relation Speise um, indem wir ein 0 an ihre
Namen hängen.
Restaurant [ rnr = rnr0 ] Speise =
rnr
1
1
1
1
2
2
3
3
3
3
..
.
name
Gußhaus
Gußhaus
Gußhaus
Gußhaus
A Tavola
A Tavola
Green Cottage
Green Cottage
Green Cottage
Green Cottage
..
.
6 Toko-Ri
6 Toko-Ri
6 Toko-Ri
adresse haube
Gußhau...
1
Gußhau...
1
Gußhau...
1
Gußhau...
1
Weihbu...
Weihbu...
Ketten...
2
Ketten...
2
Ketten...
2
Ketten...
2
..
..
.
.
Franz-...
Franz-...
Franz-...
typ
öster...
öster...
öster...
öster...
toska...
toska...
chine...
chine...
chine...
chine...
..
.
name0
Gebratener Reh...
Gefüllte Perlh...
Zarte Rotbarb...
Gemischte Käse...
Gemischter Vors...
Penne all’ Arra...
Hühnerfleisch ...
Wolfsbarschfil...
Gebratene Seet...
Eisei im gebac...
..
.
japan... Kleines Sushi
japan... Großes Sushi
japan... Gemischte Mak...
preis0
21
26
25
10
10
9,5
6,5
25
23
6,5
..
.
rnr0
1
1
1
1
2
2
3
3
3
3
..
.
12
15
21
6
6
6
Anmerkung: Die Lesbarkeit obiger Notation leidet, wenn der Gleichverbund zwischen
zwei Kopien der selben Tabelle durchgeführt wird, z.B. wenn wir nach Paaren von Restaurants
suchen, die dieselbe Anzahl an Hauben haben: Restaurant [ haube = haube 0 ] Restaurant.
Es empfiehlt sich hier einen sprechenden Bezeichner (alias) für jede Kopie zu vergeben, z.B.:
Restaurant eins [ haube = haube0 ] Restaurant zwei.
3.2.4.4 Der Theta-Verbund (theta-join)
Seien r(R), s(S) Relationen, wobei R ∩ S = {}. Sei A ∈ R, B ∈ S, und die Elemente aus
Dom(A) seien mit den Elementen aus Dom(B) mittels der Operatoren aus Θ vergleichbar.
Sei θ ∈ Θ. Der Thetaverbund r [ A θ B ] s ist die Relation:
q(RS) = {t | ∃ts ∈ s ∧ ∃tr ∈ r : t(R) = tr , t(S) = ts und tr (A)θts (B)}.
D.h., wir verfahren wie beim Gleichverbund, nur dass ein allgemeiner Operator, der zu
den zu vergleichenden Attributen passt, als Vergleichsoperator verwendet wird. Der Gleichverbund ist also ein Sonderfall des Theta-Verbundes. Falls R∩S 6= {}, müssen wir uns wieder
durch Umbenennen der Attribute weiterhelfen.
Beispiel 3.15 Wenn wir alle Paare von Restaurants auswählen wollen, die sich um mehr als
zwei Hauben unterscheiden, so müssen wir den Theta-Verbund verwenden.
KAPITEL 3. DAS RELATIONENMODELL
3.11
Restaurant eins [ haube + 2 < haube0 ] Restaurant zwei =
rnr
1
5
8
9
name
Gußhaus
San Carlo
Carpaccio
Indian Pa...
adresse haube
Gußhau...
1
Mahler...
0
Panigl...
1
Naschm...
0
typ
rnr0
öster...
7
itali...
7
itali...
7
indi...
7
name0
Steirereck
Steirereck
Steirereck
Steirereck
adresse0
Rasum...
Rasum...
Rasum...
Rasum...
haube0
4
4
4
4
Wir möchten an dieser Stelle kurz darauf hinweisen, dass es einen Unterschied macht, ob
ein Tupel auf einem Attribut den Wert 0“ bzw. den Leerstring annimmt, oder ob nichts ein”
getragen ist. Wenn ein Tupel auf einem Attribut keinen Wert annimmt, so nennen wir das
einen Nullwert. Mit einem Nullwert können wir, wie das Beispiel zeigt, keine numerischen
Vergleiche durchführen, mit dem Wert 0“ hingegen schon (siehe Abschnitt 3.3).
”
3.2.5 Die Division
Seien r(R) und s(S) Relationen mit S ⊆ R. Dann ist die Division von r durch s, r ÷ s, die
Relation
q(R − S) = {t | ∀ts ∈ s : ∃tr ∈ r mit tr (R − S) = t und tr (S) = ts }.
D.h., wollen wir die Relation r durch s dividieren, so muss die Attributmenge von s eine
Teilmenge der Attributmenge von r sein. Das Ergebnis hat die Differenz der Attributmengen
als Attribute und wählt jene Tupel aus r aus, die eingeschränkt auf die Differenz der Attribute
R − S für alle Tupel aus s denselben Wert haben.
Beispiel 3.16 Angenommen, wir wollen wissen, welche Restaurants Speisen zu bestimmten Preisen anbieten, die in einer Relation Preisliste gespeichert sind. Aus der Relation
Speise projizieren wir auf die Attribute preis und rnr. Das Ergebnis dieser Projektion
können wir nun durch die Relation Preisliste dividieren und erhalten das gewünschte Resultat. Wir betrachten einmal die Menge der Preise {6.5, 23, 25}, im zweiten Fall die Menge
{10, 25} und erhalten jene Restaurants, die Speisen zu allen diesen Preisen anbieten.
πpreis,rnr (Speise) ÷ Preisliste A =
rnr
3
4
πpreis,rnr (Speise) ÷ Preisliste B =
typ0
int...
int...
int...
int...
KAPITEL 3. DAS RELATIONENMODELL
3.12
rnr
1
4
wobei die zugrundeliegenden Relationen die folgenden sind:
πpreis,rnr (Speise)
preis rnr
21
1
26
1
25
1
10
1
10
2
9,5
2
6,5
3
25
3
23
3
6,5
3
7
4
25
4
23
4
7
4
6,5
4
10
4
12
6
15
6
21
6
Preisliste A
preis
6,5
23
25
Preisliste B
preis
10
25
Wir möchten darauf hinweisen, dass es wichtig ist, den Namen der Speisen vor dem Ausführen
der Division wegzuprojizieren; andernfalls wäre das Ergebnis in beiden Fällen die leere Menge, da die Namen der Speisen nicht alle gleich sind.
3.2.6 Der Semiverbund (semijoin)
Seien r(R) und s(S) zwei Relationen mit R ∩ S = X 6= {}. Der Semiverbund r n s ist die
Relation:
q(R) = {tr ∈ r | ∃ts (S) mit tr (X) = ts (X)}
Das Ergebnis des Semiverbunds q ist also die Menge aller Tupel von r, die in den Verbund
mit s eintreten können.
Alternativ können wir den Semiverbund als Kombination von Verbund und Projektion wie
folgt darstellen:
KAPITEL 3. DAS RELATIONENMODELL
3.13
r n s = πR (r ./ s)
Dieser Operator wurde zur Optimierung von Joins auf verteilten Datenbanken entwickelt.
Wir werden im Kapitel 9 nochmals darauf zu sprechen kommen.
Beispiel 3.17 Wollen wir alle Restaurants auswählen, zu denen es mindestens eine Speise in
der Relation Speise gibt, so bilden wir den Semijoin zwischen den Relationen Restaurant
und Speise. Das Attribut name in der Relation Speise müssen wir natürlich wieder umbenennen.
Restaurant n Speise
rnr name
adresse
1 Gußhaus
Gußhausstraße 23, 1040 Wien
2 A Tavola
Weihburggasse 3-5, 1010 Wien
3 Green Cottage Kettenbrückengasse 3, 1050 Wien
4 Drei Husaren Weihburggasse 4, 1010 Wien
6 Toko-Ri
Franz-Hochedlinger-Gasse 2, 1020 Wien
haube
1
2
2
typ
österreichisch
toskanisch
chinesisch
österreichisch
japanisch
3.3 Nullwerte
Im Rahmen der Erfassung von Daten kommt es häufig vor, dass unvollständige Information
modelliert werden muss. Es gibt verschiedene Gründe für unvollständige Information. So
kann die Adresse einer Person unbekannt (aber existent) sein, oder es gibt Attribute, die eventuell nicht anwendbar sind, etwa wenn jemand kein Telefon hat.
Um unvollständige Information in einer Datenbank zu speichern, müssen wir einen theoretischen Hintergrund erarbeiten, wie die Datenbank mit sogenannten Nullwerten (null values) umgehen soll. Manche Datenmodelle unterscheiden zwischen verschiedenen Arten von
Nullwerten (z.B. unbekannt“, nicht anwendbar“), um die fehlende Information trotz ihres
”
”
Fehlens näher zu charakterisieren. Die meisten relationalen Datenbankmanagementsysteme
unterstützen nur eine Art von Nullwerten, null.
Ein Tupel t (eine Relation r), das (die) einen oder mehrere Nullwerte enthält, heißt partiell
(partial). Ein Tupel (eine Relation) ohne Nullwerte heißt total, geschrieben t ↓ (r ↓). Ein
Attribut A heißt bestimmt (definite), geschrieben als A ↓, wenn der Wert von A nicht null
ist. Eine Relation r0 ist eine Vervollständigung (completion) der Relation r, wenn r0 keine
Nullwerte mehr enthält und aus r dadurch erhalten wird, dass Nullwerte in r durch Werte aus
dem jeweiligen Wertebereich ersetzt werden.
Beispiel 3.18 Die Relation Restaurant aus Beispiel 3.1, die wir in Abbildung 3.1 dargestellt
haben, ist eine partielle Relation. Ein partielles Tupel ist z.B. das Tupel t(rnr) = 2, da die Anzahl der Hauben des Restaurants A Tavola“ unbekannt ist. Eine mögliche Vervollständigung
”
der Relation wäre:
KAPITEL 3. DAS RELATIONENMODELL
3.14
Restaurant
rnr name
1 Gußhaus
2 A Tavola
3 Green Cottage
4 Drei Husaren
5 San Carlo
6 Toko-Ri
7 Steirereck
8 Carpaccio
9 Indian Pavillion
adresse
Gußhausstraße 23, 1040 Wien
Weihburggasse 3-5, 1010 Wien
Kettenbrückengasse 3, 1050 Wien
Weihburggasse 4, 1010 Wien
Mahlerstraße 3, 1010 Wien
Franz-Hochedlinger-Gasse 2, 1020 Wien
Rasumofskygasse 2, 1030 Wien
Paniglgasse 22, 1040 Wien
Naschmarkt Stand 74-75, 1040 Wien
haube
1
0
2
2
0
1
4
1
0
typ
österreichisch
toskanisch
chinesisch
österreichisch
italienisch
japanisch
international
italienisch
indisch
3.3.1 Auswertung von Nullwerten
Nun ergibt sich natürlich die Frage, wie Abfragen über partiellen Relationen beantwortet werden.
Die um Nullwerte erweiterten Wahrheitstabellen sehen folgendermaßen aus ( w“ = wahr,
”
f“ = falsch):
”
∧
w
f
null
w
w
f
null
f null
f null
f
f
f null
∨
w
f
null
w
f
w
w
w
f
w null
null
w
null
null
¬
w
f
null
f
w
null
Beispiel 3.19 Betrachten wir noch einmal die partielle Relation aus Beispiel 3.1.
Wollen wir wissen, ob es ein Restaurant gibt, das mehr als zwei Hauben und eine internationale Küche hat, so lautet die Antwort ja.
Wollen wir hingegen wissen, ob es Restaurants gibt, die weniger als zwei Hauben und
eine internationale Küche haben, so ist die Antwort nein.
Sind wir aber daran interessiert, ob es ein Restaurant gibt, das mehr als zwei Hauben und
eine japanische Küche hat, so ist die Antwort null.
3.3.2 Äußerer Verbund (outer join)
Bei einem normalen Join werden nur jene Tupel von Relationen r und s verbunden, die in
beiden Relationen auf den gemeinsamen Attributen dieselben Werte annehmen. Beim äußeren
Verbund werden die Tupel, die nicht verbindbar (joinable) sind, mit Nullwerten aufgefüllt und
zum Ergebnis dazugefügt.
Seien r(R) und s(S) zwei Relationen mit R ∩ S = X 6= {}. Sei null(X) definiert als
Tupel über X, bestehend nur aus Nullwerten. Sei q = r ./ s, r 0 = r \ πR (q), s0 = s \ πS (q).
Der äußere Verbund von r und s (outer join of r and s), geschrieben r ∗ s, ist definiert als
KAPITEL 3. DAS RELATIONENMODELL
3.15
r ∗ s = q ∪ (r0 × null(S \ X)) ∪ ( null(R \ X) × s0 ).
Beispiel 3.20 Wir wollen eine Liste aller Restaurants und der von ihnen angebotenen Speisen erstellen. Bei dem Versuch, dieses mittels Gleichverbund zu bewerkstelligen, müssen wir
erkennen, dass jene Restaurants, für die keine Speisen in der Relation Speise vorkommen,
nicht in unserem Ergebnis sind, wie Beispiel 3.14 zeigt. Verwenden wir allerdings den äußeren Verbund, so werden auch Restaurants ohne Speisen in das Ergebnis aufgenommen und die
entsprechenden Stellen mit Nullwerten aufgefüllt. Wie gehabt müssen wir das Attribut name
in der Relation Speise umbenennen, damit es nicht als Joinattribut verwendet wird.
Restaurant ∗ Speise =
rnr
1
1
1
1
2
..
.
6
6
7
8
9
name
Gußhaus
Gußhaus
Gußhaus
Gußhaus
A Tavola
..
.
adresse
Gußhau...
Gußhau...
Gußhau...
Gußhau...
Weihbu...
..
.
Toko-Ri
Toko-Ri
Steirereck
Carpaccio
Indian Pavillion
Franz-...
Franz-...
Rasumo...
Panigl...
Naschm...
..
.
typ
öster...
öster...
öster...
öster...
toska...
..
.
name0
Gebratener Reh...
Gefüllte Perlh...
Zarte Rotbarb...
Gemischte Käse...
Gemischter Vors...
..
.
preis
21
26
25
10
10
..
.
4
1
0
japan...
japan...
inter...
itali...
indisch
Großes Sushi
Gemischte Mak...
null
null
null
15
21
null
null
null
haube
1
1
1
1
Achtung: Der äußere Verbund ist im Gegensatz zum Verbund nicht assoziativ!
Beispiel 3.21 (q ∗ r) ∗ s 6= q ∗ (r ∗ s)
q
(q ∗ r) ∗ s =
B C
2 3
(A
1
1
r
B
C)
2
3
null 4
A
1
B
2
s
A C
1 4
q ∗ (r ∗ s) =
(A B C)
1 2 4
null 2 3
3.4 Übersetzung des ER ins Relationenmodell
Um in praktischen Belangen mit einem Datenmodell zu arbeiten, ist es sinnvoll, mit der Modellierung eines ER zu beginnen. In einem zweiten Schritt müssen wir das ER in das Relationenmodell einbetten. Dies ist immer möglich. Eine genaue Beschreibung dieser Einbettung
3.16
KAPITEL 3. DAS RELATIONENMODELL
wird in dem Artikel [Teorey et al. 1986] gegeben1 . Wir geben hier nur eine kurze Einführung,
die das Lesen des Artikels nicht ersetzt.
Entities und Beziehungen haben keine direkte Entsprechung im Relationenmodell. Alle
Sachverhalte werden einheitlich durch Relationen (Beziehungen zwischen Attributen) dargestellt.
Bei einer 1:1-Beziehung zwischen zwei Entities wird die Beziehung aufgelöst, indem der
Schlüssel der einen Entity in die Relation aufgenommen wird, die der anderen Entity entspricht. Welche Richtung hier verwendet wird, bleibt dem Designer überlassen. Wenn allerdings eine optionale Beziehung besteht, wird der Schlüssel auf der optionalen Seite gespeichert.
Im Falle einer 1:n-Beziehung zwischen zwei Entities schreiben wir den Schlüssel der
Entity auf der Einser“-Seite in die Relation, die der Entity auf der n“-Seite entspricht –
”
”
deswegen ist in unserem laufenden Beispiel das Schlüsselattribut der Entity Restaurant in
die Relation Speise gelangt.
Bei einer n:m-Beziehung zwischen zwei Entities hingegen führen wir eine neue Relation
ein, die die Schlüssel der beiden Entities als Attribute besitzt.
Bei Weak Entities, bei denen die eigenen Attribute nicht ausreichen, um ein Tupel eindeutig zu identifizieren, müssen die Schlüsselattribute der damit verbundenen Entities zum
Schlüssel dazugenommen werden – deswegen ist das Attribut rnr in der Relation Speise
Teil des Schlüssels.
3.5 NF2-Relationen
Eine Erweiterung des relationalen Modells bilden die NF2 -Relationen. NF2 sind Non First
Normal Form Relations (Relational Model with Relation-Valued Attributes), Relationen, die
nicht in erster Normalform sind. Der Begriff Normalform wird in Kapitel 7 definiert. NF 2 Relationen erlauben eine komplexere Kombination der bis jetzt kennengelernten Konzepte:
Attributwerte selbst können wieder Relationen sein. Damit können wir komplexe Objekte
und hierarchische Strukturen leichter darstellen (z.B.: CAD, Büroumgebung, . . . ).
Ein Beispiel dazu finden wir in der Abbildung 3.2 []Schek, Pistor 1982].
3.6 Weitere Sprachen f ür das Relationenmodell
Die relationale Algebra ist eine Abfragesprache für das Relationenmodell. Neben dieser gibt
es noch eine Reihe weiterer Abfragesprachen bzw. DML-Sprachen, von denen wir einige
kurz vorstellen wollen. Der wichtigsten, nämlich SQL, wird das gesamte nächste Kapitel
gewidmet. In Kapitel 5 beschreiben wir eine weitere Spreche, nämlich Datalog.
1
Diese Arbeit wird als Anhang zum Skriptum der Laborübung verteilt. Sie kann aber auch im Sekretariat der
Abteilung kopiert werden.
KAPITEL 3. DAS RELATIONENMODELL
3.17
ABTEILUNG
BÜROANGEST
ANR
BNR
1
2
TECH-ANGEST
ANAME
Forschung
Entwicklung
21
22
30
40
69
19
25
35
B-ARBEIT
Bibliothek
Übersetzer
Sekretär
Patente
Sekretär
Sekretär
Übersetzer
Hilfskraft
TNR
T-ARBEIT
KURSE
KNR
JAHR
51
Programmierer
1
2
5
75
76
79
52
Grundlagenforschung
1
2
82
79
78
Planung
2
4
75
77
50
Entwurf
4
2
75
81
80
Wartung
3
77
Planung
1
2
82
83
81
Abbildung 3.2: NF2 -Relationen nach Schek
Die Abrfragesprachen für das Relationenmodell können einerseits nach ihrer Beschreibungsart, andererseits nach der Art der Resultate in jeweils zwei Klassen eingeteilt werden.
Nach der Beschreibungsart gibt es folgende zwei Klassen:
Prozedurale Sprachen: Diese sind operational: sie stellen eine Beschreibung des Prozesses dar, der die Antwortmenge erzeugt. Die Abarbeitungsreihenfolge ist vorgegeben.
Beispiele dafür sind die DML für das Netzwerkmodell, die DML für das Hierarchische
Modell und die relationale Algebra, die wir zu Beginn dieses Kapitels vorgestellt haben.
Nichtprozedurale Sprachen: Diese sind deskriptiv (oder deklarativ): sie geben eine Beschreibung der Bedingung, die erfüllt sein muss, damit ein Datenelement zur Antwortmenge gehört. Beispiele dafür sind der Relationenkalkül, Datalog und SQL.
Teilen wir die Sprachtypen nach Art der verwendeten Datenstrukturen ein, so erhalten wir
folgende Klassen:
Datensatzorientierte Sprachen: Die Operationen arbeiten auf einzelnen Tupeln bzw. Datensätzen. Werden mehrere Tupel oder Datensätze verarbeitet, so müssen sie explizit
sequentiell abgearbeitet werden. Beispiele dafür sind die DML für das Netzwerkmodell und die DML für das Hierarchische Modell.
Mengenorientierte Sprachen: Die Operationen arbeiten auf Mengen von Tupeln. Alle relationalen Abfragespachen gehören dieser Klasse an (SQL, QUEL, Datalog, ...). Um
mit datensatzorientierten Sprachen auf diesen Mengen arbeiten zu können, gibt es das
Cursor-Konzept, das eine Umsetzung in datensatzorientierte Darstellung bietet (4.2.2).
KAPITEL 3. DAS RELATIONENMODELL
3.18
3.6.1 Der Relationenkalkül
Der Relationenkalkül beruht auf der Prädikatenlogik 1. Stufe (wo nur über Individuenvariable quantifiziert wird, im Gegensatz zur Prädikatenlogik 2. Stufe, wo auch über Prädikate
quantifiziert wird).
Der Wertebereich der Variablen kann einerseits ein Tupel sein, wenn wir vom Relationenkalkül mit Tupelvariablen (tupel relational calculus) sprechen, andererseits Attributwerte,
wenn wir vom Relationenkalkül mit Bereichsvariablen (domain relational calculus) sprechen.
3.6.1.1 Der Relationenkalkül mit Tupelvariablen
Die Ausdrücke des Relationenkalküls mit Tupelvariablen haben die Form {x(R)|f (x)}, wobei x eine Tupelvariable darstellt, R eine Menge von Attributen und f eine Funktion über
der Tupelvariable nach {wahr, falsch} ist. Die Ergebnisrelation r(R) besteht aus allen Tupeln
x(R), für die der Ausdruck f (x) wahr ist.
Beispiel 3.22 Gehen wir wieder von den beiden Relationen Restaurant und Speise aus
Abbildung 3.1 aus. Wenn wir alle Restaurants (Name und Adresse) mit mehr als einer Haube
suchen, so sieht die Abfrage wie folgt aus:
{x(name, adresse) | x ∈ Restaurant ∧ x(haube) > 1}
Beispiel 3.23 Wie heißen die Speisen, die im Restaurant Drei Husaren“ angeboten werden,
”
und was kosten sie?
{x(name, preis) | x ∈ Speise
∧ ∃ y ∈ Restaurant : x(rnr) = y(rnr)
∧ y(name) = 0 Drei Husaren0 }
3.6.1.2 QBE — Query By Example
QBE wurde um 1977 am IBM Watson Research Center entwickelt und basiert auf dem Relationenkalkül mit Bereichsvariablen.
Dem Benutzer werden Tabellengerüste aller relevanten Relationen gezeigt, die aus einer
Kopfzeile mit den Attributen bestehen. Durch Eintragungen in die jeweiligen Attributspalten werden die gewünschten Bedingungen und Ausgabewerte angegeben. Bereichsvariable
werden unterstrichen und müssen aus dem Wertebereich des betreffenden Attributes stammen. Nicht unterstrichene Zeichenketten stellen Konstante dar. Auszugebende Werte werden
durch ein vorgestelltes P. gekennzeichnet. Alle in einer Zeile stehenden Eintragungen werden
miteinander logisch UND-verknüpft, die einzelnen Zeilen werden miteinander logisch ODER
verknüpft.
KAPITEL 3. DAS RELATIONENMODELL
3.19
Beispiel 3.24 Um zu erfahren, welche Speisen es um 21 Euro gibt, brauchen wir ein Schema
der Tabelle Speise. Dort tragen wir an der Stelle preis den gewünschten Preis, nämlich
21 ein. Da uns der Name der Speisen interessiert, schreiben wir ein P. in die Spalte name.
Optional dazu können wir noch eine Variable angeben, die aus dem Wertebereich stammt, bei
uns z.B. Pizza. Unten sehen wir das Eingabeschema mit dem dazugehörigen Ergebnis.
Speise
name
P.Pizza
preis rnr
21
Speise
name
Gebratener Rehrücken mit Serviettenknödel
Gemischte Maki für 2 Personen
Fü die Selektion können in QBE auch Vergleichsoperatoren herangezogen werden. Dabei
werden Vergleichsoperatoren als Präfix von Konstanten oder Variablen verwendet.
Beispiel 3.25 Wir wollen wieder die Namen aller Restaurants auswählen, die mehr als drei
Haube haben.
Restaurant
rnr
name
P.
adresse
haube
>3
typ
Restaurant
name
Steirereck
Verwenden wir mehrere Zeilen im Eingabeschema, so werden diese miteinander ODERverknüpft; eine UND-Verknüpfung zwischen Zeilen wird durch die Verwendung derselben
Variablen erreicht.
Beispiel 3.26 Welches sind die Nummern der Restaurants, die Speisen um 25 Euro und 26
Euro abbieten, oder die Speisen anbieten, die weniger als 7 Euro kosten.
Speise
name
preis
25
26
<7
rnr
P. 99
P. 99
P. 77
Speise
rnr
1
3
4
Durch die Verwendung derselben Variablen werden auch Beziehungen zwischen Tupel
in verschiedenen Relationen ausgedrückt. Wir benötigen in diesem Fall mehrere Relationenschemata und müssen, falls notwendig, auch ein Ergebnisschema mit einem neuen Namen
vorgeben.
Beispiel 3.27 Sind wir daran interessiert zu sehen, welche Speisen in welchem Restaurant
angeboten werden, so müssen wir neben den beiden Relationenschemata für die Abfrage auch
ein Ergebnisschema Speise in Restaurant anlegen:
Speise
name
xx
preis
rnr
99
Restaurant
Speise in Restaurant
P.
name
xx
rnr name
99 yy
name
yy
adresse
zz
adresse
zz
haube
typ
KAPITEL 3. DAS RELATIONENMODELL
3.20
Damit alle Tupel ausgegeben werden, die diesem Schema angehören, schreiben wir das P.
in die Spalte unter den Schemanamen. Eine äquivalente Lösung ist, das P. zu den Variablen
xx, yy und zz zu schreiben.
Zuletzt können in einer condition box“ Beziehungen zwischen Bereichsvariablen spezi”
fiziert werden.
Beispiel 3.28 Wir wollen alle Restaurants ausgeben, die entweder mehr als eine Haube haben,
oder österreichisch sind, wobei Doppelnennungen nicht vorkommen sollen.
Restaurant
rnr
name
P. xx
P. yy
adresse
haube
>1
typ
österreichisch
CONDITION
xx 6= yy
KAPITEL 3. DAS RELATIONENMODELL
3.21
3.7 Übungsbeispiele
Übung 3.1 Gegeben sind folgende Relationen:
kh
bez
beschäftigt
arzt
(KH#, KH NAME, KH ADRESSE, ANZ BETTEN)
(KH#, BEZIRK)
(KH#, ARZT#)
(ARZT#, NAME, GEHALT, SG)
Anmerkung:
• SG . . . Spezialgebiet
• KH . . . Krankenhaus
1. Formulieren Sie in relationaler Algebra:
In welchen Bezirken gibt es Ärzte, die mehr als 20.000,- Euro verdienen?
2. Formulieren Sie in relationaler Algebra:
In welchen Bezirken gibt es Krankenhäuser mit mehr als 500 Betten und keinem Herzspezialisten?
Übung 3.2 Gegeben sind folgende Relationen:
fliegt (Pilot
Richter
Richter
Richter
Truman
Truman
Pires
Pires
Pires
Pires
Novak
wohnt (Pilot
Novak
Richter
Pires
Maschine)
707
727
747
707
727
707
727
747
1011
727
Ort)
Wien
Frankfurt
Lissabon
q
s (Maschine)
707
landet (Maschine
727
727
707
Geben Sie die Relationen folgender Abfragen (relationale Algebra) an:
1. fliegt ÷q
sowie
fliegt ÷s
(÷ bedeutet Division)
(Maschine)
707
727
747
Ort)
Wien
Frankfurt
Frankfurt
KAPITEL 3. DAS RELATIONENMODELL
3.22
2. πP ilot (fliegt) - πP ilot ( (πP ilot (fliegt) × q) − fliegt)
3. fliegt ./ wohnt ./ landet.
Übung 3.3 Gegeben sind die folgenden Relationen:
ölfeld(FELDNAME,QUELLENNAME)
(∗ Quellen liegen in Feldern ∗)
ölmulti(FIRMENNAME,UMSATZ,HL)
(∗ HL steht für Herkunftsland ∗)
besitzt(FIRMENNAME,QUELLENNAME) (∗ Quelle gehört Firma ∗)
Formulieren Sie in Relationer Algebra: Gesucht sind Quellennamen, Firmennamen und
Umsatz aller Ölmultis, die in jedem Ölfeld mindestens eine Quelle besitzen.
Übung 3.4 Gegeben sind folgende Relationen:
univers (UNINAME, STADT)
angebot (UNINAME, STR, SEIT)
Anmerkung:
STR . . . Studienrichtung
SEIT . . . Jahr der Einführung der Studienrichtung
Formulieren Sie in Relationenalgebra: In welchen Städten wurden 1979 Studienrichtungen neu eingeführt?
Formulieren Sie in Relationenalgebra: In welchen Städten kann man Informatik nicht
studieren?
Übung 3.5 Gegeben sind folgende Relationen zur Informationsspeicherung von Wasserleitungen zwischen Bassins (= Wasserbehältern):
Bassin(NR, BEZ, VOL)
Rohr(VON, ZU, DURCHFLUSS).
Bassins haben ein bestimmtes Fassungsvermögen (VOL), eine Bezeichnung (BEZ) und werden durch ihre Nummer (NR) identifiziert. Rohre führen von (VON) einem Bassin zu (ZU)
einem Bassin und sind dadurch eindeutig bestimmt. Bassins, zu denen keine Rohre hinführen
(bzw. wegführen), sind Quellen (bzw. Senken). Jedes Rohr besitzt eine bestimmte Durchflusskapazität (DURCHFLUSS).
Formulieren Sie eine Abfrage in relationaler Algebra, die alle Rohre (von, zu) liefert, die
von einer Quelle wegführen.
Formulieren Sie eine Abfrage in relationaler Algebra, die die Bezeichnung aller Bassins
liefert, zu denen Rohre hinführen, deren Durchfluss > 100 ist.
KAPITEL 3. DAS RELATIONENMODELL
3.23
Übung 3.6 Eine Sportler-Agentur hält in einer Datenbank Informationen über SportlerInnen,
die unter Vertrag stehen (mitglied), sowie Informationen über relevante LeichtathletikVeranstaltungen (veranstaltung) fest. Für statistische Zwecke sowie für künftige Vertragsverhandlungen wird zusätzlich festgehalten welche Mitglieder an welchen Veranstaltungen teilgenommen und welchen Rang sie dabei belegt haben (nimmt teil). Die Höhe der
Preisgelder, die bei den verschiedenen Veranstaltungen ausbezahlt werden, wird ebenfalls
festgehalten (preisgeld).
mitglied(MNAME, ALTER)
veranstaltung(VBEZ, VJAHR, ORT)
nimmt teil(MNAME, VBEZ, VJAHR, DISZIPLIN, RANG).
preisgeld(VBEZ, RANG, BETRAG).
Formulieren Sie in relationaler Algebra: In welchen Orten haben alle SportlerInnen, die
bei unserer Sportleragentur unter Vertrag stehen, zugleich an einer Veranstaltung teilgenommen?
Übung 3.7 Die Relation teilStueck(von-km,nach-km,steigung, zustand) beschreibt Autobahnteilstücke, wobei zustand die Werte 3 (schadhaft), 2 (unbeschädigt) oder
1 (neu) annehmen kann. steigung wird in % angegeben und ist < 0 für abfallende Teilstücke,
sonst > 0. Die Relation bruecke(von-km,bauart) kennzeichnet alle jene Teilstücke,
die Brücken sind. Ein Brückenteilstück hat immer die Steigung 0. Es kann davon ausgegangen werden, dass zwei oder mehrere Brücken nicht unmittelbar hintereinander auftreten.
Formulieren Sie in relationaler Algebra: Welche Brücken (von-km) sind Teil eines Gefälles
(vor und nach der Brücke steigung < 0)?
Übung 3.8 Über Tennisspieler (SPNR) wird vermerkt, für welches Team (TNR) sie in welchen Tennismatches (MNr) gespielt haben. Jedes Team spielt in einer bestimmten Division
(DIVISION) und wird von einem Spieler, dem Kapitän, angeführt. Die Spieler können für
beliebige Teams Matches bestreiten. Zu einem Match werden pro Spieler die gewonnenen
(G SETS) und die verlorenen Sätze (V SETS) angegeben. Lösen Sie anhand folgender vorgegebener Relationen die nachstehenden Aufgabe:
spieler(SPNR NAME ATP-RANG)
team(TNR SPNR DIVISION)
match(MNR SPNR TNR G SETS V SETS)
Gesucht sind die Namen jener Spieler, welche bereits für alle Teams gespielt haben.
Übung 3.9 Gegeben sei die folgende relationale Datenbank über den Einsatz von Flugzeugen
im internationalen Luftverkehr.
3.24
KAPITEL 3. DAS RELATIONENMODELL
flughafen(name,stadt,land)
modell(typ nr,#platz,spannweite,hersteller)
maschine(f nr,fluglinie,wartung,ankauf,typ nr)
flug(f nr,fluglinie,wtag,von,nach)
In flughafen wird der Name des Flughafens, die Stadt, zu der er gehört, sowie das
Land, in dem er liegt, gespeichert. In modell wird zu jedem Flugzeugtyp (z.B. DC10) angegeben, wieviele Sitzplätze, welche Spannweite, und von welchem Hersteller der Flieger
gebaut wurde. In maschine wird zu jedem Flugzeug, das eine Fluggesellschaft kauft, angegeben in welchem Jahr die Maschine das letzte mal gewartet wurde, wann sie angekauft
wurde und von welchem Typ sie ist. In flug wird zu jedem Flugzeug gespeichert, an welchem Wochentag der Flug von Flughafen von nach Flughafen nach fliegt.
Schreiben Sie eine Abfrage in relationaler Algebra, die alle Länder ausgibt, in denen keine
Maschine landet, die mehr als 250 Passagiere aufnehmen kann.
Übung 3.10 Gegeben sei die folgende relationale Datenbank der Tiergartenverwaltung Schönbrunn.
käfig(k nr,fläche,typ)
weg(k nr1,k nr2,dist)
tierart(art,gattung,platz,futter)
tier(name,art,k nr,geb dat,erwerb)
In der Relation käfig wird zu jedem Käfig eine eindeutige Nummer, seine Gesamtfläche
(fläche), sowie seine Beschaffenheit (typ: Terrarium, Aquarium, Gehege etc.) gespeichert. Achtung: es müssen nicht notwendigerweise alle Käfige belegt sein.
In Relation weg wird der Weg zwischen 2 angrenzenden Käfigen gespeichert, zusammen
mit der Entfernung. Die Relation ist symmetrisch, d.h., sowohl Tupel weg(A,B,N), als auch
weg(B,A,N) sind gespeichert.
Die Relation tierart beschreibt die Arten, die im Zoo gehalten werden durch Gattung, Platzbedarf und Futterart z.B. (panther,raubkatze,15m2,fleisch), die Relation tier hingegen beschreibt die einzelnen, im Zoo vorhandenen Exemplare durch ihren
Namen name, der Art art, der sie angehören, den Käfig k nr, in dem sie sich aufhalten, und
dem Geburts- und Erwerbsdatum (geb dat, erwerb). Wurde das Tier im Zoo geboren,
so sind beide Daten gleich.
Schreiben Sie eine Abfrage in relationaler Algebra, die jene Tierarten angibt, von denen
alle vorhanden Exemplare nach dem 1.1.1996 geboren worden sind.
Übung 3.11 Eine Firma für Tiefkühlprodukte speichert die folgenden Daten zur Herstellung
der Speisen in einer relationalen Datenbank:
speise(sname,haltbar,vpreis)
zutat(zname,preis)
rezept(sname,zname,#einheit)
KAPITEL 3. DAS RELATIONENMODELL
3.25
In der Relation speise werden der Name (sname), die Haltbarkeitsdauer (haltbar)
und der Verkaufspreis (vpreis) des jeweiligen Tiefkühlprodukts gespeichert. Die Relation
zutat enthält die Information, wieviel (preis) eine bestimmte Zutat (zname) pro Einheit
kostet. Die Relation rezept beschreibt, wieviel Einheiten (#einheit) von einer bestimmten Zutat in einer Speise verwendet werden.
Schreiben Sie eine Abfrage in relationaler Algebra, die Name und Kategorie der Speisen
angibt, in denen alle Zutaten, die mehr als 20 Euro pro Einheit kosten, verwendet werden.
Übung 3.12 In einer relationalen Datenbank der FIS werden die Resultate der vergangenen
Schiweltcupsaison gespeichert:
sfahr(sname,
rennen(rname,
gefahren(sname,
punkte(platz,
geb dat, geschlecht, land)
typ, länge, land, geschlecht)
rname, typ, dg, zeit, platz)
punkte)
Ein/e FahrerIn wird identifiziert mit dem Namen, beschrieben durch Geburtsdatum, Geschlecht und Herkunftsland. Ein Rennen identifiziert sich durch den Namen und Typ (z.B.
Wengen, Slalom), und wird beschrieben durch die Länge der Strecke, dem Land und für welches Geschlecht das Rennen ausgetragen wurde. Die Tabelle gefahren speichert zu jedem
Rennen und den darin angetretenen FahrerInnen die Zeit und die erreichte Plazierung. Für
Rennen, die nur aus einem Durchgang bestehen, steht im Attribut dg der Wert ‘‘G’’, ansonsten ‘‘1’’, ‘‘2’’ und ‘‘S’’ für die Gesamtwertung. Im Falle eines Ausscheidens
steht in platz NULL. Die Relation Punkte speichert die Anzahl der Punkte, die für eine
bestimmte Plazierung vergeben werden.
Schreiben Sie eine Abfrage in relationaler Algebra, die Name, Geburtsdatum und Nationalität jener FahrerInnen ausgibt, die in dieser Saison an allen Rennen (ihres Geschlechts)
teilgenommen haben.
Übung 3.13 In einer relationalen Datenbank der Wiener Fremdenverkehrsverwaltung werden
die Buchungen der Wiener Hotels gespeichert.
hotel(hname, hadresse, kategorie, betten)
zimmer(hname, znr, betten, preis )
belegt(hname, znr, anreise, abreise)
Ein Hotel wird identifiziert durch den Namen und beschrieben durch die Adresse, die
Kategorie und die Anzahl der vorhandenen Betten. Ein Zimmer identifiziert sich durch den
Namen des Hotels und die entsprechende Zimmernummer, und wird beschrieben durch die
Anzahl seiner Betten und den Preis pro Nacht und Person für dieses Zimmer. Die Relation
belegt speichert zu jedem Zimmer die An- und Abreisetermine der Gäste.
Schreiben Sie eine Abfrage in relationaler Algebra, die Name, Adresse und Kategorie aller
Hotels angibt, die vom 19. - 26. Juni 1999 noch mindestens ein freies Doppelzimmer haben.
3.26
KAPITEL 3. DAS RELATIONENMODELL
Übung 3.14 In einer relationalen Datenbank eines Bankinstituts werden unter anderem Informationen über Kundinnen und deren Sparbücher gespeichert:
kunde(Knr, name, geb dat, beruf, adresse)
sparbuch(Spnr, Knr, gebunden, von, bis)
buchung(Spnr, Bnr, datum, betrag)
Eine Kundin wird identifiziert durch eine Kundennummer (Knr) und beschrieben durch
Name, Geburtsdatum, Beruf und ihre Adresse. Ein Sparbuch wird identifiziert durch die Sparbuchnummer (Sbnr), weiters wird die dazugehörige Kundin, die Dauer der Bindung in Monaten, und das Datum der Sparbucheröffnung (von) und der Schließung (bis) gespeichert.
Ist ein Sparbuch noch offen, so ist der Wert von bis NULL. Eine Buchung ist pro Sparbuch
durchnumeriert (Bnr), weiters werden noch das Datum und der Betrag (positiv oder negativ)
gespeichert.
Schreiben Sie eine Abfrage in relationaler Algebra, die Name und Adresse aller Kundinnen angibt, die mehr als drei laufende Sparbücher haben, aber nur eines, das länger als ein
Jahr gebunden ist.
Kapitel 4
SQL
Die relationale Abfragesprache SQL wurde 1974 für das experimentelle Datenbankmanagementsystem System R von IBM entwickelt – SQL wurde damals SEQUEL (Structured English QUEry Language) genannt – und 1986 von ANSI (American National Standards Institute) und 1987 von ISO (International Standard Organisation) als internationaler Standard einer
Sprachschnittstelle für relationale Datenbankmanagementsysteme genormt. Nach einer ersten
Überarbeitung im Jahr 1989, wo die Sprache erweitert wurde, um referenzielle Integrität und
generelle Integritätsbedingungen zu verarbeiten, wurden 1992 in der zweiten Überarbeitung
die Datenmanipulation, Schemamanipulation und Datendefinitionssprache erweitert. Diese
zweite Version des Standards war in den letzten Jahren die Referenz und wird als SQL-2 oder
SQL-92 bezeichnet. SQL-2 ist relational vollständig, d.h., alles, was im Relationenkalkül ausdrückbar ist, kann auch in SQL ausgedrückt werden. Ab 1992 wurde an einer dritten, großen
Überarbeitung des Standards gearbeitet, um objekt-orientierte Konzepte, persistente Objekte,
Multimedia-Datentypen und temporale Datentypen und Sprachkonzepte zu inkorporieren und
SQL zu einer Turing-vollständigen Sprache (alle berechenbaren Abfragen sind möglich) zu
erweitern. Die in diesem Kapitel vorgestellten Sprachkonzepte von SQL orientieren sich am
SQL-3 Standard, der zu Beginn des Jahres 2000 veröffentlicht wurde.
Wir beginnen in diesem Kapitel mit der Beschreibung der Datendefinitionssprache (Data
Definition Language – DDL) und der Datenmanipulationssprache (Data Manipulation Language – DML) und kennzeichnen reine SQL-3 Konstrukte als solche. SQL kann interaktiv
verwendet werden oder in eine Wirtsprache (host language), wie C oder C++, eingebettet
werden (embedded SQL). In diesem Kapitel wird zuerst interaktives SQL vorgestellt, in Abschnitt 4.2 kurz auf die wichtigsten Konzepte von eingebettetem SQL eingegangen. Einen
Überblick über den SQL-3 Standard geben wir in Abschnitt 4.3 dieses Kapitels.
Die Präsentation von SQL beschränkt sich auf die wichtigsten Konzepte und erfolgt an
Hand von Beispielen, die es ermöglichen sollen, mit Hilfe des SQL-Manuals eines relationalen Datenbankmanagementsystems die Sprache im Detail zu erlernen. Lehrbücher zu
SQL, [Date et al. 1994] und [Melton et al. 1994], umfassen mehrere hundert Seiten, wobei
in diesen Büchern noch der SQL-2 Standard beschrieben wird, mit einem Ausblick auf den
1
KAPITEL 4. SQL
4.2
bei ihrem Erscheinen noch nicht beendeten SQL-3 Standard. Der SQL-3 Standard wird in
[Fortier 1999] beschrieben, wobei der Autor dieses Buches Chairman des SQL-3 Standards
Committee war und jahrelang an der Entwicklung des Standards aktiv teilnahm.
4.1 Interaktives SQL
4.1.1 Allgemeines
Mit SQL können Relationen und Views (virtuelle Relationen) definiert, abgefragt und manipuliert werden. In SQL werden Relationen als Tabellen (tables), Attribute als Spalten (columns)
und Tupel als Zeilen (rows) bezeichnet. Die SQL DDL stellt Befehle zum Erzeugen und Entfernen von Relationen sowie für die Änderung des Schemas einer Relation zur Verfügung.
Die SQL DML stellt Befehle zum Abfragen, Einfügen, Ändern und Löschen von Tupeln
in Relationen zur Verfügung. Wir besprechen zunächst einige ausgewählte Datentypen von
SQL, dann SQL-Abfragen aus der Datenmanipulationssprache, die Datendefinitionssprache
und zuletzt die restlichen Befehle der Datenmanipulationssprache.
4.1.2 Datentypen
SQL unterstützt unter anderem die folgenden Datentypen:
• CHAR(n) Zeichenkette der Länge n.
• CHAR VARYING(n) oder VARCHAR(n) Zeichenkette variabler Länge, die kleiner oder gleich
n ist. Die maximale Länge von n ist implementierungsabhängig, meist 255. Wollen wir
einen String der Länge 5 in eine Spalte schreiben, die einmal mit CHAR(10), ein zweites mal mit VARCHAR(10) definiert wurde, so wird dieser String im ersten Fall mit 5
Leerzeichen aufgefüllt, im zweiten Fall nicht.
• BIT(n) bzw. BIT VARYING(n) Bitstrings der fixen bzw. variablen Länge n.
• INTEGER und SMALLINT Integerzahlen, wobei im zweiten Fall vom System eine Optimierung durchgeführt und weniger Platz reserviert werden kann. Die genaue Größe der
Zahl ist implementierungsabhängig.
• NUMERIC(p, s) Fixkommazahl, wobei mit p die Gesamtanzahl der Stellen, mit s die
Anzahl der Nachkommastellen angegeben werden kann. Die Darstellung von Fixkommazahlen sieht wie folgt aus: 2.345, 3999.1 oder 87.52436.
• REAL und DOUBLE PRECISION Gleitkommazahlen, wobei die Anzahl der Stellen implementierungsabhängig ist, im zweiten Fall aber üblicherweise größer als im ersten.
Die Darstellung von Gleitkommazahlen sieht wie folgt aus: 0.2345E0, 0.39991E-4,
0.8752436E2.
KAPITEL 4. SQL
4.3
• DATE, TIME(p) und TIMESTAMP DATE ist zehnstellig, 4 Stellen für Jahreszahlen (00019999), zwei für Monats- und zwei für die Tagesangabe. TIME(p) speichert Uhrzeiten.
Es stellt zwei Stellen für die Stunde (00-23) und zwei für die Minuten (00-59) zur
Verfügung. Für die Sekunden steht der Bereich 00-61.999... 1 zur Verfügung; die Anzahl
der Nachkommastellen können wir im Parameter p festlegen, die maximale Größe von
p ist implementierungsabhängig, der Defaultwert 0. TIMESTAMP ist eine Kombination
aus DATE und TIME, der Defaultwert für die Nachkommastellen der Sekunden ist 6.
Auf Zeichenketten, Zahlen und Datumsangaben sind u.a. die Vergleichsoperatoren =, <,
>, =<, >=, <> bzw. != mit der üblichen Bedeutung definiert. Bei Zeichenketten gibt es
auch den Vergleichsoperator LIKE, der einen Mustervergleich durchführt. Auf Zahlen können
die arithmetischen Operatoren +, −, ∗, / mit der üblichen Semantik angewandt werden, auch
Klammerungen mittels (“ und )“ sind möglich.
”
”
Aus den vorgestellten Datentypen können mit dem Befehl CREATE DOMAIN domainName
”
AS Typ“ neue Datentypen definiert werden.
Beispiel 4.1 Wir wollen für alle Geldbeträge wie Preise, Gehälter oder Rechnungssummen
Beträge mit zwei Nachkommastellen, für Speisen und Restaurants Namen mit maximal 50
Zeichen zulassen; für Namen von Personen erlauben wir maximal 20 Zeichen.
CREATE DOMAIN euro AS NUMBER(10,2);
CREATE DOMAIN lang_name AS VARCHAR(50);
CREATE DOMAIN name AS VARCHAR(20);
SQL-3 erweitert SQL-2 um einige Datentypen.
• BOOLEAN nimmt die Werte TRUE oder FALSE an. Diese können mit logischen Operatoren
verknüpft werden.
• LARGE BINARY OBJECT (BLOB) und analog dazu LARGE CHARACTER OBJECT (CLOB) sind
große Objekte, die entweder nur aus Binärzeichen oder aus characters bestehen. Für
diese gibt es spezielle Zugriffsstrukturen, die eine effiziente Verarbeitung ermöglichen.
Auf BLOBs und CLOBs können die Vergleichsoperatoren =, ! = und LIKE angewandt
werden, der <-Operator nicht. Sie können nicht als Primärschlüssel verwendet werden
und nicht in einer GROUP BY oder ORDER BY Klausel auftreten.
• ROW ( Zeile“) ist vom Konzept her völlig neu, da wir hiermit komplexe Attribute dar”
stellen können: ROW(attributeDefinitionList)“.
”
• Abstrakte Datentypen sind ein weiteres völlig neues Konzept in SQL-3 und stellen eine Verbindung zwischen dem relationalen und dem objektorientierten Datenmodell dar.
Wir werden am Ende dieses Abschnittes genauer auf abstrakte Datentypen eingehen.
1
Dass der Bereich der Sekunden nicht nur bis 59 geht, liegt an den Schaltsekunden.
KAPITEL 4. SQL
4.4
• Sub- und Supertabellen ermöglichen es, die Generalisierung nicht durch Auflösung in
Relationen wie in [Teorey et al. 1986] beschrieben zu realisieren, sondern explizit Subtabellen anzulegen. Subtabellen erben alle Attribute der Supertabellen. Jeder Eintrag
einer Subtabelle hat genau einen entsprechenden Eintrag in der Supertabelle, zu jedem Eintrag in einer Supertabelle gibt es maximal einen entsprechenden Eintrag in der
Subtabelle. Subtabellen werden mit dem Befehl CREATE TABLE relationName UNDER
”
relationName“ angelegt.
Beispiel 4.2 Bei den Kreditkartendaten eines Kunden wollen wir auch die Unterschrift des
Kunden speichern. Diese legen wir in einem BLOB ab.
Die Adresse der Kunden ist ein typisches Beispiel für einen ROW-Typ.
CREATE TABLE kunde (vorname
nachname
sig
....
adresse
name,
name,
BLOB,
ROW (strasse
ort
plz
land
VARCHAR(30),
VARCHAR(30),
INTEGER,
VARCHAR(30)));
Wir können entweder bei der Tabellendefinition direkt den Typ ROW verwenden oder eine
neue Domain definieren, da wir Adressen vermutlich auch in anderen Tabellen benötigen
werden.
CREATE DOMAIN adresse AS ROW (strasse
ort
plz
land
VARCHAR(30),
VARCHAR(30),
INTEGER,
VARCHAR(30));
Die Modellierung der Kunden und der Mitarbeiter aus Beispiel 2.6 wird mittels Generalisierung dargestellt.
CREATE TABLE kunden UNDER person;
CREATE TABLE mitarbeiter UNDER person;
4.1.3 Abfragen
In diesem Abschnitt besprechen wir zunächst das Prinzip von SQL-Abfragen. Anschließend
behandeln wir die Gruppenbildung von Tupeln und Aggregatfunktionen, danach betrachten wir die Möglichkeit, komplexere Abfragen durch Schachtelung von Abfragen zu bilden.
Schließlich besprechen wir Mengenoperationen und Nullwerte.
KAPITEL 4. SQL
4.5
4.1.3.1 Grundkonstruktion einer SQL-Abfrage
Die Grundkonstruktion einer SQL-Abfrage ist von der Form
SELECT attributeList FROM relations WHERE condition“ .
”
Eine solche SQL-Abfrage wird ausgewertet, indem zunächst das kartesische Produkt der
in der FROM-Klausel angegebenen Relationen gebildet wird. Daraus werden dann jene Tupel
ausgewählt, die die in der WHERE-Klausel angegeben Bedingungen erfüllen. Zuletzt wird auf
die in der SELECT-Klausel angegebenen Attribute dieser Tupel projiziert.
Die Bedingung in der SELECT-Klausel kann sich aus mehreren, durch die logischen Operatoren AND, OR und NOT verbundenen Teilbedingungen zusammensetzen. Als Teilbedingungen
sind Vergleiche zwischen Attributwerten bzw. zwischen Attributwerten und Konstanten mittels der auf den betreffenden Datentyp anwendbaren Vergleichsoperatoren zugelassen, bzw.
durch AND, OR und NOT verbundene Teilbedingungen. Weitere Arten von Teilbedingungen
lernen wir später kennen.
In SQL werden Duplikate, d.h. Ergebnistupel mit identischen Werten, nicht automatisch
eliminiert. Um Duplikate zu eliminieren, muss der Liste von ausgewählten Attributen das
Schlüsselwort DISTINCT vorangestellt werden. Durch die Angabe einer ORDER BY-Klausel
mit den Schlüsselworten ASC oder DESC kann die Ausgabe aufsteigend bzw. absteigend nach
bestimmten Attributen sortiert werden; der Defaultwert ist ASC.
Die folgenden Beispiele, anhand derer wir Syntax und Semantik von SQL beschreiben,
verwenden wieder die in Beispiel 3.1 beschriebenen Relationenschemata und die in Abbildung 3.1 dargestellten Relationen:
Restaurant = {rnr, name, adresse, haube, typ}
Speise = {name, preis, rnr}
Weiters verwenden wir zur Beschreibung der Operationen, soweit möglich, dieselben Abfragen wie in der Relationalen Algebra.
Die Selektion Die Selektion wird durch die Angabe der Bedingungen in der condition realisiert. Bei den Bedingungen können beliebige Vergleichsoperatoren (die für den Datentyp
definiert sind) verwendet werden.
Beispiel 4.3 Wir selektieren alle jene Restaurants, die zwei Hauben haben.
SELECT rnr, name, adresse, haube, typ
FROM restaurant
WHERE haube = 2;
Wir selektieren alle jene Restaurants, die mehr als eine Haube, aber keine österreichische oder
internationale Küche haben.
4.6
KAPITEL 4. SQL
SELECT rnr, name, adresse, haube, typ
FROM restaurant
WHERE haube > 1 AND NOT
(typ = österreichisch OR
typ = international);
Die Projektion Die Projektion wird durch Angabe der gewünschten Attribute in der attributeList realisiert.
Beispiel 4.4 Wir projizieren die Relation Restaurant nach den Attributen name, adresse
und haube.
SELECT name, adresse, haube
FROM restaurant;
Wenn kein Attribut wegprojiziert werden soll, so können wir anstelle der Aufzählung aller
Attribute des Schemas *“ als Platzhalter verwenden.
”
Der Verbund Um mehrere Relationen im Verbund zu verknüpfen, schreiben wir die Namen
der Relationen in die FROM-Klausel. Dadurch wird das kartesische Produkt zwischen den
Relationen gebildet. Wenn wir einen Gleichverbund oder Theta-Verbund durchführen wollen,
so erreichen wir dies durch Selektion der gewünschten Tupel aus dem Kartesischen Produkt.
Gibt es in den Relationen Attribute mit derselben Bezeichnung, so müssen wir bei diesen
Attributen auch den Namen der Relation angeben, aus der sie genommen werden.
Beispiel 4.5 Wir wollen wissen, welche Speisen in welchem Restaurant angeboten werden.
SELECT restaurant.*, speise.*
FROM restaurant, speise
WHERE restaurant.rnr = speise.rnr;
Werden in einer Abfrage zwei Kopien derselben Relation benötigt oder sollen Relationen
durch kürzere Namen angesprochen werden, so können in der FROM-Klausel Aliasbezeichner
vergeben werden.
In der SELECT-Klausel können auch Ausdrücke, die aus Attributen berechnet werden, stehen. Durch das Schlüsselwort AS kann einem so berechneten Ausdruck ein Attributname
zugewiesen werden.
Beispiel 4.6 Wir wollen alle Paare von Restaurants auswählen, die sich um mehr als zwei
Hauben unterscheiden und die Differenz der Hauben ausgeben. Weiters sind wir nur an den
Namen der Restaurants interessiert.
SELECT r1.name, r2.name, (r2.haube - r1.haube) AS differenz
FROM restaurant r1, restaurant r2
WHERE r1.haube + 2 < r2.haube;
KAPITEL 4. SQL
4.7
Die Division Es gibt keinen, der Division direkt entsprechenden Operator in SQL. Allerdings kann die Division mit Hilfe der Negation und von Teilabfragen dargestellt werden.
4.1.3.2 Mengenoperationen
SQL stellt die Mengenoperationen UNION (Mengenvereinigung), UNION ALL (Multimengenvereinigung, d.h. gleiche Tupel werden nicht eliminiert), INTERSECT (Durchschnitt) und EXCEPT
(Mengendifferenz) für typkompatible Relationen (d.h. Relationen mit der gleichen Anzahl von
jeweils typkompatiblen Attributen) zur Verfügung.
Beispiel 4.7 Wir wollen eine Liste der Namen aller Restaurants und der Namen aller Speisen.
(SELECT name FROM restaurant) UNION
(SELECT name FROM speise)
Mit typkompatiblen Relationen“ sind dabei natürlich nicht die Relationen Restaurant
”
oder Speise gemeint, sondern die Ergebnisse der beiden SELECT Statements.
4.1.3.3 Gruppierung und Aggregatfunktionen
Der bereits bekannte SELECT − FROM − WHERE“-Block kann um eine Klausel GROUP BY at”
”
tributeList“ und eine Klausel HAVING condition“ ergänzt werden, um Gruppen von Tupeln
”
zu bilden und auf diese Gruppen Aggregatfunktionen anzuwenden. Eine solche Abfrage
wird ausgewertet, indem zunächst wie gehabt aus dem kartesischen Produkt der in der FROMKlausel angegebenen Relationen jene Tupel selektiert werden, die die WHERE-Klausel erfüllen.
Danach werden diese Tupel nach gemeinsamen Werten in den in der GROUP BY-Klausel angeführten Attributen gruppiert. Von diesen Gruppen werden jene eliminiert, die die in der
HAVING-Klausel angegebene Bedingung nicht erfüllen. Anschließend werden etwaige in der
SELECT-Klausel angegebenen Aggregatfunktionen wie AVG, SUM, MAX, MIN und COUNT auf
jede der verbliebenen Gruppen angewendet. Diese Aggregatfunktionen (außer COUNT) können
auch auf arithmetische Ausdrücke über Attributen angewandt werden. COUNT wird über Booleschen Ausdrücken ausgewertet und zählt jene Tupel, die den jeweiligen Booleschen Ausdruck erfüllen. Der Ausdruck COUNT(∗) zählt alle Tupel.
In der SELECT-Klausel und in der HAVING-Klausel dürfen jene Attribute, nach denen
gruppiert wurde, nur ohne Aggregatfunktion verwendet werden – nach jenen Attributen, die in der SELECT-Klausel ohne Aggregatfunktionen selektiert werden, muss gruppiert werden. (Zum besseren Verständnis dieser Konstrukte überlegen Sie sich, warum dies
so ist.)
Beispiel 4.8 Schreiben wir eine SQL-Abfrage, die den Namen und die Anzahl der Hauben
jener Restaurants angibt, deren teuerste Speise mehr als 22 Euro kostet. Weiters werden
jeweils die Anzahl der Speisen als auch deren Durchschnittspreis ausgegeben.
4.8
KAPITEL 4. SQL
SELECT r.rnr, r.haube, count(*), avg(s.preis)
FROM restaurant r, speise s
WHERE r.rnr=s.rnr
GROUP BY r.rnr, r.haube
HAVING MAX(s.preis) > 22;
Fehlen die GROUP BY und HAVING-Klauseln, so müssen in der SELECT-Klausel entweder
auf alle Attribute oder auf kein einziges Attribut Aggregatfunktionen angewendet werden.
Werden Aggregatfunktionen angewandt, so wird die Gesamtheit der in der WHERE-Klausel
ausgewählten Tupel als einzige Gruppe betrachtet.
4.1.3.4 Teilabfragen
Innerhalb der WHERE-Klausel kann an jeder Stelle, an der ein Wert erwartet wird, dieser auch
durch eine SQL-Abfrage berechnet werden. Wird in der Teilabfrage auf keine Relation der
Hauptabfrage Bezug genommen, so handelt es sich um eine einfache Teilabfrage. Diese wird
nur einmal ausgewertet, das Ergebnis dieser Auswertung wird dann in der Hauptabfrage verwendet. Wird in der Teilabfrage auf eine Relation der Hauptabfrage Bezug genommen, so
nennen wir das eine korrelierte Teilabfrage. In diesem Fall wird die Teilabfrage für jedes
Tupel der Hauptabfrage neu ausgewertet.
Weiters können mit einem Vergleichsoperator auch gleich lange Listen positionsweise
verglichen werden. Ein solcher Ausdruck liefert wahr, wenn der Vergleich für jede Position
der Liste wahr liefert.
Beispiel 4.9 Wir wollen alle jene Restaurants selektieren, die gleichviele Hauben haben, wie
das Restaurant Drei Husaren. Die Anzahl der Hauben der Drei Husaren bekommen wir aus
einer einfachen Teilabfrage. Die Ausgabe soll nach den Namen der Restaurants sortiert sein.
SELECT *
FROM restaurant
WHERE haube = (SELECT haube
FROM restaurant
WHERE name = ’Drei Husaren’)
ORDER BY name;
Beispiel 4.10 Wir sind nun an jenen Restaurants interessiert, deren Durchschnittspreise für
Speisen höher sind als jener aller Preise der anderen Restaurants mit derselben Anzahl an
Hauben.
SELECT r.*
FROM restaurant r, speise s
WHERE r.rnr = s.rnr
KAPITEL 4. SQL
4.9
GROUP BY r.rnr, r.name, r.adresse, r.haube, r.typ
HAVING AVG(s.preis) > (SELECT AVG(s1.preis)
FROM restaurant r1, speise s1
WHERE r1.rnr = s1.rnr AND
r1.rnr <> r.rnr AND
r1.haube = r.haube);
Wichtige spezielle Formen von Teilbedingungen in der WHERE-Klausel sind:
• EXISTS query“ liefert wahr, genau dann wenn die Abfrage query mindestens ein Tupel
”
selektiert.
• expressionList comparisonOp ANY query“ liefert wahr, wenn der Vergleich der Aus”
drucksliste expressionList mit irgendeinem von der Abfrage query erzeugten Tupel wahr
liefert.
• expressionList comparisonOp ALL query“ liefert wahr, wenn der Vergleich der Aus”
drucksliste expressionList mit allen von der Abfrage query erzeugten Tupel wahr liefert.
• expressionList IN query“ liefert wahr, wenn der Vergleich der Ausdrucksliste expres”
sionList mit einem Tupel der Abfrage query identisch ist.
• expressionList NOT IN query“ liefert wahr, wenn der Vergleich der Ausdrucksliste ex”
pressionList mit keinem Tupel der Abfrage query identisch ist.
An Stelle der Ausdrucksliste kann auch ein einzelner Ausdruck stehen. Die Abfrage darf
dann auch nur ein Attribut selektieren.
Beispiel 4.11 In diesem Beispiel wollen wir zeigen, wie die Division in SQL dargestellt werden kann. Wir wollen wie in Beispiel 3.16 herausfinden, welche Restaurants Speisen zu einer
bestimmten Menge von Preisen, die in der Relation Preisliste gespeichert sind, anbieten.
SELECT r.*
FROM restaurant r
WHERE NOT EXISTS (SELECT p.preis
FROM preisliste p
WHERE p.preis NOT IN (SELECT s.preis
FROM speise s
WHERE s.rnr=r.rnr));
KAPITEL 4. SQL
4.10
4.1.4 Nullwerte
SQL unterstützt den Nullwert NULL. Jeder numerische Vergleich mit einem Nullwert liefert
falsch und jede arithmetische Operation, auf einen Nullwert angewandt, liefert NULL. Boolesche Vergleiche mit Nullwerten werden entsprechend der im Abschnitt 3.3 vorgestellten
3-wertigen Logik behandelt.
Die speziellen Prädikate IS NULL und IS NOT NULL können verwendet werden, um zu
prüfen, ob ein Attribut einen Nullwert enthält bzw. nicht enthält.
Für die nachfolgenden Beispiele benötigen wir eine weitere Relation, nämlich die der Mitarbeiter in R EINE. Mitarbeiter haben einen Namen, eine Sozialversicherungsnummer und ein
Gehalt. Weiters gibt es für manche Mitarbeiter eine Provision und wir müssen die Beziehung
zu dem Restaurant herstellen, in dem jeder Mitarbeiter arbeitet. Da ein Mitarbeiter nur in
einem Restaurant angestellt sein kann, handelt es sich um eine 1:n-Beziehung, die wir durch
Hinzunahme des Primärschlüssels der Restaurants auflösen. Leere Felder kennzeichnen die
Nullwerte.
Mitarbeiter = {vname, nname, svnr, gehalt, prov, rnr}
Die Relation, die wir für die Beispiele verwenden, ist folgende:
Mitarbeiter
vname nname
Gerti
Müller
Anton Eder
Max
Muster
Edith Huber
Rita
Muster
Ilse
Hofer
Rudi
Maier
Theo
Novak
Karin Meinl
svnr
gehalt prov rnr
2435020466
2.000
100
1
8450270768
1.900
50
1
5467151171
1.300
2
9876020170
1.500
2
8350120571
1.800
2
2463300668
1.700
90
3
8533211065
2.100
3
1234240863
2.000
3
8347090964
2.500
120
3
Beispiel 4.12 Wieviele Personen bekommen neben dem Gehalt noch eine Provision?
SELECT COUNT(prov)
FROM mitarbeiter;
COUNT(PROV)
----------4
Enthält eine Spalte einen Nullwert, wird sie nicht mitgezählt.
KAPITEL 4. SQL
4.11
Beispiel 4.13 Wieviel verdient jeder Mitarbeiter an Gehalt, Provision und insgesamt?
SELECT vname, nname, gehalt, prov, gehalt + prov AS sum
FROM mitarbeiter;
VNAME
-----Gerti
Anton
Max
Edith
Rita
Ilse
Rudi
Theo
Karin
NNAME
------Müller
Eder
Muster
Huber
Muster
Hofer
Maier
Novak
Meinl
GEHALT
------2000
1900
1300
1500
1800
1700
2100
2000
2500
PROV SUM
----- -----100
2100
50
1950
90
1790
120
2620
Bei arithmetischen Operationen ist das Ergebnis ein Nullwert, wenn ein Operand ein Nullwert ist.
Als nächstes folgen einige Beispiele, die zeigen, wie SQL mit Nullwerten in Mengenoperationen verfährt.
Beispiel 4.14 Wir wollen wissen, welche Mitarbeiter 50 Euro oder 120 Euro Provision bekommen, sowie über welche Mitarbeiter keine Information vorhanden ist.
SELECT vname, nname, prov
FROM mitarbeiter
WHERE prov IN (50, 120, NULL);
VNAME
-----Anton
Karin
NNAME PROV
------ ----Eder
50
Meinl
120
Dies ist nicht das gewünschte Ergebnis, denn es gibt Mitarbeiter, von denen nicht bekannt
ist, ob sie eine Provision bekommen oder nicht:
SELECT vname, nname, prov
FROM mitarbeiter
WHERE prov IS NULL;
KAPITEL 4. SQL
4.12
VNAME
-----Max
Edith
Rita
Rudi
Theo
ENAME
PROV
------- ---Muster
Huber
Muster
Maier
Novak
Die Tupel, die einen Nullwert als Provision haben, kommen bei der ersten Abfrage nicht
im Ergebnis vor, da vom System ein numerischer Vergleich zwischen Nullwerten durchgeführt
wird und dieser immer einen Nullwert ergibt. Um das gewünschte Ergebnis zu erhalten
müssen wir daher folgende Abfrage schreiben:
SELECT vname, nname, prov
FROM mitarbeiter
WHERE prov IN (50, 120) OR
prov IS NULL;
Beispiel 4.15 Nun wollen wir eine Liste aller Mitarbeiter, deren Provision weder 50 Euro
noch 120 Euro beträgt, und deren Provision kein Nullwert ist.
SELECT vname, nname, prov
FROM mitarbeiter
WHERE prov NOT IN (50, 120, NULL);
no rows selected
Hier werden keine Tupel als Ergebnis selektiert, da für jeden Wert der Provision ein numerischer Vergleich auch mit dem Nullwert durchgeführt wird, was in jedem Fall einen Nullwert
ergibt.
SELECT vname, nname, prov
FROM mitarbeiter
WHERE prov IS NOT NULL;
VNAME
-----Gerti
Anton
Ilse
Karin
NNAME
PROV
------- ----Müller
100
Eder
50
Hofer
90
Meinl
120
KAPITEL 4. SQL
4.13
Da es aber Mitarbeiter gibt, von denen wir die Provision kennen, müssen wir die korrekte
Abfrage wie folgt formulieren:
SELECT vname, nname, prov
FROM mitarbeiter
WHERE prov NOT IN (50, 120) AND
prov IS NOT NULL;
VNAME
-----Gerti
Ilse
NNAME
PROV
------- ----Müller
100
Hofer
90
Beispiel 4.16 Wir wollen nun von jedem Restaurant wissen, wieviel Gehalt und Provision die
Mitarbeiter zusammen bekommen und wieviele Mitarbeiter es gibt.
SELECT rnr, COUNT (gehalt+prov), SUM(gehalt+prov)
FROM mitarbeiter
GROUP BY rnr;
RNR COUNT(GEHALT+PROV) SUM(GEHALT+PROV)
-------- ------------------ ---------------1
2
4050
2
0
3
2
4410
Dass diese Abfrage nicht das gewünschte Ergebnis liefert, ist offensichtlich.
4.1.4.1 Der Outer Join in SQL
SQL unterstützt den Outer-Join, den wir im Abschnitt 3.3.2 vorgestellt haben. In SQL haben wir beim Outer Join die Möglichkeit anzugeben, welche der beiden Seiten beim Joinen
mit Nullwerten aufgefüllt werden soll. Ein Outer-Join zwischen zwei Relationen wird im
FROM-Teil einer SQL-Abfrage durch die Klausel relname1 [FULL|LEFT|RIGHT] OUTER JOIN
”
relname2 ON joinCondition“ ausgedrückt.
Wir rufen uns die Definition des Outer Join in Abschnitt 3.3.2 in Erinnerung:
r ∗ s = q ∪ (r0 × null(S \ X)) ∪ ( null(R \ X) × s0 ).
Der Ausdruck (r 0 × null(S \ X)) füllt die Attribute von s an den unbekannten Stellen
mit null, der Ausdruck ( null(R \ X) × s0 ) die Attribute von r. In diesem Sinn war die
Definition symmetrisch. Die Befehle LEFT OUTER JOIN und RIGHT OUTER JOIN geben in SQL
die Möglichkeit, diese Symmetrie aufzubrechen.
4.14
KAPITEL 4. SQL
Beispiel 4.17 Schreiben wir eine SQL-Abfrage, die Name und Adresse aller Restaurants liefert, für die die Anzahl der Hauben nicht bekannt ist, sowie die Namen gegebenenfalls angebotener Speisen.
SELECT r.name, r.adresse, s.name
FROM restaurant r LEFT OUTER JOIN speisen s ON r.rnr=s.rnr
WHERE r.haube IS NULL;
4.1.5 Datendefinition
In diesem Abschnitt stellen wir die SQL-Befehle zum Erzeugen von Relationen, zur Festlegung von globalen Integritätsbedingungen, zum Ändern von Relationen und zum Entfernen
von Relationen vor.
4.1.5.1 Erzeugen von Relationenschemata
Mit dem Befehl CREATE TABLE relationName ...“ wird ein Relationenschema definiert und ei”
ne leere Relation mit dem Namen relationName zu diesem Schema erzeugt. Zu jedem Attribut
wird ein Typ angegeben; optional können eine oder mehrere Integritätsbedingungen angegeben werden. Mögliche Integritätsbedingungen sind u.a. die Angabe, dass das Attribut einen
Primärschlüssel darstellt (PRIMARY KEY); dass das Attribut keinen Nullwert annehmen darf
(NOT NULL) — diese Bedingung gilt automatisch für Primärschlüsselattribute —; dass ein Attribut eindeutig sein muss (UNIQUE) — diese Bedingung gilt automatisch für Primärschlüsselattribute —; oder eine durch die Klausel CHECK (condition)“ formulierte Wertebereichsein”
schränkung. Weiters kann für Attribute durch die Klausel DEFAULT value“ ein Defaultwert
”
angegeben werden.
Beispiel 4.18 Der folgende SQL-Befehl erzeugt ein Relationenschema mit den Attributen für
Restaurants aus Beispiel 3.1 und dazu eine leere Relation mit dem Namen Restaurant. Er
legt weiters fest, dass das Attribut rnr ein Primärschlüssel ist, dass die Attribute name und
adresse keinen Nullwert annehmen dürfen, und dass haube nur die Werte 0 − 4 annehmen
darf. Für den Typ eines Restaurants ist als Defaultwert österreichisch festgelegt.
CREATE TABLE restaurant
(rnr
INTEGER PRIMARY KEY,
name
name NOT NULL,
adresse adresse NOT NULL,
haube
INT CHECK (haube IN (0, 1, 2, 3, 4)),
typ
VARCHAR(15) DEFAULT ’österreichisch’);
Neben Integritätsbedingungen zu Attributen können auch Integritätsbedingungen zur Relation durch CONSTRAINT-Klauseln angegeben werden, wobei für jede Integritätsbedingung
ein innerhalb der Relation eindeutiger Name vergeben wird.
KAPITEL 4. SQL
4.15
Eine spezielle Integritätsbedingung (zu Attributen oder zu Relationen) ist die mittels einer REFERENCES-Klausel angegebene Fremdschlüsselbedingung FOREIGN KEY, die eine Inklusionsabhängigkeit, wie sie im Abschnitt 6.4 definiert wird, repräsentiert. Zu jeder Fremdschlüsselbedingung kann durch eine ON UPDATE action“ und eine ON DELETE action“ -Klausel
”
”
angegeben werden, wie auf Verletzungen durch Änderung oder Löschen des referenzierten Schlüsselwertes reagiert werden soll. Mögliche Aktionen sind, die Änderung bzw. das
Löschen zu verhindern (NO ACTION), die Änderung oder das Löschen zu propagieren (CASCADE)
bzw. den Wert des referenzierenden Attributes auf einen Nullwert (SET NULL) oder den Defaultwert des Attributs (SET DEFAULT) zu setzen.
Beispiel 4.19 Der nächste SQL-Befehl erzeugt ein Relationenschema mit den Attributen für
die Speisen aus Beispiel 3.1 und dazu eine leere Relation mit dem Namen Speise. Die angeführten Integritätsbedingungen legen u.a. fest, dass die Attribute rnr und name gemeinsam den Primärschlüssel der Relation Speise bilden und dass das Attribut rnr der Relation Speise ein Fremdschlüssel ist, der sich auf das Schlüsselattribut rnr der Relation
Restaurant bezieht (Speise[rnr] ⊆ Restaurant[rnr]). Die Angabe ON UPDATE CASCADE
legt fest, dass eine Änderung der Nummer eines Restaurants bei den entsprechenden Speisen
mitgezogen wird, und die Angabe ON DELETE NO ACTION legt fest, dass ein Restaurant nicht
gelöscht werden darf, solange noch Speisen für dieses Restaurant vorhanden sind.
CREATE TABLE speise
(rnr
INTEGER,
name
name,
preis
euro,
CONSTRAINT speise_pk PRIMARY KEY (rnr, name)
CONSTRAINT rnr_fk FOREIGN KEY (rnr)
REFERENCES restaurant (rnr)
ON UPDATE CASCADE
ON DELETE NO ACTION
CONSTRAINT preis_check CHECK (preis > 0));
4.1.5.2 Globale Integritätsbedingungen
Neben den bei Attributen und Relationen lokal angegebenen Integritätsbedingungen können
auch relationenübergreifende globale Integritätsbedingungen mit dem SQL-Befehl CREATE
ASSERTION festgelegt werden. Dabei wird ein Name für die Integritätsbedingung und eine
boolesche Bedingung angegeben, die in jedem Datenbankzustand erfüllt sein muss. Durch
die Angabe des Zusatzes DEFERRABLE kann angegeben werden, dass die Überprüfung der
Integritätsbedingung mit dem Befehl SET CONSTRAINT constraintName DEFERRABLE“ bis
”
unmittelbar vor das Ende einer Transaktion verschoben werden kann. Durch den Befehl
SET CONSTRAINT constraintName IMMEDIATE“ kann wieder auf eine andauernde Überprüfung
”
dieser Integritätsbedingung zurückgeschaltet werden.
KAPITEL 4. SQL
4.16
Beispiel 4.20 Der nächste SQL-Befehl definiert die globale Integritätsbedingung, dass ein
Restaurant nur dann Speisen um mehr als 50 Euro anbieten kann, wenn es mehr als eine
Haube hat. Die Integritätsbedingung definieren wir als IMMEDIATE, da sie beim Einfügen
neuer Speisen immer gleich überprüft werden soll.
CREATE ASSERTION max_preis
(1 < ALL (SELECT haube
FROM restaurant r, speise s
WHERE r.rnr = s.rnr AND s.preis > 50))
IMMEDIATE;
4.1.5.3
Ändern von Relationenschemata
Mit dem SQL-Befehl ALTER TABLE relationName ADD attribute“ kann ein Attribut zu einer
”
Relation hinzugefügt und durch den SQL-Befehl ALTER TABLE relationName DROP attribute“
”
kann ein Attribut entfernt werden.
Beispiel 4.21 Mit folgendem SQL-Befehl fügen wir das Attribut kalorien zur Relation
Speise hinzu.
ALTER TABLE speise ADD (kalorien INTEGER);
4.1.5.4 Entfernen von Relationenschemata
Mit dem SQL-Befehl DROP TABLE relationName“ wird eine Relation aus der Datenbank ent”
fernt.
4.1.6 Datenmanipulation
In diesem Abschnitt stellen wir die SQL-Befehle zum Einfügen von Tupeln in Relationen,
zum Ändern von Attributwerten von Tupeln, und zum Löschen von Tupeln aus Relationen
vor.
4.1.6.1 Einfügen von Daten
Mit dem SQL-Befehl INSERT INTO relationName (attribute 1, . . . , attribute n) VALUES (va”
lue 1, . . . , value n)“ kann ein neues Tupel in eine Relation eingefügt werden.
Beispiel 4.22 Mit dem nächsten SQL-Befehl fügen wir ein neues Tupel, das Restaurant Wok“
”
in die Relation Restaurant ein.
KAPITEL 4. SQL
4.17
INSERT INTO restaurant (rnr, name, adresse.strasse, adresse.ort,
adresse.plz, adresse.land, haube, typ)
VALUES (10, ’Wok’ , ’Operngasse’, ’Wien’, 1040,
’Österreich’, 0, ’asiatisch’)
Die Syntax zum Einfügen von Werten in Attribute vom Typ ROW ist erst Teil des SQL-3
Standard.
Sollen die Ergebnistupel einer beliebigen Abfrage in eine Relation eingefügt werden, so
kann dafür der SQL-Befehl INSERT INTO relationName (attribute 1, . . . , attribute n) query“
”
verwendet werden.
Beispiel 4.23 Der folgende SQL-Befehl fügt alle österreichischen Restaurants aus der Relation Restaurant in die Relation Inland ein. Die Relation Inland muss bereits existieren.
INSERT INTO inland (rnr, name, adresse)
SELECT rnr, name, adresse
FROM restaurant
WHERE typ = ’österreichisch’;
4.1.6.2 Löschen von Daten
Der SQL-Befehl DELETE FROM relationName“ löscht alle Tupel aus der Relation relationNa”
me und der SQL-Befehl DELETE FROM relationName WHERE condition“ löscht alle Tupel aus
”
der Relation relationName, die die angegebene Bedingung condition erfüllen.
Beispiel 4.24 Schreiben wir einen SQL-Befehl, der alle Restaurants löscht, zu denen es keine
Speise in der Relation Speise gibt:
DELETE FROM restaurant
WHERE rnr NOT IN (SELECT rnr
FROM speise);
4.1.6.3
Ändern von Daten
Mit dem SQL-Befehl UPDATE relationName SET attribute = expression WHERE condition“
”
wird für alle Tupel aus der Relation relationName, die die Bedingung condition erfüllen, der
Wert des Attributes attribute auf den Wert des Ausdrucks expression gesetzt.
Beispiel 4.25 Mit dem nächsten SQL-Befehl erhöhen wir den Preis aller Speisen der Restaurants mit 4 Hauben um 10%.
UPDATE speise
SET preis = preis*1.1
WHERE rnr IN (SELECT rnr
FROM restaurant
WHERE haube = 4);
4.18
KAPITEL 4. SQL
4.1.7 Benutzersichten
Das Konzept der logischen Datenunabhängigkeit (vergleiche Kapitel 1) wird in SQL durch
die Möglichkeit der Definition von Views (Sichtrelationen) unterstützt. Views dienen zum
Aufbau von Benutzersichten und sind auf Grund einer Abfrage über Basisrelationen und zuvor definierter Views definiert. Während die Tupel von Basisrelationen gespeichert sind, sind
die Tupel von Views virtuell, und werden auf Grund der bei der Definition der View angegebenen Abfrage berechnet. Eine View wird in SQL mit Hilfe des Befehls CREATE VIEW
”
relationName (attribute 1, . . . , attribute n) AS query-expression“ definiert.
Änderungen über Views, die durch eine Verknüpfung aus mehreren Relationen definiert
sind, können nicht immer eindeutig auf Änderungen in den zugrunde liegenden Relationen
zurückgeführt werden. Deswegen sind in SQL nur Änderungen über Views, die auf einer Basisrelation oder einer veränderbaren View definiert sind, erlaubt. Weiters darf das Schlüsselwort DISTINCT nicht vorkommen und in der WHERE-Klausel dürfen keine Teilabfragen stehen,
die sich in ihrer FROM-Klausel auf dieselbe Tabelle wie die Hauptabfrage beziehen. Es darf
keine GROUP BY- oder HAVING-Klausel verwendet werden. Ebenso können errechnete Attributwerte nicht direkt geändert werden.
Die Änderung eines Tupels einer View kann dazu führen, dass dieses Tupel nach der
Änderung nicht mehr zur View gehören würde. Solche Änderungen können bei der Definition
der View durch die Angabe der Klausel WITH CHECK OPTION“ verhindert werden.
”
Beispiel 4.26 Mit dem folgenden SQL-Befehl definieren wir eine View Spitze, die die Nummer, den Namen und die Adresse jener Restaurants enthält, die mehr als 2 Hauben haben.
CREATE VIEW spitze (rnr, name, adresse, haube) AS
SELECT rnr, name, adresse, haube
FROM restaurant
WHERE haube > 2
WITH CHECK OPTION;
Wollen wir in der View Spitze die Anzahl der Hauben verändern, so geht das nur, wenn die
Bedingung haube > 2 weiterhin erfüllt ist.
Eine View, deren Ausprägung vom augenblicklichen Datenbankbenutzer abhängt, kann
durch die Verwendung der SQL-Funktion USER definiert werden.
Beispiel 4.27 Die unten definierte View persönlich enthält für jeden Mitarbeiter seine
Personaldaten (unter der Annahme, dass Nachname und Username ident sind):
CREATE VIEW persönlich AS
SELECT *
FROM mitarbeiter m
WHERE m.nname = USER;
Views können mit dem SQL-Befehl DROP VIEW relationName“ entfernt werden.
”
KAPITEL 4. SQL
4.19
4.1.8 Zugriffskontrolle
In SQL hat der Besitzer einer Basisrelation oder View alle Rechte über diese Relation. Er kann
diese Rechte auch anderen Benutzern gewähren und gewährte Rechte wieder zurücknehmen.
Ein Benutzer besitzt eine Relation, wenn er diese erzeugt hat.
Mit dem Befehl GRANT privilege ON relationName TO authID“ wird in SQL das Recht
”
privilege über die Relation relationName dem Benutzer authID gewährt. Zu den in SQL
unterstützten Rechten gehören das Lesen von Tupeln bzw. von ausgewählten Attributwerten (SELECT bzw. SELECT(attribute 1, . . . attribute n)), das Einfügen (INSERT) und Löschen
(DELETE) von Tupeln, das Ändern von Tupeln bzw. von ausgewählten Attributwerten (UPDATE
bzw. UPDATE(attribute)), sowie das Recht, auf Attributen einen Fremdschlüssel zu definieren
(REFERENCES (attribute 1, . . . , attribute n)). Die Angabe ALL PRIVILEGES umfasst alle diese Rechte. Werden Rechte mit der Angabe der Klausel WITH GRANT OPTION“ gewährt, so
”
dürfen diese vom Empfänger weitergegeben werden, sonst nicht.
Beispiel 4.28 Mit dem nächsten SQL-Befehl gewähren wir der Benutzerin Huber alle Rechte
über die View Spitze. Sie darf diese Rechte auch weitergeben.
GRANT ALL PRIVILEGES
ON spitze
TO Huber
WITH GRANT OPTION;
Durch die Angabe des speziellen Autorisierungsidentifikators PUBLIC können Rechte an
alle Benutzer, inklusive aller zukünftigen Benutzer, gewährt werden.
Beispiel 4.29 Nun erlauben wir jedem Benutzer, seine Personaldaten zu lesen.
GRANT SELECT
ON persönlich
TO PUBLIC;
Gewährte Rechte können mit dem SQL-Befehl REVOKE privilege ON relationName FROM
”
authID“ entzogen werden. Wurden inzwischen Rechte weitergegeben, so wird jener Zustand
hergestellt, der gelten würde, wenn das entzogene Recht nie gewährt worden wäre.
Beispiel 4.30 Wollen wir der Benutzerin Huber das Recht entziehen, Nummer und Name der
Restaurants von Spitze zu ändern, so sieht das folgendermaßen aus:
REVOKE UPDATE(rnr, name)
ON spitze
FROM Huber;
4.20
KAPITEL 4. SQL
4.1.9 Transaktionsverwaltung
Die meisten SQL-Befehle können nur im Rahmen einer Transaktion (siehe Kapitel 10) verwendet werden. Ist in einer interaktiven SQL-Sitzung keine Transaktion aktiv und wird
ein SQL-Befehl, der nur innerhalb einer Transaktion ausgeführt werden kann wie INSERT,
UPDATE, SELECT, CREATE TABLE an das Datenbankmanagementsystem übergeben, wird automatisch eine Transaktion gestartet. Die Transaktion kann mit dem SQL-Befehl COMMIT
erfolgreich abgeschlossen bzw. mit dem SQL-Befehl ROLLBACK abgebrochen werden. In Abschnitt 10.4 gehen wir genauer auf die Behandlung von Transaktionen in SQL ein, da wir die
notwendigen Voraussetzungen momentan noch nicht haben.
4.1.10 Definition von Dateiorganisationsformen und Zugriffspfaden
SQL-Befehle zur Festlegung von Dateiorganisationsformen für Relationen und von Zugriffspfaden waren Bestandteil der Norm von SQL-89. Sie wurden jedoch aus dem genormten
Sprachumfang von SQL-92 gestrichen. Verschiedene relationale Datenbankmanagementsysteme unterstützen zur Zeit unterschiedliche Primär- und Sekundärorganisationsformen für
Dateien (vergl. Kapitel 8) und damit verbunden die SQL-Befehle CREATE INDEX/CLUSTER,
ALTER INDEX/CLUSTER und DROP INDEX/CLUSTER in unterschiedlichen Varianten.
4.1.11 Abstrakte Datentypen
Abstrakte Datentypen (ADTs) stellen die wichtigste konzeptionelle Änderung von SQL-2 auf
SQL-3 dar. ADTs unterstützen die Konzepte Objektidentität, Vererbung und Polymorphismus, die aus der objektorientierten Welt kommen. Der Grund für die Erweiterung des relationalen Modells um objektorientierte Konzepte zum Objekt-Relationalen Modell liegt im
Aufkommen und Zusammenspiel von objektorientierten Programmiersprachen und objektorientierten Datenbanken. Dieses Zusammenspiel ermöglicht es, Daten der Anwendungen leicht
in einem persistenten und sicheren Medium – der Datenbank – abzulegen und dort herauszuholen. Daher begannen die verschiedenen DBMS-Anbieter Unterstützung zur Speicherung
und Bearbeitung von nicht-standard Daten zu bieten. Das SQL-3 Komitee schlug daher den
Weg ein, die zugrundeliegende Struktur von Tabellen zu erweitern. Eine Tabelle kann nun
nicht nur mehr aus einfachen (atomaren) Attributen zusammengesetzt sein, sondern Attribute
können selbst zusammengesetzt sein, z.B. als Datentyp ROW oder eben als ADT.
Die Spezifikation eines ADT besteht aus zwei Teilen: der Spezifikation der Attribute, aus
denen sich der ADT zusammensetzt, und der Spezifikation der Funktionen, mit denen auf den
ADT zugegriffen werden kann. Das Verhalten eines ADT ist in der Typdefinition gekapselt.
Von außen sind nur die Definition der Attribute und die Schnittstelle der Funktionen sichtbar,
nicht jedoch die Details der Implementierung. Für Attribute und Funktionen kann angegeben
werden, ob sie public, private oder protected sind. Public bedeutet, dass sie allen Benutzern
des ADTs zur Verfügung stehen; private, dass sie nur innerhalb des ADTs verwendet werden
KAPITEL 4. SQL
4.21
können; protected, dass neben ADT-internem Code nur Subtypen darauf zugreifen können.
ADTs können entweder Wert-ADTs oder Objekt-ADTs sein. Wert-ADTs haben keine Objektidentität, sondern nur Werte für die entsprechenden Instanzen. Objekt-ADTs haben eine
Objektidentität (OID), die für jede Instanz des ADTs eindeutig ist.
Mit dem Befehl CREATE TYPE typeName (attributeList)“ kann ein ADT definiert werden.
”
Mit den Schlüsselwörtern PUBLIC, PRIVATE oder PROTECTED vor Attributen und Funktionen
können wir angeben, wie diese zur Verfügung stehen. Attribute können gespeichert oder virtuell sein. Virtuelle Attribute haben keinen bestimmten Wert, sondern eine Funktion muss
angeben, wie der Wert des Attributs berechnet werden kann. Zu jedem ADT wird ein Konstruktor und ein Destruktor angelegt. Diese können vom Benutzer überschrieben werden. Für
jedes Attribut werden zwei Funktionen angelegt, eine Observer- und eine Mutator-Funktion,
mit denen die Werte der Attribute ausgelesen bzw. verändert werden können.
Beispiel 4.31 Wir wollen anstelle einer Relation Mitarbeiter einen ADT mitarbeiter anlegen. Die Attribute nname, vname und adresse sollen allgemein zur Verfügung stehen. Die
Adresse kann entweder wie zu Beginn des Kapitels beschrieben aus einem ROW Typ bestehen,
oder sie kann selbst ein ADT sein. Das Attribut geburt steht nur innerhalb des ADT zur
Verfügung. Das Attribut alter ist ein virtuelles Attribut. Die zugehörige Funktion alter
stellen wir allgemein zur Verfügung.
CREATE TYPE mitarbeiter (
PRIVATE mnr
INTEGER,
PUBLIC nname
name,
PUBLIC vname
name,
PUBLIC adresse adresse,
PUBLIC gehalt
euro,
PUBLIC prov
euro,
PRIVATE geburt
DATE,
PUBLIC alter
INTEGER VIRTUAL);
PUBLIC FUNCTION alter (m mitarbeiter) RETURNS INTEGER
BEGIN
DECLARE :a INTEGER;
SET a = CAST(CURRENT_DATE - geburt(m));
RETURN a;
END;
Das System generiert für alle Attribute Observer- und Mutator-Funktionen. Die entsprechenden Funktionen für das Attribut name sehen wie folgt aus:
FUNCTION nname (mitarbeiter) RETURNS name
FUNCTION nname (mitarbeiter, name) RETURNS mitarbeiter
4.22
KAPITEL 4. SQL
Wir wollen eine eigene Konstruktor-Funktion schreiben, da wir bestimmte Attribute wie
mnr, nname und vname als Parameter übergeben und auch das Gehalt auf den Default-Wert
1.000 setzen wollen.
CONSTRUCTOR FUNCTION mitarbeiter (r INTEGER, n name, v name)
RETURNS mitarbeiter
DECLARE :m mitarbeiter
BEGIN
NEW :m;
SET :m.mnr = r;
SET :m.nname = n;
SET :m.vname = v;
SET :m.adresse = NULL;
SET :m.gehalt = 1000;
SET :m.prov = NULL;
SET :m.geburt = NULL;
RETURN m;
END;
END FUNCTION
DESTRUCTOR FUNCTION destr_mitarbeiter ( :m mitarbeiter)
RETURNS mitarbeiter
BEGIN
DESTROY :m;
RETURN :m;
END;
END FUNCTION
4.1.12 Rekursion in SQL-3
Relationale Algebra, Relationenkalkül, QBE und SQL-2 sind relational vollständig. Das
heißt, alle Abfragen, die in Relationaler Algebra ausgedrückt werden können, sind auch in
den anderen bisher besprochenen Sprachen formulierbar.
Das bedeutet allerdings nicht, dass alle überhaupt möglichen Abfragen in diesen Sprachen
formuliert werden können. Insbesondere können rekursive Abfragen in diesen Sprachen im
Allgemeinen nicht formuliert werden. Diese Einschränkung ist durch die Einführung von
Rekursion in SQL-3 aufgehoben worden. Wollten wir bis jetzt in einer Abfrage Probleme
wie Finde alle Bestandteile eines bestimmten Teils“ (bill of material), Traveling Salesman“
”
”
oder generelle Graphalgorithmen abarbeiten, so müssen wir das sehr kompliziert durch das
Erstellen von verschachtelten Cursor-Konstrukten machen und mithilfe der Einbettung in eine
prozedurale Programmiersprache (siehe Abschnitt 4.2.2), eine Lösung mit nacktem“ SQL
”
war prinzipiell unmöglich.
KAPITEL 4. SQL
4.23
Lieferung
von
Wien
Wien
Wien
Wien
St. Pölten
St. Pölten
St. Pölten
Klosterneuburg
Tulln
Wr. Neustadt
bis
lnr
Wr. Neustadt
1
Klosterneuburg
1
St. Pölten
1
Linz
1
Krems
2
Melk
2
Linz
2
Tulln
3
Krems
3
Eisenstadt
4
kosten
3
2
6
10
7
6
8
2
3
5
Abbildung 4.1: Beispiel einer Relation für Lieferung
Angenommen, wir haben eine Tabelle, die Lieferdaten speichert, den Lieferanten (lnr),
der eine Strecke beliefert, und die Kosten für die Lieferstrecken (siehe Abbildung 4.1). Wenn
wir wissen wollen, wieviel eine Lieferung in beliebig vielen Etappen von einem Ort zu einem
anderen kostet, oder welche Orte wir von Wien aus beliefern können, so können wir mit
SQL-2 keine allgemeine Abfrage formulieren, die für jede Instanz der Relation Lieferung
das gewünschte Ergebnis liefert. Mit anderen Worten: wir können keine Relation Alle wege
erzeugen, die alle Tupel < X, Y > enthält, für die es einen Weg von X nach Y gibt.
Schrittweise betrachtet erfordert die Erzeugung der Wege für jede Zwischenstufe einen
Join und eine Projektion, z.B.:
CREATE VIEW einstop (start, ziel)
SELECT l1.von, l2.bis
FROM lieferung l1, lieferung l2
WHERE l1.bis = l2.von;
CREATE VIEW zweistop (start, ziel)
SELECT e.start, l.bis
FROM einstop e, lieferung l
WHERE e.ziel = l.von;
Das Ergebnis der Gesamtabfrage besteht dann aus der Vereinigung aller Teilergebnisse:
CREATE VIEW alle_wege (start, ziel)
SELECT von, bis FROM lieferung
UNION
SELECT * FROM einstop
KAPITEL 4. SQL
4.24
UNION
SELECT * FROM zweistop
UNION
.....
Da wir aber nicht wissen, wieviele Zwischenstopps in der aktuellen Instanz vorkommen,
können wir auch keinen allgemeinen Ausdruck finden, der Alle wege in Abhängigkeit von
Lieferung berechnet.
In SQL-3 wird eine rekursive Abfrage mit dem Befehl WITH RECURSIVE relationName AS
”
(initialQuery UNION ALL recursiveQuery) query“ erzeugt. Um die Erzeugung von Duplikaten
zu verhindern, können wir entweder das Schlüsselwort ALL weglassen oder in der Teilabfrage der recursiveQuery das Schlüsselwort DISTINCT verwenden. Im zweiten Fall werden die
Duplikate schon bei der Berechnung der Zwischenresultate eliminiert. Wir können mit Hilfe einer SEARCH-Klausel und der Schlüsselworte DEPTH FIRST BY oder BREADTH FIRST BY
attributeList SET ordnungAttribut die Abarbeitungsstrategie vorgeben. Das System verwaltet dabei eine Hilfsdatei, die das Attribut ordnungAttribut enthält und füllt. Dieses Attribut
enthält einen numerischen Wert, der abhängig von der Abarbeitungsstrategie und den zu beobachtenden Attributen in attributeList die jeweilige Abarbeitungsschicht beschreibt. Dieser
Wert wird dann zur Ausgabe in der richtigen Reihenfolge verwendet. Um Zyklen bei der Abarbeitung zu erkennen, gibt es die CYCLE-Klausel, die Zyklen erkennt und die dazugehörende
Information in der angegebenen Hilfstabelle speichert. Mit dem Befehl CYCLE attributeList
SET attribute TO cycleMarkValue DEFAULT non-cycleMarkValue USING relationName wird
eine Relation relationName mit dem Attribut attribute angelegt, die den Defaultwert noncycleMarkValue enthält, der bei der Entdeckung eines Zyklus in der attributeList allerdings
auf den Wert cycleMarkValue gesetzt wird.
Die Rekursion bringt aber auch aufgrund der Verwendung der Negation das folgende Problem mit sich: wir können Negation in recursiveQuery nur auf Relationen anwenden, die zu
diesem Zeitpunkt vollständig bekannt sind. Dieses Konzept nennen wir Stratifikation und es
wird im Abschnitt 5.4 genau beschrieben. Warum ist diese Einschränkung notwendig? Wenn
wir verlangen, dass ein Tupel t ein Lösungstupel einer Abfrage ist, wenn es nicht einer Relation R angehört, dann darf sich die Relation R nicht mehr verändern. Denn wenn noch neue
Tupel zu R dazukommen, könnte es passieren, dass t plötzlich ein Element von R wird und
daher nun nicht mehr als Lösungstupel für die Abfrage in Frage kommt. Auch alle auf der
Negation aufbauenden Sprachkonstrukte wie INTERSECT und EXCEPT sind von diesem Problem betroffen. Gruppierung und Aggregatfunktionen haben eine ähnliche Auswirkung. Ein
Tupel, das bei der rekursiven Verarbeitung als Lösungstupel erkannt wurde, kann wieder aus
der Lösungsmenge fallen, wenn sich ein aggregierter Wert während der Rekursion verändert.
Aus diesem Grund können auch Aggregatfunktionen nur auf Relationen angewandt werden,
die bereits vollständig bekannt sind.
Beispiel 4.32 Wir wollen nun anhand der Relation Lieferung herausfinden, welche Orte von
Wien aus beliefert werden können und welche Kosten dabei anfallen. Duplikate sollen nicht
KAPITEL 4. SQL
4.25
eliminiert werden. Die Suche soll als Breitensuche durchgeführt werden, also sollen zuerst
alle Orte ausgegeben werden, die ohne Stop von Wien aus beliefert werden, im nächsten
Schritt alle Orte, die mit einem Zwischenstop beliefert werden können usw. Die Information
über die Suchtiefe wird im Attribut ordnung abgelegt, das dann zur Sortierung der Ausgabe
verwendet wird. Informationen über allfällige Zyklen, die im Attribut bis auftreten, wollen
wir in der Tabelle Zyklen mit dem Attribut zyklus ablegen.
WITH RECURSIVE alle_wege (von, bis, kosten) AS
(SELECT von, bis, kosten
FROM lieferung
UNION ALL
SELECT a.von, l.bis, a.kosten + l.kosten
FROM alle_wege a, lieferung l
WHERE a.bis=l.von)
SEARCH BREADTH FIRST BY von SET ordnung
CYCLE bis SET zyklus TO ’1’ DEFAULT ’0’ USING zyklen
SELECT * FROM alle_wege
ORDER BY ordnung;
4.1.13 Trigger in SQL-3
Trigger, die im SQL-3 Standard definiert werden, erlauben es dem Datenbankmanagementsystem auf Änderungen, die auf den Daten durchgeführt werden, direkt zu reagieren und selbst
Aktionen zu setzen. So können wir mit Hilfe von Triggern die Integrität der Datenbank besser
sicherstellen.
Trigger arbeiten nach dem Event-Condition-Action“-Modell. Das bedeutet, dass wir
”
Trigger definieren können, die vor oder nach einem bestimmten Event (dem UPDATE, INSERT
oder dem DELETE auf bestimmte Tabellen oder Spalten) abhängig von bestimmten Bedingungen eine bestimmte Aktion durchführen. Mit dem Befehl CREATE TRIGGER triggerName
”
BEFORE/AFTER event ON table WHEN triggerCondition triggerAction“ wird ein Trigger angelegt. Mit der Klausel FOR EACH ROW bzw. FOR EACH STATEMENT legen wir die Granularität des
Triggers fest. Er kann einmal für jede Änderung einer Zeile oder einmal für das gesamte SQLStatement ausgeführt werden. Mit der Klausel REFERENCING OLD alteDaten NEW neueDaten
können wir auf die Werte einer Zeile oder einer ganzen Tabelle aller im Falle eines UPDATES
geänderten Daten zugreifen. Diese Klausel ist aber nur zulässig, wenn die Triggergranularität
FOR EACH ROW ist.
Beispiel 4.33 Der folgende SQL Befehl erzeugt einen Trigger, der bei allen Mitarbeitern, die
eine Gehaltserhöhung von mehr als 5% bekommen, die Provision auf 0 setzt.
CREATE TRIGGER provision
AFTER UPDATE OF gehalt ON mitarbeiter
4.26
KAPITEL 4. SQL
REFERENCING OLD as gehalt_alt
NEW as gehalt_neu
FOR EACH ROW
WHEN gehalt_alt * 1.05 < gehalt_neu
UPDATE mitarbeiter
SET prov = 0;
Bei der Verwendung von Triggern müssen wir beachten, keine zyklischen Trigger zu definieren. In obigem Beispiel wäre das etwa der Fall, wenn wir einen Trigger definierten, der,
wenn ein Mitarbeiter eines Restaurants mehr als der Durchschnitt aller Mitarbeiter dieses Restaurants verdient, das Gehalt des Mitarbeiters um 20 Euro erhöht. Dieser Trigger reagiert
auf ein UPDATE des Attributes gehalt. Durch die Ausführung des Triggers wird das Attribut
gehalt nochmals verändert, der Trigger wird wieder gefeuert usw.
4.2 Embedded SQL
Im Teil 5 des SQL-3 Standards mit dem Titel SQL Host Language Bindings“ wird die Einbet”
tung von SQL in verschiedene Wirtsprachen beschrieben. Die Wirtsprachen, die im Standard
behandelt werden sind C, C++, BASIC, Ada und COBOL.
4.2.1 Prinzip der Einbindung
Ein Embedded-SQL-Programm besteht aus Befehlen der jeweiligen Wirtsprache und ESQLBefehlen. ESQL-Befehle werden durch das Schlüsselwort EXEC SQL als solche ausgewiesen. Die in einem besonderen Deklarationsteil (der DECLARE SECTION“) definierten Varia”
blen können sowohl von Befehlen der Wirtsprache als auch von ESQL-Befehlen gelesen und
geschrieben werden, wobei im Fall von ESQL-Befehlen diese Variablen durch einen vorangestellten Doppelpunkt gekennzeichnet werden. Als Befehle stehen alle im letzten Abschnitt
vorgestellten SQL-Befehle zur Verfügung. So können wir mittels EXEC SQL UPDATE relation”
Name SET attribute = expression WHERE condition“ für alle Tupel aus der Relation relationName, die die Bedingung condition erfüllen, den Wert des Attributes attribute auf den Wert
des Ausdrucks expression setzen.
Abbildung 4.2 zeigt den Ablauf zur Erstellung eines ausführbaren Programms, das mittels
SQL auf eine Datenbank zugreift. Zunächst werden von einem speziellen ESQL-Precompiler
die ESQL-Befehle in normale Befehle aus der Wirtsprache übersetzt. Dadurch entsteht ein
Programm, das von einem Compiler der Wirtsprache übersetzt werden kann. Zuletzt wird der
Objektcode mit der ESQL-Laufzeitbibliothek gelinkt.
KAPITEL 4. SQL
4.27
prog.sc
ESQL-Precompiler
prog.c
C Compiler
prog.o
Linker
SQL-Library
prog
Abbildung 4.2: Ablauf der Erstellung eines ausführbaren Programmes in C
4.2.2 Cursor
Beim Zusammenspiel zwischen datensatzorientierten Programmiersprachen, wie sie die Wirtsprachen sind, und der mengenorientierten Sprache SQL entsteht das Problem, dass die Menge
der Tupel ein SQL-Abfrage in eine Reihe von Tupeln verwandelt werden muss, da die Wirtsprachen nur ein Tupel nach dem anderen abarbeiten können. Um die Tupel einer Abfrage
elementweise abzuarbeiten, wird das Konzept eines Cursors verwendet.
Ein Cursor wird mit dem Befehl EXEC SQL DECLARE cursorName CURSOR FOR query “ für
”
eine bestimmte Abfrage (query) deklariert. Sollen bestimmte Attributwerte der ausgewählten
Tupel in der weiteren Verarbeitung geändert werden, so wird der DECLARE CURSOR-Befehl um
die Klausel FOR UPDATE OF attribute-1, . . . , attribute-n ergänzt.
Die Deklaration des Cursors bedingt noch nicht die Ausführung der dem Cursor zugeordneten SQL-Abfrage. Diese wird erst durch den Befehl EXEC SQL OPEN CURSOR cursorName“
”
ausgeführt, wobei der Cursor vor das erste Tupel des Ergebnisses gesetzt wird. Mit dem
Befehl EXEC SQL FETCH cursorName INTO :var-1, . . . , :var-n“ wird zunächst der Cursor
”
um ein Tupel weiterbewegt, danach werden die Attributwerte des Tupels in die angegebenen ESQL-Wirtvariablen gelesen. Ist kein Tupel mehr vorhanden, wird die Statusvariable
SQLSTATE gesetzt. Ein Cursor wird mit dem Befehl EXEC SQL CLOSE cursorName“ wieder
”
geschlossen. Beim Beenden einer Transaktion mit den Befehlen EXEC SQL COMMIT“ oder
”
EXEC SQL ROLLBACK“ werden etwaige offene Cursor automatisch geschlossen.
”
4.3 SQL-2 versus SQL-3 Standard
Der Schritt von SQL-2 zu SQL-3 bedeutete eine enorme Erweiterung des Sprachumfangs von
SQL. Aufgrund des anspruchsvollen und komplexen Programms haben die Normierungsinstitute ANSI und ISO daher beschlossen, die weitere Entwicklung von SQL in mehrere Stan-
4.28
KAPITEL 4. SQL
dards aufzuteilen. Der Standard für die ersten fünf Teile ist bereits bei ANSI erhältlich, die
Beschreibung der restlichen Teile wird folgen.
Teil 1: ANSI/ISO/IEC 9075-1-1999 Information Technology – Database Languages – SQL
Part 1: Framework (SQL/Framework). Dieser Teil gibt einen Überblick über den Standard und beschreibt, in welcher Form die einzelnen Komponenten von SQL zusammenspielen.
Teil 2: ANSI/ISO/IEC 9075-2-1999 Information Technology – Database Languages – SQL
Part 2: Foundation (SQL/Foundation). In diesem Teil finden wir die Spezifikation aller
Datentypen, die Beschreibung der DDL, der DML, die Befehle zur Transaktionskontrolle und zum Verbindungsaufbau mit der Datenbank. Dieser Teil enthält die meisten
der vorgestellten Erweiterungen von SQL: die neuen Datentypen und ADTs, die Behandlung der Rekursion und der Trigger.
Teil 3: ANSI/ISO/IEC 9075-3-1999 Information Technology – Database Languages – SQL
Part 3: SQL/CLI (Call Level Interface). CLI bietet eine Schnittstelle zu einem Datenbankmanagementsystem, wobei kein Preprozessor notwendig ist, um die SQL-Befehle
in die entsprechende Programmiersprache der Anwendung zu übersetzen. Es werden
die Strukturen und Prozeduren beschrieben, die verwendet werden können, um SQLStatements aus Anwendungen, die in verschiedenen Programmiersprachen geschrieben sind, auszuführen. Damit können wir Resourcen allozieren und deallozieren, die
Verbindung zu einem SQL-Server kontrollieren, Transaktionen kontrollieren und SQLStatements ausführen.
Grob gesagt erzeugt die Anwendung durch das Absetzen eines SQL-Befehls einen CLI
environment handle. Danach erstellt sie einen connect handle, über den die Verbindung mit der Datenbank abläuft. CLI kann nun die SQL-Statements auf der Datenbank
durchführen. Nach erfolgreicher Durchführung wird die Verbindung wieder geschlossen, der connect handle und der environment handle freigegeben.
Teil 4: ANSI/ISO/IEC 9075-4-1999 Information Technology – Database Languages – SQL
Part 4: SQL/PSM (Persistent SQL Modules). PSM beschreibt, wie Stored Procedures und benutzerdefinierte Funktionen einer 3GL (Third Generation Language) in SQL
geschrieben werden können. Funktionen und Prozeduren können entweder extern definiert sein oder in ADTs gekapselt sein. Für ADTs werden automatisch Konstruktor- und
Destruktor-Funktionen angelegt, die bei der Erstellung einer neuen Instanz eines ADTs
und beim Löschen verwendet werden müssen. Für jedes Attribut wird eine Observerund eine Mutator-Funktion angelegt, die zum Auslesen und zum Verändern der Werte
verwendet werden.
Zur Kontrolle des Programmflusses werden Blockbefehle wie BEGIN und END, Schleifenbefehle wie WHILE, IF THEN ELSE, REPEAT, FOR und LOOP und der Befehl CASE
KAPITEL 4. SQL
4.29
zugelassen. Diese müssen nicht mehr von Wirtsprachen ausgeborgt“ werden. Dieser
”
Zusatz erweitert SQL zu einer computational vollständigen Sprache.
Teil 5: ANSI/ISO/IEC 9075-5-1999 Information Technology – Database Languages – SQL
Part 5: SQL/Bindings. Dieser Teil wird aus Kompatibilitätsgründen zu SQL-2 übernommen und auf SQL-3 Konstrukte erweitert. Er stellt drei Methoden vor, wie aus
Anwendungsprogrammen, die in einer der gängigen Programmiersprachen geschrieben
wurden, auf eine Datenbank zugegriffen werden kann. Die am meisten verwendete Methode ist die Einbettung in eine andere Programmiersprache durch Verwendung eines
Precompilers. Weiters gibt es Dynamic SQL und direkten Aufruf von SQL-Statements.
Teil 6: SQL/Transactions. Dieser Teil beschreibt die Strategien und Mechanismen, durch die
Anwendungsprogramme mit Transaktionsmanager und Resourcemanager interagieren.
Der Transaktionsmanager muss die verschiedenen Resourcemanager, z.B. verschiedene Datenbankmanagementsysteme, koordinieren. Die Resourcemanager ihrerseits verwenden two-phase-commit, um die Korrektheit eines Transaktionsablaufs sicherzustellen. Diese Verfahren werden bei verteilten Transaktionen, die verschiedene Datenbankmanagementsysteme auf unterschiedlichen Plattformen betreffen, verwendet.
Teil 7: SQL/Temporal. In diesem Teil wird auf den Umstand eingegangen, dass Daten nur für
bestimmte Zeitabschnitte gültig sind; z.B. kann ein Mitarbeiter in der Mitarbeiterhierarchie aufsteigen oder ein neues Gehalt bekommen. Nicht mehr gültige Daten können
jedoch oft nicht einfach gelöscht werden. In diesem Teil werden Datentypen und Befehle vorgestellt, um über die Zeit veränderte Daten zu verwalten.
Teil 8: SQL/Object. In diesem Teil wird beschrieben, wie das Datenbankmanagementsystem
auf spezielle Datentypen, die in den Anwendungsprogrammen verwendet werden, zugreifen kann.
Zusätzlich zum SQL-3 Projekt gibt es weitere Projekte zur Erweiterung von SQL, die teils
neuere Entwicklungen in Informationssystemen aufgreifen. So hat etwa SQL/MM zum Ziel,
Standard-Multimedia-Pakete basierend auf ADT’s in SQL-3 zu entwickeln, und SQL/RT will
Unterstützung für Echtzeitdatenbanken geben.
KAPITEL 4. SQL
4.30
4.4 Übungsaufgaben
Übung 4.1 In einer relationalen Datenbank sind Daten über Erdbeben in folgenden Relationen gespeichert:
erdbeben(ENR, EPX, EPY, DATUM)
schaden(ENR, SNR, KX, KY, OPFER, EURO)
erdstoss(ENR, SNR, SX, SY, STAERKE)
stadt(KX, KY, SNAME, LAND)
Schlüssel sind unterstrichen. Die Erdbeben sind durch eindeutige Nummern identifiziert
und durch die kartesischen Koordinaten der Epizentren (X- und Y-Koordinaten, in km) sowie
die Zeitpunkte des Auftretens beschrieben. Jedes Erdbeben umfasst (i.a. mehrere, durchnummerierte) Erdstöße, für die jeweils Auftrittsort (=Koordinaten) und Stärke gespeichert sind.
Durch einen Erdstoß enstandene Schäden sind in schaden nach Orten (=Koordinaten) gespeichert, wobei jeweils die Anzahl der Opfer und der Sachschaden (Einheit: 100.000 Euro)
gespeichert ist. stadt enthält ein Koordinatenverzeichnis aller Städte.
Schreiben Sie eine SQL-Abfrage, die das heftigtste Erdbeben (Heftigkeit = stärkster Einzelstoß) ausgibt, zusammen mit dem Datum und der Anzahl der Opfer bei diesem Erdbeben.
Schreiben Sie eine SQL-Abfrage, die jene Erdbeben ausgibt, die im Umkreis von 100km
(=Abstand vom Epizentrum) einen Gesamtschaden von mehr als 15 Mio Euro verursacht haben.
Übung 4.2 Gegeben sind folgende Relationen einer Datenbank über Opernsänger:
auftritt(SAENGER, HAUS, TAG, MONAT, JAHR, GAGE)
lehrer(MEISTER, SCHUELER)
Schlüsselattribute sind unterstrichen. Jedes Tupel in auftritt gibt an, in welchem
Opernhaus der Sänger an dem betreffenden Datum aufgetreten ist und wieviel er dafür kassiert
hat. Die Tupel in lehrer geben an, welche Sänger Lehrer von anderen Sängern sind.
Formulieren Sie eine Abfrage in SQL, die die Namen aller Sänger liefert, welche in einem
Zeitraum von zwei aufeinanderfolgenden Kalenderjahren in Summe mehr als 500.000,- Euro
Gage kassiert haben.
Formulieren Sie eine Abfrage in SQL, die genau jene Tupel aus lehrer liefert, für die
gilt, dass der Schüler in einem Opernhaus aufgetreten ist, in dem sein Lehrer nicht aufgetreten
ist.
Übung 4.3 Gegeben sind folgende Relationen einer Datenbank über Schilifte:
lift(LNR,TAL,BERG,KAP,LAENGE),
station(SNAME,HOEHE),
piste(PNR,START,ZIEL,GRAD,LAENGE)
KAPITEL 4. SQL
4.31
Schlüsselattribute sind unterstrichen. Jedes Tupel in lift gibt die eindeutige Nummer,
die Tal- und Bergstation, sowie die Förderkapazität (Personen pro Stunde) und die Länge
eines Lifts an. Zu jeder Station ist in station ihre Seehöhe gespeichert; zu einer Station
können mehrere Lifte hinführen bzw. von dort wegführen. Für jede Piste sind eine eindeutige
Nummer, Start und Ziel (jeweils Stationen), der Schwierigkeitsgrad ( blau“ = leicht, rot“ =
”
”
mittelschwer, schwarz“ = schwer) und die Länge gespeichert.
”
Formulieren Sie eine Abfrage in SQL, die den Namen der höchstgelegenen Station und
die Anzahl der Personen ausgibt, die an einem Tag (= in 8 Stunden) maximal dorthin befördert
werden können. Anmerkung: Die höchstgelegene Station ist eindeutig.
Formulieren Sie eine Abfrage in SQL, die in einer Tabelle die Nummern jener Pisten
zusammen mit dem jeweiligen Schwierigkeitsgrad und der entsprechenden Höhendifferenz
ausgibt, sodass jede Piste für ihren Schwierigkeitsgrad die höchste Höhendifferenz hat. Ausgabetupel z.B: (1,blau,500) .
Übung 4.4 Gegeben sind folgende Relationen aus der Datenbank eines Gemüsegroßanbauers:
pflanze(NAME,DUENGER,REIFEDAUER)
anbau(FELD,BEET,PNAME,STUECK,WOCHE)
weg(WEGNR,FELD1,FELD2,LAENGE)
Schlüsselattribute sind unterstrichen. Für jede Pflanze ist ihr eindeutiger Name, ihr wöchentlicher
Düngerbedarf und ihre Reifedauer (in Wochen) gespeichert. Jedes Tupel in anbau besagt,
dass eine bestimmte Stückzahl einer Pflanze in der angegebenen Woche in einem Beet eines
Feldes angepflanzt worden ist. Jedes Feld besteht aus mehreren Beeten, die unterschiedlich
bepflanzt sein können. Ernte und Anpflanzung erfolgen jeweils am Wochenbeginn. In weg
sind direkte Wege zwischen Feldern und deren Länge (in m) gespeichert.
Schreiben Sie eine Abfrage in SQL, die jene Felder liefert, die in der 30. Woche mit Karotten (’KAR’) bepflanzt waren und mehr als 1 kg Dünger für diese benötigt haben, zusammen
mit der Düngermenge.
Schreiben Sie eine SQL-Abfrage, die jene Beete ausgibt, in denen unmittelbar hintereinander zweimal dieselbe Pflanzenart angebaut worden ist.
Übung 4.5 Gegeben sind folgende Relationen aus der Datenbank einer Gärtnerei für Schnittblumen:
blume(NAME,DUENGER,WACHSZEIT)
anbau(GLASHAUS,BEET,BNAME,STUECK,WOCHE)
weg(WEGNR,GLASHAUS1,GLASHAUS,LAENGE)
Schlüsselattribute sind unterstrichen. Für jede Blumenart ist ihr eindeutiger Name, ihr
wöchentlicher Düngerbedarf (in Gramm) und die Zeit bis zur Schnittreife (in Wochen) gespeichert. Jedes Tupel in anbau besagt, dass eine bestimmte Stückzahl einer Blume in der
KAPITEL 4. SQL
4.32
angegebenen Woche in einem Beet eines Glashauses angepflanzt worden ist. Jedes Glashaus
hat mehrere Beete, die unterschiedlich bepflanzt sein können. Blumenschnitt und Anpflanzung erfolgen jeweils am Wochenbeginn. In weg sind direkte Wege zwischen Feldern und
deren Länge (in m) gespeichert.
Formulieren Sie eine Abfrage in SQL, die jene Glashäuser liefert, in denen in der 30. Woche mehr als 2 kg Dünger für Tulpen (’TULPE’) benötigt wurde, zusammen mit der jeweiligen
Düngermenge.
Schreiben Sie eine SQL-Abfrage, die jene Beete ausgibt, in denen unmittelbar hintereinander zweimal dieselben Blumen gepflanzt wurden.
Übung 4.6 Gegeben sind folgende Relationen aus der Datenbank eines Perlenzüchters:
muschel(MNAME,PTYP),
perle(PTYP,KALIBER,PREIS),
stelle(NR,ANZKOERBE,TIEFE),
besatz(NR,JAHR,MNAME),
ernte(NR,JAHR,KALIBER,ANZPERLEN)
Schlüsselattribute sind unterstrichen. Für jede Muschelart ist ihr eindeutiger Name sowie
der Perlentyp gespeichert, der von dieser Muschelart produziert werden kann (Annahme hier:
nur ein Typ). Für jeden Perlentyp (z.B. weiß, schwarz) ist der Preis einer Perle nach
Kaliber (Durchmesser in mm) gespeichert. Die Muscheln werden in Körben an bestimmten
nummerierten Stellen ausgesetzt, von denen die Anzahl der Muschelkörbe und die Tiefe (in
m), in der sie sich befinden, gespeichert sind. Beim Besatz einer Stelle (höchstens einmal pro
Jahr) werden alle Körbe mit Muscheln derselben Art (mname) bestückt, mit je 10 Stück pro
Korb. Die Daten der Ernte an einer Stelle sind mit dem Erntejahr bestimmt und geben die
Anzahl der Perlen an, die pro Kaliber aus den Muscheln gewonnen wurden.
Formulieren Sie eine Abfrage in SQL, die die Nummer(n) jener Stelle(n) liefert, an denen
im Jahr 1992 am meisten Perlen des Kalibers 7mm in einer Ernte geerntet worden sind, sowie
die betreffende Anzahl.
Formulieren Sie eine Abfrage in SQL, die jene Muschelarten liefert, mit denen an Stelle 7
jeweils eine Ausbeute von insgesamt mehr als 5000 weißen Perlen erzielt wurde, zusammen
mit der Ausbeute. (Die Ausbeute bezieht sich auf alle Besätze.)
Übung 4.7 Gegeben seien die Datenbankrelationen aus Beispiel 3.9.
Schreiben Sie eine Abfrage in SQL, die jene Fluglinien ausgibt, die in einem Land nur
Inlandsflüge anbieten, zusammen mit dem Land. (Annahme: die Einträge in flug sind symmetrisch, d.h., wenn es einen Flug von Wien nach Frankfurt gibt, gibt es auch einen Flug von
Frankfurt nach Wien.)
Schreiben Sie eine Abfrage in SQL, die zu jeder Fluggesellschaft angibt, wieviele Flugzeuge von welchen Herstellern zwischen 1970 und 1995 gekauft wurden.
KAPITEL 4. SQL
4.33
Übung 4.8 Gegeben seien die Datenbankrelationen aus Beispiel 3.10.
Schreiben Sie eine Abfrage in SQL, die den Namen und die Art aller Tiere ausgibt, die in
zu dicht besiedelten Gehegen sitzen.
Schreiben Sie eine Abfrage in SQL, die Nummer und Typ aller Käfige ausgibt, in denen
sich nur Tiere derselben Art befinden.
Übung 4.9 Gegeben seien die Datenbankrelationen aus Beispiel 3.11.
Schreiben Sie eine Abfrage in SQL, die zu jeder Speise den dazugehörigen Gewinn für
die Firma angibt.
Schreiben Sie eine Abfrage in SQL, die den Namen aller Zutaten zu den Produkten mit
der geringsten Haltbarkeitsdauer angibt.
Übung 4.10 Gegeben seien die Datenbankrelationen aus Beispiel 3.12.
Die Länderwertung gibt zu jedem Land und Geschlecht die Summe aller in einer Saison
erreichten Punkte an. (Achtung bei Rennen mit 2 Durchgängen.) Schreiben Sie eine Abfrage
in SQL, die zu jedem Land das stärkere Geschlecht in der Länderwertung ausgibt gemeinsam
mit den Punkten.
Schreiben Sie eine Abfrage in SQL, die den Namen jener FahrerInnen angibt, die es geschafft haben, sich im 2. Lauf in der Gesamtwertung um mehr als 5 Plätze zu verbessern und
wie oft es ihnen gelungen ist.
Übung 4.11 Gegeben seien die Datenbankrelationen aus Beispiel 3.13.
Schreiben Sie eine Abfrage in SQL, die den Namen und die Kategorie aller jener Hotels
ausgibt, die in der Woche vom 14. - 21. August 1999 ausgebucht sind (Zimmer werden immer
nur für die ganze Woche vergeben).
Schreiben Sie eine Abfrage in SQL, die zu jeder Bettenanzahl Name und Adresse jener
Hotels angibt, die die günstigsten Nächtigungspreise für dieser Bettenanzahl haben (Bsp.:(1,
Bristol, Kärntnerstr. 1)).
Übung 4.12 Gegeben seien die Datenbankrelationen aus Beispiel 3.14.
Schreiben Sie eine Abfrage in SQL, die Name, Adresse und die Anzahl der Sparbücher
jener Kundinnen ausgibt, die im Jahr 1997 insgesamt mehr Geld eingelegt als abgehoben
haben.
Schreiben Sie eine Abfrage in SQL, die Name, Adresse und Beruf aller jener Kundinnen
ausgibt, die zum 1.1.1997 kein Sparbuch hatten.
4.34
KAPITEL 4. SQL
Kapitel 5
Datalog
5.1 Motivation
Datalog ist eine Prolog-ähnliche logische Abfragesprache, in der rekursive Anfragen an eine Datenbank direkt (auf nicht-prozedurale Weise) formuliert werden können. Die Relation
Alle wege aus Beispiel 4.32 kann in Datalog unter Zuhilfenahme einer Relation Sum(X, Y, Z)
(X = Y + Z) wie folgt definiert werden:
Alle wege(START, ZIEL, KOSTEN) : − Lieferung(START, ZIEL, , KOSTEN).
Alle wege(START, ZIEL, KOSTEN) : − Alle wege(START, BIS, KOSTEN1),
Lieferung(BIS, ZIEL, , KOSTEN2),
Sum(KOSTEN, KOSTEN1, KOSTEN2).
Sollen alle Wege von einem bestimmten Ort (z.B. Wien) berechnet werden, so können wir
dies durch Definition der gesamten Relation Alle wege (wie oben) und anschließende Abfrage Alle wege(wien, X, Y)“ realisieren. Effizienter ist es aber, eine spezielle Abfrage zu
”
konzipieren, da wir in diesem Fall nur die Wege von Wien weg berechnen und nicht alle
möglichen Wege in der Relation.
Alle wienwege(START, ZIEL, KOSTEN) : − Lieferung(wien, ZIEL, , KOSTEN).
Alle wienwege(START, ZIEL, KOSTEN) : − Alle wienwege(START, BIS, KOSTEN1),
Lieferung(BIS, ZIEL, , KOSTEN2),
Sum(KOSTEN, KOSTEN1, KOSTEN2).
5.2 Die Syntax von Datalog
Die Syntax der Sprache Datalog ist durch folgende BNF-Deklaration gegeben.
1
KAPITEL 5. DATALOG
5.2
<Datalog_Programm> ::= <Datalog_Regel> |
<Datalog_Programm>
<Datalog_Regel>
<Datalog_Regel>
::= <Regelkopf> :- <Regelrumpf>.
<Regelkopf>
::= <Literal>
<Regelrumpf>
::= <Literal> |
<Regelrumpf>, <Literal>
<Literal>
::= <Relationen_id>[(<Argumentliste>)]
<Argumentliste>
::= <Term> |
<Argumentliste>, <Term>
<Term>
::= <Konstantensymbol> |
<Variablensymbol>
<Konstantensymbol> ::= <Zahl> | <Kleinbuchstabe> |
<Kleinbuchstabe><String>
<Variablensymbol>
::= <Großbuchstabe> |
<Großbuchstabe><String> | "_"
5.2.1 Einschränkungen zur Syntax von Datalog
< Relationen id > bezeichnet entweder den Namen einer bereits bekannten, in der Datenbank abgespeicherten Relation (z.B. Restaurant) oder einer neuen Relation, die durch das
Datalog-Programm definiert wird (z.B. Alle wege). Durch ein Datalog-Programm können
gleichzeitig mehrere neue Relationen definiert werden. Namen bereits existierender Relationen dürfen nur in Regelrümpfen vorkommen, da diese Relationen nicht verändert werden
sollen. Außer Datenbank-Relationen sind als < Relationen id > auch spezielle Vergleichsprädikate wie =, <>, <, >, usw. zugelassen. Diese werden formal den bekannten Datenbankrelationen gleichgestellt und dürfen daher nur in Regelrümpfen vorkommen.
Jede Variable, die im Kopf einer Datalog-Regel vorkommt, muss auch im Rumpf derselben Regel vorkommen. Variablen, die als Argumente spezieller Vergleichsprädikate vorkommen, müssen im selben Regelrumpf auch in Literalen ohne Vergleichsprädikate vorkommen.
Jede verwendete < Relationen id > tritt immer mit derselben Anzahl von Argumenten
auf.
Datalog-Abfragen werden auch Datalog-Programme“ genannt.
”
KAPITEL 5. DATALOG
5.3
5.3 Semantik von Datalog
Die Semantik von Datalog ohne Negation1 ist formal sehr einfach beschreibbar. Es gibt zwar
mehrere verschiedene Semantiken, allerdings können wir zeigen, dass sie äquivalent sind und
so dasselbe Ergebnis liefern. Wir stellen in diesem Abschnitt zunächst die logische Semantik
von Datalog vor, die einem Programm rein deklarative Bedeutung zuschreibt, danach die operationale Semantik von Datalog, die auf einer konstruktiven Bottom-Up“ Methode basiert.
”
5.3.1 Logische Semantik von Datalog
Sei R eine Datalog-Regel der Form
L0 :- L1 , L2 , ..., Ln
wobei jedes Li ein Literal der Form pi (t1 , . . . tni ) ist und seien x1 , x2 , . . . , xk alle Variablen, die in R vorkommen, Dann bezeichnen wir mit R ∗ die folgende prädikatenlogische
Implikationsformel:
∀x1 ∀x2 . . . ∀xk ((L1 ∧ L2 ∧ . . . ∧ Ln ) ⇒ L0 ).
Es werden also die Namen von Datenbankrelationen als Prädikatensymbole gedeutet.
Sei P ein Datalog-Programm bestehend aus den Regeln R1 , R2 , . . . Rm , dann bezeichnen
wir mit P ∗ jene prädikatenlogische Formel, die durch Konjunktion der einzelnen R i∗ entsteht,
also:
∗
P ∗ = R1∗ ∧ R2∗ ∧ . . . ∧ Rm
Es wird also jedem Datalog-Programm P in (semantisch) eindeutiger Weise eine Formel
P zugeordnet.
Wir betrachten nun eine in der Datenbank abgespeicherte Relation R. Auch dieser Relation können wir eine prädikatenlogische Formel R∗ zuordnen, die aus der Konjunktion aller
Prädikatenausdrücke der folgenden Form besteht:
∗
R(t1 , . . . , to ) für jedes Tupel (t1 , . . . , to ) in R
Einzelne Prädikatenausdrücke der Form R(t1 , . . . , to ) nennen wir auch Fakten.
Da eine Relation eine (ungeordnete) Menge von Tupeln ist, ist die Zuordnung R → R ∗
nicht eindeutig bestimmt. Um diese Zuordnung eindeutig zu machen, können wir eine beliebige Ordnung (z.B. lexikographische Ordnung) über den Tupeln einer Relation voraussetzen.
Die Auswahl der Ordnung spielt keine Rolle, weil die logische Konjunktion kommutativ ist.
Eine gesamte Datenbank DB bestehend aus mehreren Relationen R 1 , R2 , . . ., Rk kann nun
als entsprechende logische Formel DB* gedeutet werden:
1
Die Negation in Datalog führen wir in Anbschnitt 5.4 ein.
KAPITEL 5. DATALOG
5.4
DB ∗ = R∗1 ∧ R∗2 ∧ . . . ∧ R∗k .
Sei G eine Konjunktion von Fakten und von Implikationsformeln. Dann ist die Menge
der aus G logisch folgenden Fakten eindeutig bestimmt. Wir bezeichnen diese Menge mit
cons(G).
Die Semantik eines Datalog-Programms P kann nun als Funktion M [P ] dargestellt werden, die jeder Datenbank DB die Menge aller aus der Formel P ∗ ∧ DB ∗“ logisch folgenden
”
Fakten zuordnet:
M [P ] : DB −→ cons(P ∗ ∧ DB ∗ )
Hierdurch ist die Semantik von Datalog auf sehr einfache und äußerst elegante Weise
definiert.
Beispiel 5.1 Betrachten wir einen Ausschnitt der Datenbank, die wir für R EINE entworfen
haben, nämlich die Relation Lieferung aus Abbildung 4.1.
Der Ausdruck Lieferung(wien, wr. neustadt, 1, 30) ist ein Fakt, und die folgende logische Formel DB ∗ entspricht der Datenbank DB:
Lieferung(wien, wr.neustadt, 1, 30)
Lieferung(wien, st.pölten, 1, 60)
Lieferung(st.pölten, krems, 2, 70)
Lieferung(st.pölten, linz, 2, 80)
Lieferung(tulln, krems, 3, 30)
∧
∧
∧
∧
∧
Lieferung(wien, klosterneuburg, 1, 20)
Lieferung(wien, linz, 1, 100)
Lieferung(st.pölten, melk, 2, 60)
Lieferung(klosterneuburg, tulln, 3, 20)
Lieferung(wr.neustadt, eisenstadt, 4, 50)
Betrachten wir dazu das folgende Datalog-Programm P , das Paare von Orten berechnet,
die vom Lieferanten 2“ beliefert werden:
”
Liefert 2(X, Y) : − Lieferung(V1, X, 2, K1), Lieferung(V2, Y, 2, K2).
Dem Datalog-Programm P entspricht die folgende logische Formel P ∗ :
∀ X ∀ Y ∀ V1 ∀ V2 ∀ K1 ∀ K2 : ((Lieferung(V1, X, 2, K1) ∧ Lieferung(V2, Y, 2, K2)) ⇒
Liefert 2(X, Y)).
Es ist leicht zu sehen, dass aus der Konjunktion von DB ∗ und P ∗ außer den bereits in DB
enthaltenen Fakten die folgenden Fakten logisch ableitbar sind:
Liefert 2(krems, krems).
Liefert 2(krems, linz).
Liefert 2(krems, melk).
∧
∧
∧
∧
KAPITEL 5. DATALOG
Liefert
Liefert
Liefert
Liefert
Liefert
Liefert
5.5
2(linz, krems).
2(linz, linz).
2(linz, melk).
2(melk, krems).
2(melk, linz).
2(melk, melk).
Mit anderen Worten definiert das Datalog-Programm P eine neue Relation Liefert 2,
deren aktuelle Instanz folgendermaßen aussieht:
Liefert 2
Krems Melk
Krems Linz
Melk
Krems
Melk
Linz
Linz
Krems
Linz
Melk
5.3.2 Operationale Semantik von Datalog
Bei der operationalen Semantik werden die Datalog-Regeln als einfache Inferenzregeln aufgefasst, die es erlauben, bei Vorhandensein von Fakten, die im Rumpf auftreten, den Fakt im
Kopf einer Regel abzuleiten. So kann aus der Regel
Liefert(tulln, krems) : − Lieferung(tulln, krems, 3, 30).
und dem Fakt Lieferung(tulln, krems, 3, 30) der Fakt
Liefert(tulln, krems)
gewonnen werden. Eine Regel R, in der Variable auftreten, wird dabei als Repräsentation aller variablenfreien Regeln aufgefasst, die wir durch beliebiges Ersetzen der Variablen mit
Konstantensymbolen gewinnen können, die im Programm P oder in der Datenbank DB
vorkommen. Diese Regeln nennen wir Grundinstanzen von R bezüglich P und DB, kurz
Ground(R; P, DB).
Beispiel 5.2 Die allgemeine Regel
Liefert(X, Y) : −Lieferung(X, Y, L, K).
stellt alle Paare von Orten dar, zwischen denen es eine Belieferung gibt. Die Grundinstanzen dieser Regel bezüglich des Programms P und der Datenbank DB aus Beispiel 5.1 sind
(Konstantensymbole = 1, 2, 3, 4, wien, wr. neustadt, . . . , tulln, krems, eisenstadt,
30, 50, 60, 70, 80, 100.)
KAPITEL 5. DATALOG
5.6
Liefert(1, 1) : − Lieferung(1, 1, 1, 1).
(X = Y = L = K = 1)
Liefert(1, 1) : − Lieferung(1, 1, 1, 2).
(X = Y = L = 1, K = 2)
..
..
.
.
Liefert(tulln, krems) : − Lieferung(tulln, krems, 3, 30).
(X = tulln, Y = krems, L = 3, K = 30)
..
..
.
.
Insgesamt gibt es |Konstante||Variable| Grundinstanzen (von denen natürlich viele nie zur
Ableitung angewendet werden können, z.B. die erste Regel, weil der Fakt Lieferung(1, 1, 1, 1)
nicht vorhanden ist).
Das Resultat der Anwendung eines Datalog-Programms P auf eine Datenbank DB kann
nun über iteriertes Ableiten von Fakten bis zum Fixpunkt (keine neuen Fakten werden mehr
gewonnen) definiert werden. Dazu fassen wir im weiteren DB auch als Menge von Fakten
auf.
Wir definieren zunächst einen Operator TP (DB), der als Resultat die Erweiterung von
DB (als Faktenmenge) um alle Fakten liefert, die durch unmittelbare Anwendung einer Regel
R auf Fakten von DB abgeleitet werden können.
TP (DB) = DB ∪
[
{L0 | L0 : −L1 , . . . , Ln ∈ Ground(R; P, DB), L1 , . . . , Ln ∈ DB}
R∈P
Formal ist der Operator TP eine Abbildung, die jeder Faktenmenge DB eine Menge von
Fakten zuordnet.
Wiederholte Anwendung von Regeln wird nun durch die folgende Folge Γ ausgedrückt:
Γ = hDB, TP (DB), TP (TP (DB)) = TP2 (DB),
···
TP (TPi−1 (DB)) = TPi (DB), . . .i
TPi (DB) sind die Fakten, die wir in i Ableitungschritten aus DB erhalten haben. Diese
Menge wächst monoton mit der Zahl der Schritte i, d.h., es gilt TPi (DB) ⊆ TPi+1 (DB).
Die Folge Γ konvergiert endlich, d.h., es gibt ein n sodass TPm (DB) = TPn (DB) für alle
m ≥ n. (Dies muss gelten, weil es nur endlich viele Konstantensymbole gibt und die Menge
KAPITEL 5. DATALOG
5.7
der Grundinstanzen jeder Regel R in jedem Schritt i dieselbe ist, d.h., Ground(R; P, DB) =
Ground(R; P, TPi (DB)), i ≥ 1. Da mit jeder Grundinstanz höchstens ein Fakt abgeleitet
werden kann, und es insgesamt nur endlich viele Grundinstanzen gibt, können zu DB nur
endlich viele Fakten hinzukommen.)
Die Faktenmenge, zu der Γ konvergiert, wird mit TPω (DB) bezeichnet; sie ist das Resultat
der Anwendung von P auf DB. D.h., die operationale Semantik eines Datalog-Programms P
ordnet jeder Datenbank DB die Faktenmenge TPω (DB) zu:
O[P ] : DB −→ TPω (DB)
Wir können zeigen, dass die operationale Semantik mit der logischen Semantik übereinstimmt, und somit für jedes Programm P und jede Datenbank DB gilt:
M [P ](DB) = cons(P ∗ ∧ DB ∗ ) = O[P ](DB) = TPω (DB).
Anhand der operationalen Semantik können wir einen einfachen Algorithmus zur Auswertung eines Datalog-Programms P über einer Datenbank DB angeben.
Algorithmus IN F ER
INPUT: Datalog-Programm P , Datenbank DB
OUTPUT: TPω (DB) (= cons(P ∗ ∧ DB ∗ ))
S
Schritt 1. GP := R∈P Ground(R; P, DB), (* GP ist die Menge aller Grundinstanzen *)
Schritt 2. OLD := {}; N EW := DB;
Schritt 3. while N EW 6= OLD do begin
OLD := N EW ; N EW := T P (OLD);
end;
Schritt 4. output OLD.
Subroutine T P
INPUT: Faktenmenge D
OUTPUT: T P (D)
Schritt 1. F := D;
Schritt 2. for each rule L0 : −L1 , . . . , Ln in GP do
if L1 , . . . , Ln ∈ DB
then F := F ∪ { L0 };
Schritt 3. return F ;
(* end of T P *)
KAPITEL 5. DATALOG
5.8
Beispiel 5.3 Wir wenden das Programm P
Alle wege(X, Y) : − Liefert(X, Y).
Alle wege(X, Y) : − Liefert(X, Z), Alle wege(Z, Y).
zur Berechnung aller Wege auf die Datenbank DB aus Beispiel 5.2 an und verwenden dabei
den Algorithmus IN F ER.
Schritt 1. Bildung von GP
GP = {Alle wege(wien, wien) : − Liefert(wien, wien),
Alle wege(wien, linz) : − Liefert(wien, linz),
...
Alle wege(wien, wien) : − Liefert(wien, wien),
Alle wege(wien, wien),
Alle wege(wien, wien) : − Liefert(wien, linz),
Alle wege(linz, wien),
...
Alle wege(wien, linz) : − Liefert(wien, st.pölten),
Alle wege(st.pölten, linz),
. . .}.
(Insgesamt gibt es 92 + 93 = 810 Grundinstanzen. )
Schritt 2. OLD := {}, N EW := DB;
Schritt 3. Die Schleife wird ausgeführt. Vor dem ersten Durchlauf wird OLD zu DB; das
Resultat von T P (DB) ist die Menge DB ∪{Alle wege(X, Y) | Liefert(X, Y) ∈ DB},
da mit OLD = DB nur Grundinstanzen der ersten Regel von P angewendet werden
können.
Im zweiten Durchlauf ist das Resultat von T P (OLD):
OLD ∪ {Alle wege(wien, eisenstadt), Alle wege(wien, tulln),
Alle wege(wien, krems), Alle wege(wien, melk),
Alle wege(klosterneuburg, krems)}.
Es kommen also Fakten durch Anwendung von Grundinstanzen der zweiten Regel von
P hinzu.
Im dritten Durchlauf ist das Resultat von T P (OLD) gleich OLD, es können keine
neuen Fakten mehr abgeleitet werden.
KAPITEL 5. DATALOG
Liefert
Wien
Wien
Wien
Wien
St. Pölten
St. Pölten
St. Pölten
Klosterneuburg
Tulln
Wr. Neustadt
Wr. Neustadt
Klosterneuburg
St. Pölten
Linz
Krems
Melk
Linz
Tulln
Krems
Eisenstadt
5.9
Alle wege
Wien
Wien
Wien
Wien
St. Pölten
St. Pölten
St. Pölten
Klosterneuburg
Tulln
Wr. Neustadt
Wien
Wien
Wien
Wien
Klosterneuburg
Wr. Neustadt
Klosterneuburg
St. Pölten
Linz
Krems
Melk
Linz
Tulln
Krems
Eisenstadt
Eisenstadt
Tulln
Krems
Melk
Krems
Abbildung 5.1: Ergebnis der Anwendung von P auf Liefert
Schritt 4. Ausgabe von OLD. Das Resultat entspricht der Erweiterung der Datenbank DB
um die neue Tabelle Alle wege (siehe Abbildung 5.1).
Der Algorithmus IN F ER realisiert eine naive Methode zur Auswertung von DatalogProgrammen. Er terminiert bei einem festgehaltenen Programm P zwar immer in polynomieller Zeit, ist aber nicht optimal.
Es gibt bessere Algorithmen, auf die wir hier jedoch nicht eingehen.
5.4 Erweitertes Datalog mit Negation
Die Abfragesprache Datalog ist nicht relational vollständig: es ist nicht möglich, Differenzen
zwischen Relationen auszudrücken.
Durch die Einführung des Negationszeichens (non) in Regelrümpfen kann dieser Mangel
behoben werden. Bei der Verwendung der Negation müssen wir allerdings die folgende wichtige Einschränkung berücksichtigen, die auch bei der Verwendung von Negation in rekursivem
SQL Probleme bereitet:
Keine Relation darf (direkt oder indirekt) aufgrund ihrer eigenen Negation definiert werden.
Die Erfüllung dieser Bedingung kann einfach durch graphentheoretische Hilfsmittel geprüft werden.
KAPITEL 5. DATALOG
5.10
ehemann
verheiratet
*
junggeselle
mann
Abbildung 5.2: DEP (P ) für das Datalog-Programm aus Beispiel 5.4
5.4.1 Graphendarstellung
Sei P ein erweitertes Datalog-Programm, welches negierte Literale in Regelrümpfen enthält.
Sei DEP (P ) der gerichtete Graph, der für jede in P vorkommende Relation R genau
einen Knoten R enthält und dessen Kantenmenge wie folgt definiert ist:
Die Knoten R und S sind genau dann durch eine Kante R → S verbunden, wenn es eine
Regel in P gibt, in der die Relation R aufgrund der Relation S definiert wird (mit anderen
Worten, falls es eine Regel gibt, deren Kopfprädikat R ist, und die im Rumpf das Prädikat S
enthält).
Zusätzlich markieren wir jede Kante R → S von DEP (P ) mit einem Stern *“, falls es
”
eine Regel in P gibt, deren Kopfprädikat R ist, und die im Rumpf ein negiertes Literal mit
Prädikat S enthält.
Ein um Negation erweitertes Datalog-Programm P ist genau dann zulässig, wenn im Graph
DEP (P ) kein gerichteter Kreis vorkommt, der eine durch *“ markierte Kante enthält. Ein
”
solches Programm wird auch stratifiziert genannt, da es bezüglich der Negation in eine Hierarchie von Schichten (Strata) zerlegt werden kann.
Beispiel 5.4 Betrachten wir das folgende Datalog-Programm, das aus den Regeln
ehemann(X) : − mann(X), verheiratet(X).
junggeselle(X) : − mann(X), non ehemann(X).
besteht. Der dazugehörige Graph in Abbildung 5.2 besteht aus den Knoten ehemann,
junggeselle, mann und verheiratet. Von ehemann nach verheiratet und nach mann
gibt es aufgrund der ersten Regel Kanten. Aufgrund der zweiten Regel bekommen wir Kanten von junggeselle nach mann und nach ehemann, wobei letztere mit einem Stern gekennzeichnet wird.
Wie wir leicht erkennen können, ist dieses Programm stratifiziert.
Beispiel 5.5 Als nächstes ersetzen wir die erste Regel aus dem obigen Programm durch die
folgende:
ehemann(X) : − mann(X), non junggeselle(X).
Dadurch erhalten wir den Graphen in Abbildung 5.3 und ein nicht stratifiziertes DatalogProgramm.
KAPITEL 5. DATALOG
5.11
ehemann
*
junggeselle
*
mann
Abbildung 5.3: DEP (P ) für das Datalog-Programm aus Beispiel 5.5
5.4.2 Semanik von Datalog mit Negation
Um die Semantik von Datalog-Programmen mit Negation zu definieren, verwenden wir die
Darstellung eines Programmes P in Schichten. Eine Schicht besteht aus der größtmöglichen
Menge von Prädikaten, für die gilt:
1. Kommt ein Prädikat p im Kopf einer Regel vor, die im Rumpf ein negiertes Prädikat q
enthält, so ist p in einer höheren Schicht als q.
2. Kommt ein Prädikat p im Kopf einer Regel vor, die im Rumpf ein nicht negiertes
Prädikat q enthält, so ist p in einer mindestens so hohen Schicht wie q.
Wir können folgenden Algorithmus anwenden, um ein Programm in Schichten einzuteilen
und so herauszufinden, ob es stratifizierbar ist:
INPUT: Eine Menge von Datalog-Regeln.
OUTPUT: Eine Entscheidung, ob das Programm stratifiziert ist, und wenn ja, eine Einteilung
der Prädikate in Schichten.
Methode: Setzen wir die Schicht für alle Prädikate auf 1. Nun wiederholen wir die folgenden
Schritte für alle Prädikate p.
Wenn p im Kopf einer Regel vorkommt, die im Rumpf ein negiertes Prädikat q hat, p
aus Schicht i, q aus Schicht j, und falls i ≤ j, so setzen wir i := j + 1.
Wenn p im Kopf einer Regel vorkommt, die im Rumpf ein nicht negierten Prädikat q
hat, p aus Schicht i, q aus Schicht j und i < j ist, so setzen wir i := j.
Wenn wir einen stabilen Zustand erreichen und kein Prädikat mehr einer anderen Schicht
zugeordnet werden kann, so ist das Programm stratifiziert. Wird hingegen eine Schicht
n ≥ #p (Anzahl der Prädikate) erreicht, so ist das Programm nicht stratifiziert. 2
Beispiel 5.6 Die Relationen r und s seien vorgegeben. Betrachten wir nun das folgende
Datalog-Programm P , welches die neuen Relationen u, v und w definiert:
2
Die genaue Formulierung dieses Algorithmus ist in [Ullman, 1988 Bd. I] zu finden.
KAPITEL 5. DATALOG
5.12
*
w
u
v
w
Schicht 3
u
Schicht 2
*
s
r
v,r,s Schicht 1
Abbildung 5.4: DEP (P ) für das Datalog-Programm aus Beispiel 5.6
v(X, Y) : − r(X, X), r(Y, Y).
u(X, Y) : − s(X, Y), s(Y, Z), non v(X, Y).
w(X, Y) : − non u(X, Y), v(Y, X).
Wir stellen DEP (P ) in Abbildung 5.4 dar. Dieser Graph enthält keine Kreise, insbesondere keine Kreise, die eine mit *“ markierte Kante enthalten, daher ist P stratifizierbar. Die
”
drei Schichten von P sind in der obigen Abbildung angegeben.
Bei der Berechnung von Datalog-Anfragen mit Negation ist die Ordnung der Schichten zu
beachten: Zuerst werden alle Relationen der ersten Schicht berechnet, das sind alle Relationen, die ohne Verwendung von Negation berechnet werden. Diese Relationen gelten dann als
bekannte, unveränderbare Relationen. Danach werden alle Relationen der zweiten Schicht berechnet usw. Dadurch erhält Datalog mit Negation auch eine eindeutige Semantik. Im obigen
Beispiel bedeutet das, dass zuerst v aus r berechnet wird, dann u aus s und v und schließlich
w aus u und v.
Datalog mit Negation ist relational vollständig. Die Mengendifferenz d = r − s zweier
(z.B. zweistelliger) Relationen r und s können wir durch das folgende Programm ermitteln:
d(X, Y) : − r(X, Y), ¬ s(X, Y).
Beispiel 5.7 Betrachten wir den gerichteten Graphen, der in Abbildung 5.5 dargestellt ist. In
der Datenbank DB wird der Graph durch Fakten v(X), für jeden Knoten X, und e(X, Y), für
jede Kante zwischen X und Y repräsentiert. Nun wollen wir ein Datalog-Programm schreiben, das alle Paare (X, Y ) ausgibt, wo X eine Quelle, Y eine Senke ist, und die miteinander
verbunden sind, d.h., es gibt einen Weg von X nach Y . Als Lösung sollten sich die Paare
< a, e >, < a, f > und < d, e > ergeben, wie wir aus der Abbildung sehen können.
Als erstes definieren wir ein Prädikat p(X, Y), das wahr ist, wenn X eine Quelle und Y
eine Senke ist und es einen Weg von X nach Y gibt.
p(X, Y) : − quelle(X), senke(Y), weg(X, Y).
Das Prädikat weg können wir in zwei Schritten definieren; einerseits gibt es immer einen
trivialen Weg vom Knoten X zu sich selbst (Abbruchbedingung), andererseits gibt es einen
KAPITEL 5. DATALOG
5.13
p
a
b
f
c
e
quelle
senke
*
*
n quelle
weg
n senke
d
Abbildung 5.5: Graph aus Beispiel 5.7
Weg von X zu Y , wenn es eine Kante von X zu einem Zwischenknoten Z gibt, von dem aus
ein Weg nach Y führt.
weg(X, X) : − v(X).
weg(X, Y) : − e(X, Z), weg(Z, Y).
Wann ist ein Knoten X eine Quelle? Genau dann, wenn es keine Kante gibt, die nach X
führt. Wie können wir diesen Umstand in Datalog ausdrücken? Wenn wir es mit der Regel
quelle(X) : −non e(Y, X), v(X). versuchen, so wird diese Regel für alle jene Knoten X zu
true ausgewertet, für die es einen Knoten Y gibt, von dem es keine Kante nach X gibt, wie
z.B. für b, da es von d keine Kante nach b gibt. Wir wollen aber ausdrücken, dass dies für alle
Knoten Y gelten muss. Dafür verwenden wir ein Hilfsprädikat n quelle(X) : −e(Y, X)., das
wahr ist, wenn ein Knoten keine Quelle ist. In diesem Fall reicht nämlich das Auffinden einer
Kante nach X, um das Prädikat wahr zu machen. Die Quelle selbst definieren wir nun durch
quelle(X) : −v(X), ¬n quelle(X). Die Abfrage für die Senke ist analog. Wir erhalten das
folgende Programm:
p(X, Y) : − quelle(X), senke(Y), weg(X, Y).
weg(X, X) : − v(X).
weg(X, Y) : − e(X, Z), weg(Z, Y).
n quelle(X) : − e(Y, X).
quelle(X) : − v(X), non n quelle(X).
n senke(X) : − e(X, Y).
senke(X) : − v(X) non n senke(X).
In diesem Beispiel sehen wir noch eine weitere syntaktische Einschränkung von Datalog
mit Negation: alle Variablen, die in negierten Literalen vorkommen, müssen auch in einem
positiven Literal im Rumpf vorkommen (siehe die Regel für quelle).
5.14
KAPITEL 5. DATALOG
5.5 Übungsbeispiele
Übung 5.1 Prüfen Sie, ob das folgende Datalog-Programm stratfizierbar ist (Angabe des
Abhängigkeitsgraphen):
p(X,Y) :- q(Z), r(X,Z,Y), non h(Y).
h(X)
:- q(Y), non s(X,Y), w(X,Z).
s(X,Y) :- v(X), non p(X,Y), w(X,Y).
Hierbei sind r, q, v und w feststehende Datenbankrelationen.
Übung 5.2 In einer Datenbank für eine flexible Fertigungsstraße wird für jedes Produkt festgehalten, welche Teile des Produkts in welcher Anzahl von einer Maschine zu anderen Maschinen weitergeleitet werden (Zyklen treten nicht auf):
prod(ProdNo, PName)
maschine(MaschNo, MName)
band(ProdNo, VonMaschNo, NachMaschNo, TeilNo, Anzahl)
1. Schreiben Sie ein stratifiziertes Datalog-Programm, das die Relation v(P, M 1, M 2, T )
definiert, sodass hP, M 1, M 2, T i ∈ v genau dann gilt, wenn T Teil des Produktes P ist,
wobei T von Maschine M 1 zu Maschine M 2 - u. U. über andere Maschinen - fließt.
2. Formulieren Sie ein stratifiziertes DATALOG-Programm, das unter Verwendung von v
die Relation f(P, M 1, M 2, T ) definiert, wobei hP, M 1, M 2, T i ∈ f genau dann gilt,
wenn M 1 und M 2 Anfangs- bzw. Endpunkt des Flusses des Teils T des Produktes P
sind.
Übung 5.3 Schreiben Sie zu den Relationen aus Beispiel 4.1 in Kapitel 4 eine DatalogAbfrage, die in die zweistellige Relation m harmlos(ENR, SNR) den Erdstoß mit der größten
Stärke aufnimmt, der keine Opfer gefordert hat.
Übung 5.4 Schreiben Sie zu den Relationen aus Beispiel 4.2 in Kapitel 4 ein stratifiziertes
Datalog-Programm, das die Relation p(S1,S2) so berechnet, dass ein Tupel (s1, s2) genau
dann zu p gehört, wenn s1 und s2 einen gemeinsamen Lehrer haben, aber nie gemeinsam auf
der Bühne gestanden sind.
Übung 5.5 Schreiben Sie zu den Relationen aus Beispiel 4.3 in Kapitel 4 ein stratifiziertes
Datalog-Programm, das die Relation p(L) so berechnet, dass die Tupel in p genau die Nummern jener Lifte sind, von deren Bergstation aus es eine Schiabfahrt zur Station sudhaus“
”
gibt, aber keine, die nur über leichte Pisten führt.
KAPITEL 5. DATALOG
5.15
Übung 5.6 Schreiben Sie zu den Relationen aus Beispiel 4.4 in Kapitel 4 ein stratifiziertes
Datalog-Programm, das die Relation t frei so berechnet, dass die Tupel in t frei genau
jene Felder sind, für die gilt, dass in einer Entfernung bis zu 4500 m Tomaten (’TOM’) angebaut worden sind. Ein Built-in Prädikat sum(X, Y, Z) ≡ X = Y + Z steht zur Verfügung. (Ann.:
Jedes Feld kommt in weg vor.)
Übung 5.7 Schreiben Sie zu den Relationen Beispiel 4.5 in Kapitel 4 ein stratifiziertes DatalogProgramm, das die einstellige Relation l frei so berechnet, dass die Tupel in l frei genau
jene Glashäuser sind, für die gilt, dass in keinem Glashaus, das näher als 50 m liegt, Lilien
(’LILIE’) angebaut worden sind. Ein Built-in Prädikat sum(X, Y, Z) ≡ X = Y + Z steht zur
Verfügung. (Ann.: Jedes Glashaus kommt in weg vor.)
Übung 5.8 Schreiben Sie zu den Relationen aus Beispiel 4.6 in Kapitel 4 ein stratifiziertes
Datalog-Programm, das die Relation best ertrag(stelle, jahr, mname) so berechnet, dass die Tupel in ihr die ertragreichsten Besätze für Kaliber 6mm angeben, d.h., jene
Besätze, die bei der späteren Ernte den höchsten insgesamt erzielten Geldwert der Perlen von
Kaliber 6mm erbracht haben. Ein Built-in Prädikat prod(X, Y, Z) ≡ X = Y ∗ Z steht zur
Verfügung.
Übung 5.9 Schreiben Sie zu den Relationen aus Beispiel 3.9 eine Abfrage in stratifiziertem
Datalog, das im Prädikat inland(F,L) alle Fluglinien F angibt, die in einem Land L nur Inlandsflüge anbieten.
Übung 5.10 Schreiben Sie zu den Relationen aus Beispiel 3.10 eine Abfrage in stratifiziertem Datalog, die im Prädikat aq weg alle Wege zwischen je zwei Aquarien und die Entfernung dazu angibt. Achtung: der Weg kann auch über andere Käfige gehen. Ein Prädikat
sum(X,Y,Z) X = Y +Z ist vorhanden (ignorieren Sie das Problem von unendlichen Wegen
= Endlosschleife).
Übung 5.11 Schreiben Sie zu den Relationen aus Beispiel 3.11 eine Abfrage in stratifiziertem
Datalog, die im Prädikat wichtig(Z) den Namen der Zutaten zu den Produkten angibt, die
die geringste Haltbarkeitsdauer haben.
Übung 5.12 Schreiben Sie zu den Relationen aus Beispiel 3.12 eine Abfrage in stratifiziertem Datalog, die im Prädikat a(NAME) den Namen jener SchifahrerInnen angibt, die nur
Auslandssiege gefeiert haben.
Übung 5.13 Schreiben Sie zu den Relationen aus Beispiel 3.13 eine Abfrage in stratifiziertem
Datalog, die im Prädikat durchgehend(HNAME) alle jene Hotels angibt, bei denen alle
Zimmer im August dieses Jahres durchgehend belegt sind. Dazu benötigen Sie ein Prädikat
durch zimmer(HNAME,ZNR), das Ihnen alle Zimmer ausgibt, die durchgehend belegt
sind.
Übung 5.14 Schreiben Sie zu den Relationen aus Beispiel 3.14 eine Abfrage in stratifiziertem
Datalog, die im Prädikat durchgehend(KNR) die Kundennummer jener Kundinnen angibt,
die zwischen 1.1.1990 und 31.12.1997 immer mindestens ein Sparbuch an der Bank hatten.
5.16
KAPITEL 5. DATALOG
Kapitel 6
Funktionale Abh¨
angigkeiten
Bei der Modellierung einer Datenbank suchen wir eine Abbildung von Objekttypen der realen
Welt auf Relationenschemata R bzw. von Objektexemplaren der realen Welt auf Tupel t(R).
Dabei kommt es aber zu Einschränkungen (constraints) auf den Werten von R. Wir wollen die
möglichen R-Werte auf solche beschränken, die Abbild eines realen Objektes sein können.
Dabei können wir zwei Arten von Einschränkungen unterscheiden:
• Statische Einschränkungen beschreiben Zustände der Datenbank, z.B. muss es für jede Speise ein Restaurant geben, das diese Speise anbietet. Statische Einschränkungen müssen in allen Ausprägungen der Datenbank gültig sein und stellen eine spezielle
Form von Integritätsbedingungen dar.
• Dynamische Einschränkungen regeln die Übergänge zwischen zwei Datenbankzuständen,
z.B.: Das Gehalt eines Angestellten darf nur zunehmen“.
”
6.1 Definition von funktionalen Abh¨
angigkeiten
Wie wir in Kapitel 1 gesehen haben, sind zwei wichtige Gründe zur Einführung von Datenbanksystemen die Redundanz der Daten zu minimieren und ihre Verlässlichkeit zu maximieren. Wenn wir a priori bekannte Constraints mitmodellieren können, können wir Teile dieser
Aufgaben dem Datenbanksystem selber überlassen. Eine Möglichkeit, dieses a-priori-Wissen
zu formulieren, sind Datenabhängigkeiten. Eine wichtige Art von Datenabhängigkeiten sind
funktionale Abhängigkeiten. Weiters werden wir am Ende dieses Kapitels noch Inklusionsabhängigkeit besprechen.
Definition 6.1 Seien X und Y Teilmengen eines Relationenschemas R. Eine Relation r(R)
erfüllt (satisfies) die funktionale Abhängigkeit (functional dependency, FD) X → Y , geschrieben, wenn für jedes Paar von Tupeln u,v ∈ r(R) gilt: u(X) = v(X) ⇒ u(Y ) = v(Y ).
Formal:
1
6.2
KAPITEL 6. FUNKTIONALE ABHÄNGIGKEITEN
X → Y ⇔ ∀u, v ∈ r(R) : u(X) = v(X) ⇒ u(Y ) = v(Y )
Die funktionale Abhängigkeit ist also jene Eigenschaft zweier Attributmengen X und Y ,
dass X eindeutig die Werte von Y bestimmt. X kann dabei natürlich auch nur aus einem
einzigen Attribut bestehen. Ist eine funktionale Abhängigkeit als statische Einschränkung auf
einem Schema R definiert, so muss jede Relation r über R diese funktionale Abhängigkeit zu
jedem Zeitpunkt erfüllen.
Definition 6.2 Eine funktionale Abhängigkeit X → Y heißt trivial, wenn Y eine Teilmenge
von X ist.
X → Y trivial ⇔ Y ⊆ X
Beispiel 6.1 Welche funktionalen Abhängigkeiten sollten in unserer Relation Restaurant
gelten? Auf jeden Fall sollte die Restaurantnummer den Namen und die Adresse des Restaurants bestimmen. Wir erhalten:
f1 = rnr → name, adresse
Weiters sollen Name und Adresse zusammen die Restaurantnummer eindeutig bestimmen,
ebenso die Anzahl der Hauben und den Typ. Daraus erhalten wir:
f2 = name, adresse → rnr, haube, typ
Die Instanz der Relation Restaurant aus Abbildung 3.1 erfüllt sowohl f 1 als auch f2 .
Wollen wir aber das Tupel t mit t(rnr) = 10, t(name) = Green Cottage, t(adresse) = Kettenbrückengasse 3, 1050 Wien, t(haube) = 1 und t(typ) = österreichisch in die Datenbank
aufnehmen, so wird f2 verletzt.
Wir können nun die in Kapitel 3 eingeführten Begriffe Oberschlüssel“ und Schlüssel“
”
”
unter Zuhilfenahme des Konzepts der funktionalen Abhängigkeit wie folgt definieren:
Definition 6.3 Gegeben sei ein Relationenschema R. Eine Teilmenge X von Attributen in R
ist ein Oberschlüssel für R genau dann, wenn X die funktionale Abhängigkeit X → R erfüllt.
Formal:
X ⊆ R ist Oberschlüssel für R ⇔ X → R
Ist X minimal, d.h., gilt für jede Teilmenge Y ⊂ X, dass sie die funktionale Abhängigkeit
Y → R nicht erfüllt, so ist X ein Schlüssel. Formal:
X ist Schlüssel für R ⇔ (X → R und ∀A ⊂ X(X\A 6→ R))
KAPITEL 6. FUNKTIONALE ABHÄNGIGKEITEN
6.3
Diese Definitionen von Schlüssel und Oberschlüssel und jene in Kapitel 3 sind äquivalent.
6.2 Ableitungsregeln f ür funktionale Abha¨ngigkeiten
Wenn eine Menge von funktionalen Abhängigkeiten F gegeben ist, können wir uns die Frage
stellen, welche zusätzlichen Abhängigkeiten f durch F impliziert werden (F |= f ).
Beispiel 6.2 Betrachten wir nochmals die beiden funktionalen Abhängigkeiten f 1 = rnr →
name, adresse und f2 = name, adresse → rnr, haube, typ. Aufgrund von f 1 gilt: wenn
zwei Tupel dieselbe Restaurantnummer haben, so haben sie denselben Namen und dieselbe
Adresse. Aufgrund von f2 gilt: wenn zwei Restaurants denselben Namen und dieselbe Adresse haben, so haben sie auch denselben Typ und dieselbe Anzahl von Hauben. Wenn wir diese
beiden Bedingungen kombinieren, erhalten wir f3 = rnr → haube, typ.
Definition 6.4 Die Menge aller funktionalen Abhängigkeiten, die von F auf R impliziert
werden, heißt die Hülle (closure) von F auf R und wird als FR+ notiert. Ist die Attributmenge
R aus dem Kontext klar, wird nur F + geschrieben.
F + = {f |F |= f }
Definition 6.5 Unter der Hülle (closure) einer Menge von Attributen X ⊆ R, geschrieben als
XF+ (bzw. X + ) bezüglich F verstehen wir die Menge aller Attribute A, sodass X → A in F + .
XF+ = {A | X → A ∈ F + }
Die folgenden beiden Algorithmen bestimmen die Hülle einer Menge von Attributen
bezüglich einer Menge von funktionalen Abhängigkeiten (Algorithmus CLOSURE), bzw. testen, ob eine bestimmte funktionale Abhängigkeit in der Hülle einer Menge von gegebenen
funktionalen Abhängigkeiten enthalten ist (Algorithmus MEMBER).
Algorithmus CLOSURE
INPUT: X Attributmenge, F Menge von FD’s.
OUTPUT: XF+
X + := X
while ∃ (Y → Z) ∈ F mit Y ⊆ X + und Z 6⊆ X + do
X + := X + ∪ Z
end
return X +
KAPITEL 6. FUNKTIONALE ABHÄNGIGKEITEN
6.4
Algorithmus MEMBER
INPUT: X → Y FD, F Menge von FD’s.
OUTPUT: true, if F |= X → Y
false, if F 6|= X → Y
return (Y ⊆ CLOSURE(X, F ))
Wir können den Algorithmus CLOSURE verwenden, wenn wir bei einer gegebenen Menge von funktionalen Abhängigkeiten F über einem Relationenschema R feststellen wollen,
welche Attribute die Schlüssel zu R sind. X ist nämlich genau dann ein Schlüssel von R,
wenn XF+ = R und X minimal ist.
Beispiel 6.3 Betrachten wir nochmals die funktionalen Abhängigkeiten aus Beispiel 6.1.
F = {rnr → name, adresse
name, adresse → rnr, haube, typ}
Um die Hülle von rnr zu berechnen, verwenden wir den Algorithmus CLOSURE und
sehen, dass rnr ein Schlüssel der Relation Restaurant ist.
{rnr}+
F = {rnr, name, adresse, haube, typ}
Nun wollen wir überprüfen, ob f3 = rnr → haube, typ aus F folgt. Dazu verwenden
wir den Algorithmus MEMBER. Mit diesem wird überprüft, ob haube und typ in der Hülle
von rnr liegen. Da das der Fall ist, erhalten wir den Wert TRUE und f 3 folgt aus F.
Von Armstrong (1974) stammt die folgende Axiomatisierung. Sie gibt uns ein System von
Ableitungsregeln, mit deren Hilfe wir alle durch eine Menge F von funktionalen Abhängigkeiten implizierten funktionalen Abhängigkeiten f berechnen können. Wir können zeigen,
dass die Ableitungsregeln einerseits korrekt (sound) sind, d.h., sie leiten von F nur wirklich
gültige funktionale Abhängigkeiten ab (F ` f ⇒ F |= f ), und andererseits auch vollst ändig
(complete), d.h., sie erzeugen bei wiederholter Anwendung alle von F implizierten Abhängigkeiten (F |= f ⇒ F ` f ). Einen Beweis dazu finden wir in [Ullman, 1988 Bd. I] oder
[Maier, 1983].
Anmerkung:
• |=
...
Gültigkeitsbegriff, modelltheoretisch
• `
...
Ableitbarkeitsbegriff, beweistheoretisch
F1.: Reflexivität (reflexivity)
Y ⊆X ` X →Y
KAPITEL 6. FUNKTIONALE ABHÄNGIGKEITEN
6.5
F2.: Erweiterung (augmentation)
X → Y ` XZ → Y Z
F3.: Vereinigung (additivity)
X →Y,X →Z ` X →YZ
F4.: Zerlegung (projectivity)
X →YZ ` X →Y,X →Z
F5.: Transitivität (transitivity)
X →Y,Y →Z ` X →Z
F6.: Pseudotransitivität (pseudotransitivity)
X → Y , Y W → Z ` XW → Z
Anmerkung: Dieses System ist redundant, einige Regeln sind überflüssig. Z.B. folgt Regel
F5 unmittelbar aus Regel F6 (W = {}). Die Bestimmung einer nichtredundanten Axiomatisierung wird als Übungsaufgabe empfohlen.
6.3 Äquivalenz von Systemen von funktionalen Abha¨ngigkeiten
In diesem Abschnitt befassen wir uns mit dem Versuch, eine möglichst kompakte Darstellung
für funktionale Abhängigkeiten zu finden. Diese ist notwendig, da wir etwa im Algorithmus
MEMBER gesehen haben, dass die Laufzeit von der Anzahl der funktionalen Abhängigkeiten
im Input abhängt. Eine kleinere Menge von funktionalen Abhängigkeiten bringt also besseres
Laufzeitverhalten des Algorithmus. Da funktionale Abhängigkeiten in Datenbanken dazu verwendet werden, Konsistenz und Korrektheit zu gewährleisten, bedeuten weniger funktionale
Abhängigkeiten geringeren Speicherplatzverbrauch und weniger Tests, wenn die Datenbank
modifiziert wird. Bei der Überführung eines Relationenschemas in dritte Normalform (siehe
Kapitel 7.4) ist es ebenfalls notwendig, dass wir von einer möglichst geringen Menge von
funktionalen Abhängigkeiten ausgehen.
Definition 6.6 Zwei Mengen funktionaler Abhängigkeiten G und F sind äquivalent, geschrieben als G ≡ F , wenn sie dieselbe Hülle besitzen. F heißt dann Überdeckung (cover)
von G.
G ≡ F ⇔ G+ = F +
Um feststellen zu können, ob F ≡ G, gehen wir wie folgt vor:
1. prüfe für alle g ∈ G, ob F |= g,
KAPITEL 6. FUNKTIONALE ABHÄNGIGKEITEN
6.6
2. prüfe für alle f ∈ F , ob G |= f .
Beispiel 6.4 Seien F und G die zwei unten angegebenen Mengen funktionaler Abhängigkeiten.
Gilt F ≡ G ?
G = {rnr → name, adresse
name, adresse → rnr, haube, typ}
F = {rnr → name, adresse
name, adresse → rnr, haube, typ
rnr → haube
adresse, haube → haube}
1. prüfe für alle g ∈ G, ob F |= g. Antwort: ja, trivialerweise (G ⊆ F ).
2. prüfe für alle f ∈ F , ob G |= f . Die ersten beiden funktionalen Abhängigkeiten sind
trivialerweise in G enthalten. Für f3 müssen wir wieder die Hülle von rnr in G betrachten, die haube enthält. Daher gilt G |= f3 . Für f4 bilden wir die Hülle von
{adresse, haube} bezüglich G, haube ist trivialerweise enthalten. Daher gilt G |= f 4 .
Also haben wir insgesamt erhalten dass F ≡ G.
Wir konnten von zwei verschiedenen Mengen F und G von funktionalen Abhängigkeiten
zeigen, dass sie dieselbe Menge von funktionalen Abhängigkeiten ableiten. Interessiert sind
wir nun an einer möglichst kleinen Menge G von funktionalen Abhängigkeiten, die zu einer
gegebenen Menge F äquivalent ist. Dazu benötigen wir die folgenden Definitionen.
Definition 6.7 Eine Menge funktionaler Abhängigkeiten F heißt kanonisch, wenn für jede
FD f ∈ F die rechte Seite nur aus einem Attribut besteht.
Aufgrund der Regel F4 der Armstrong Axiome können wir jede nicht-kanonische funktionale Abhängigkeit in mehrere kanonische zerlegen.
Definition 6.8 Eine Menge funktionaler Abhängigkeiten F heißt linksreduziert, wenn sie keine FD f mit überflüssigen Attributen auf der linken Seite enthält.
B ist überflüssig in XBY → A bzgl. F ⇔ (F \{XBY → A}) ∪ {XY → A} ≡ F.
Definition 6.9 Eine Menge funktionaler Abhängigkeiten F heißt nicht-redundant, wenn es
keine FD f in F gibt, sodass F \{f } äquivalent zu F ist.
f redundant in F ⇔ F \{f } ≡ F.
KAPITEL 6. FUNKTIONALE ABHÄNGIGKEITEN
6.7
Definition 6.10 Eine Menge funktionaler Abhängigkeiten F heißt minimal, wenn sie kanonisch, linksreduziert und nicht-redundant ist.
Wir wollen nun zu einer gegebenen Menge von funktionalen Abhängigkeiten eine äquivalente Menge zu finden, die minimal ist. Dass dies immer geht, sagt uns der folgende Satz:
Theorem 6.1 Zu jeder Menge funktionaler Abhängigkeiten F gibt es eine minimale Überdeckung. (Beweis in [Ullman, 1988 Bd. I])
Im allgemeinen ist eine minimale Überdeckung nicht eindeutig, es kann mehrere minimale
Überdeckungen geben. Eine minimale Überdeckung kann nach dem folgenden Algorithmus
berechnet werden.
Algorithmus MINCOVER
INPUT: Menge F von FD’s
OUTPUT: Minimale Überdeckung G für F
1. Zerlegung aller funktionalen Abhängigkeiten in kanonische:
G := {X → Ai | X → A1 . . . Ak ∈ F };
2. Entfernen überflüssiger Attribute (Linksreduziertheit):
Für jede FD XB → Y ∈ G :
X → Y ∈ G+ ⇒ G := (G \ {XB → Y }) ∪ {X → Y };
3. Entfernen aller redundanten Abhängigkeiten X → Y :
Für jede FD X → Y ∈ G :
X → Y ∈ (G \ {X → Y })+ ⇒ G := G \ {X → Y };
4. output G.
Beispiel 6.5 Betrachten wir die folgende Menge G von funktionalen Abhängigkeiten. Um
eine minimale Überdeckung zu finden, führen wir im ersten Schritt G über in eine kanonische
Form G0 . Im zweiten Schritt testen wir alle funktionalen Abhängigkeiten auf Linksreduziertheit. Im dritten und letzten Schritt berechnen wir G000 , das nur noch aus nichtredundanten
funktionalen Abhängigkeiten bestehen soll. Dieser Test wird mit jeder FD durchgeführt.
G = {rnr → name, adresse
name, adresse → rnr, haube, typ
rnr, name → haube
adresse, haube → haube}
KAPITEL 6. FUNKTIONALE ABHÄNGIGKEITEN
6.8
1. Berechnung von G0 .
G0 = {rnr → name
rnr → adresse
name, adresse → rnr
name, adresse → haube
name, adresse → typ
rnr, name → haube
adresse, haube → haube}
2. Berechnung von G00 . g3 , g4 , g5 und g7 haben jeweils zwei Attribute auf der linken Seite. Um zu überprüfen, ob wir eines der beiden Attribute streichen können, müssen wir
überprüfen, ob das Attribut auf der rechten Seite in der Hülle eines der beiden Attribute
+
auf der linken Seite bezüglich G liegt. Da name +
G = {name}, adresse G = {adresse}
können wir weder name noch adresse aus g3 , g4 und g5 streichen und auch nicht haube
aus g7 . Allerdings ist haube +
G = {haube} und daher können wir adresse aus g 7 streichen. Aufgrund ähnlicher Überlegungen können wir g6 links-reduzieren.
G00 = {rnr → name
rnr → adresse
name, adresse → rnr
name, adresse → haube
name, adresse → typ
rnr → haube
haube → haube}
3. Berechnung von G000 . Bei der Überprüfung auf redundante Abhängigkeiten müssen wir
für jede Abhängigkeit X → Y testen, ob das Attribut Y auf der rechten Seite in der
Hülle der Attribute X der linken Seite bezüglich G\(X → Y ) liegt.
Da name nicht in rnr+
G00 \{rnr→name} liegt, ist g1 nicht redundant. Gleiches gilt auch für
g2 , g3 und g5 .
Für g4 gilt: haube liegt in name, adresse +
G00 \{name,adresse→haube} und für g6 gilt: haube
+
liegt in rnrG00 \{rnr→haube} . Sobald wir eine dieser beiden redundanten Abhängigkeiten
entfernen, ist die andere jedoch nicht mehr redundant, wir müssen uns also für eine der
beiden entscheiden.
Für g7 liegt haube ebenfalls in haube+
G00 \{haube→haube} und ist trivialerweise redundant.
KAPITEL 6. FUNKTIONALE ABHÄNGIGKEITEN
6.9
4. Eine minimale Überdeckung für G ist somit:
G000 = {rnr → name
rnr → adresse
name, adresse → rnr
name, adresse → haube
name, adresse → typ
6.4 Inklusionsabh¨
angigkeiten
Eine weitere besondere Form von statischen Integritätsbedingungen sind Inklusionsabhängigkeiten. Sie dienen vor allem zur Gewährleistung der referentiellen Integrität. Dies ist jene
Eigenschaft, dass eine Datenbank keine Fremdschlüssel enthält, deren Werte keine Entsprechung mit einem Schlüsselwert haben. Angewandt auf unsere Relationen Restaurant und
Speise bedeutet das, dass es keine Speise geben darf, die im Attribut rnr einen Wert stehen
hat, der keine Entsprechung in der Relation Restaurant hat.
6.4.1 Definition von Inklusionsabhängigkeiten
Eine Inklusionsabhängigkeit (IA) wird als Integritätsbedingung zu zwei Relationenschemata
R und S als R[X] ⊆ S[Y ] geschrieben, wobei X und Y Sequenzen von Attributen von R
bzw. S sind und | X | = | Y | gilt. Zwei Relationen r(R) und s(S) erfüllen die Inklusionsabhängigkeit R[X] ⊆ S[Y ], falls πX (r) eine Teilmenge von πY (s) ist.
Eine Inklusionsabhängigkeit R[X] ⊆ S[Y ] heißt schlüsselbasiert, wenn Y ein Schlüssel
für S ist. Schlüsselbasierte Inklusionsabhängigkeiten dienen zur Gewährleistung der referentiellen Integrität. Ist auf einer Attributmenge X eines Relationschemas R eine schlüsselbasierte Inklusionsabhängigkeit R[X] ⊆ S[Y ] definiert, so heißt X Fremdschl üssel und die
Inklusionsabhängigkeit Fremdschlüsselbedingung.
Beispiel 6.6 Betrachten wir die Relationenschemata Restaurant = {rnr, name, adresse,
haube, typ} und Speise = {name, preis, rnr} aus Beispiel 3.1. Dann ist Speise[rnr] ⊆
Restaurant[rnr] eine Inklusionsabhängigkeit; da das Attribut rnr für Restaurant ein Schlüssel ist, ist das Attribut rnr ein Fremdschlüssel des Relationenschemas Speise.
6.4.2 Ableitungsregeln für Inklusionsabhängigkeiten
Casanova et. al. haben 1984 eine Reihe von Ableitungsregeln für Inklusionsabhängigkeiten
vorgestellt. Diese sind:
6.10
KAPITEL 6. FUNKTIONALE ABHÄNGIGKEITEN
I1: Reflexivität:
X Attributsequenz von R ` R[X] ⊆ R[X]
I2: Projektion und Permutation:
R[X1 . . . Xn ] ⊆ S[Y1 . . . Yn ] ` R[Xk . . . Xm ] ⊆ S[Yk . . . Ym ], wobei k . . . m eine Sequenz
von Indizes aus dem Bereich 1 . . . n ist
I3: Transitivität:
R[X] ⊆ S[Y ], S[Y ] ⊆ T [Z] ` R[X] ⊆ T [Z].
KAPITEL 6. FUNKTIONALE ABHÄNGIGKEITEN
6.11
6.5 Übungsbeispiele
Übung 6.1 F = {AB → C, B → D, CD → E, CE → GH, G → A}
• Berechnen Sie AB + .
• Gilt AB → E ?
• Gilt BG → C ?
Übung 6.2 Gegeben ist die Relation r(R):
r (A
a1
a1
a2
a2
a3
B
b1
b2
b1
b1
b2
C
c1
c2
c3
c4
c5
D
d1
d2
d3
d3
d1
E)
e1
e1
e1
e1
e1
Geben Sie an, welche der folgenden Abhängigkeiten r erfüllt:
1. A → D
2. AB → D
3. C → BDE
4. E → A
5. A → E
6. A → BC
Übung 6.3 F = {AB → C, DE → AB, A → D, B → E, DE → C, AD → G}
Geben Sie F in kanonischer Darstellung an.
1. (AB)+ = ?
2. (DE)+ = ?
3. Gilt AB ≡ DE ?
4. Gilt AB → CDG ?
5. Ist DE → C in F redundant? (Warum? Warum nicht?)
KAPITEL 6. FUNKTIONALE ABHÄNGIGKEITEN
6.12
6. Ist D in AD → G überflüssig? (Warum? Warum nicht?) Geben Sie eine minimale
Überdeckung von F an.
Übung 6.4 F = {AB → CD, D → E, EC → G, AH → GI, AB → E}
1. Geben Sie F in kanonischer Darstellung an.
2. Berechnen Sie (AB)+ .
3. Ist AB → E in F redundant? (Warum? Warum nicht?)
Übung 6.5 Berechnen Sie die Hüllen der linken Seiten von FDs aus F :
F = {A → D, AB → DE, CE → G, E → AH}.
Berechnen Sie weiters (AC)+ , (BC)+ und (AE)+ .
Übung 6.6 Sind folgende Mengen von funktionalen Abhängigkeiten äquivalent?
F = {A → BDGH, B → AC, C → DE, D → CGH, H → G}
G = {A → B, B → AC, C → D, D → CEH, H → G}
Übung 6.7 Sind I bzw. I 0 Überdeckungen bzw. nicht redundante Überdeckungen von H?
H = {AB → C, A → B, B → C, A → C}
I = {AB → C, A → B, B → C}
I 0 = {A → B, B → C}
Übung 6.8 Streichen Sie redundante FDs aus Fi :
F1
F2
F3
F4
F5
= {A → BC, B → C}
= {A → BD, B → C, C → D}
= {AB → CD, D → E, EC → G, AH → GI, AB → E}
= {AB → CDEF, AC → B, AD → B}
= {A → BCGH, BC → EGH, B → E, G → H, BE → DH}
Übung 6.9 Erzeugen Sie eine minimale Überdeckung Gi für:
F1
F2
F3
F4
F5
F6
= {A → BC, B → C, AB → D}
= {A → BCE, AB → DE, BI → J}
= {A → BCGH, BC → EGH, G → H, BE → DH}
= {A → C, AB → C, C → DI, CD → I}
= {CD → BE, CB → I, BE → I, CB → E}
= {AB → CD, B → D, CD → A, C → E, EC → AB}
Übung 6.10 Gegeben ist die Menge der funktionalen Abhängigkeiten
F = {AB → C, C → E, EC → D, HE → ABE, AB → D}.
KAPITEL 6. FUNKTIONALE ABHÄNGIGKEITEN
6.13
1. Geben Sie F in kanonischer Darstellung an.
2. Berechnen Sie (AB)+ .
3. Ist AB → D in F redundant? (Warum? Warum nicht?)
Übung 6.11 Gegeben sind die Relationen r(ABCE) und s(ABCF ). Angenommen, r erfüllt
die FD A → B und s erfüllt die FD B → C, gilt dann im allgemeinen:
1. r ./ s erfüllt A → B ?
2. r ./ s erfüllt B → C ?
3. r ./ s erfüllt A → C ?
4. πAC (r) × πBE (r) erfüllt A → B ?
5. πAB (r) ∪ πAB (s) erfüllt A → B ?
6. πAB (r) ∩ πAB (s) erfüllt A → B ?
Übung 6.12 Es seien p, q und r Instanzen von Relationenschemata P, Q und R, die bestimmte
funktionelle Abhängigkeiten erfüllen.
Bestimmen Sie, ob auf den folgenden abgeleiteten Relationen die angeführten funktionellen Abhängigkeiten sicher gelten:
1. p(ABCDE), q(BCDF ), p |= A → B, q |= BC → D;
Gilt p ./ q |= A → D ?
2. p(ABCD),q(ABCD), p |= A → BC, q |= A → C;
Gilt p ∪ q |= A → C ?
3. p(ABCDE), q(ABCDF ), p |= A → CD, q |= CA → D;
Gilt p n q |= AC → D ?
4. p(ABCD), q(ABCD), p |= A → B, q |= A → C, q |= CD → B;
Gilt p ∩ q |= AD → B ?
5. p(ABCDE), q(DE), p |= ABE → C, q |= D → E;
Gilt p ÷ q |= AB → C ?
6. p(ABC), q(CD), p |= A → C, q |= D → C;
Gilt σB=5 p ./ q |= AD → B
KAPITEL 6. FUNKTIONALE ABHÄNGIGKEITEN
6.14
7. p(ABCD), q(AB), r(CD), p |= A → BD, q |= A → B, r |= C → D;
Gilt p − (q × r) |= A → BD ?
Übung 6.13 Gegeben seien R = {ABC} und F = {A → B, B → C}. Bestimmen Sie
durch Anwendung der Armstrongaxiome alle nichttrivialen von F implizierten funktionalen
Abhängigkeiten (Darstellung in kanonischer Form).
Übung 6.14 Gegeben ist F = {X → Y, XZ → Y, Y → V W, Y V → W }. Geben Sie eine
minimale Überdeckung G für F an.
Übung 6.15 Gegeben ist F = {A → BC, AD → E, CD → E, E → AC}. Geben Sie eine
minimale Überdeckung G für F an.
Übung 6.16 Gegeben ist ein Relationenschema R und eine Menge von funktionalen Abängigkeiten F. Gegeben sind außerdem Attributmengen X und Y , wobei X ⊆ R, Y ⊆ R. X sei
ein Schlüssel unter F und Y ∪ X = ∅. Welche der folgenden Aussagen ist richtig, falsch bzw.
kann sein (mit Begründung)?
X+ = R
Y+ = R
X+ = F +
X → Y ∈ F+
X →Y ∈F
Kapitel 7
Normalformen
Die Kriterien eines guten Datenbankentwurfs sind einerseits möglichst geringe Redundanz,
andererseits die Vermeidung von Einfüge-, Lösch- und Änderungsanomalien. Um Redundanzen und Anomalien zu vermeiden, führen wir den Begriff der Normalformen für Datenbankschemata ein. Eine Normalform ist eine Einschränkung auf dem Datenbankschema, die uns
hilft, unerwünschte Eigenschaften der Datenbank zu verhindern. Ziel der Normalisierung ist
ein Entwurf, der mindestens die Dritte Normalform (3NF) erfüllt. Erste und Zweite Normalform sind nur ein Zwischenschritt in dieser Entwicklung, sie helfen jedoch beim Verständnis
der schrittweisen Verbesserung des Entwurfs.
7.1 Erste und Zweite Normalform
Ein Relationenschema R ist in 1. Normalform (1NF), wenn die Wertebereiche aller Attribute
von R atomar sind.
1NF ⇔ Wertebereiche atomar
Ob ein Wertebereich atomar ist oder nicht, ist allerdings nicht immer ganz einfach zu
sagen.
Beispiel 7.1 Wenn wir das Schema Mitarbeiter(svnr, nname, vname, adresse, geburt)
betrachten und das Geburtsdatum immer nur als ganzen Wert verwenden, ist das Schema
in 1. Normalform. Sobald wir aber nur auf Teile des Datums zugreifen wollen, ist es nicht
mehr in 1. Normalform. Angenommen wir wollen das Attribut sternzeichen hinzufügen, so
erhalten wir die FD geburt → sternzeichen, die es erlaubt, dass Personen, die am selben
Tag in verschiedenen Jahren geboren sind, ein unterschiedliches Sternzeichen haben. Spalten
wir den Datumswert in drei Attribute tag, monat und jahr auf, so können wir die gewünschte
FD mit tag, monat → sternzeichen angeben.
Die 1. Normalform genügt aber nicht, um die oben angegebenen Entwurfskriterien zu
erfüllen. Um Redundanzen und Datenanomalien zu vermeiden, benötigen wir die 2. und 3.
Normalform.
1
KAPITEL 7. NORMALFORMEN
7.2
Beispiel 7.2 Für die Verwaltung der Getränke in R EINE müssen wir wissen, welche Getränke
wo gelagert sind, um sie bei einer Bestellung aus einem geeigneten Lager heranzuschaffen.
Diese Informationen gewinnen wir aus den Relationenschemata Getränke(gnr, name,hersteller)
und Lager(gnr, lnr, menge, adresse), wobei das erste die Informationen zu den Getränken,
das zweite zum Lagerort der Getränke liefert.
Betrachten wir folgende Relation für Lager:
Lager
gnr lnr menge
101
1
25
078
2
340
078
1
56
204
3
3000
adresse
Wiener Straße 88, 2352 Gumpoldskirchen
Lenz Moser-Str. 1, 3495 Rohrendorf bei Krems
Wiener Straße 88, 2352 Gumpoldskirchen
Billrothstr. 51, 1190 Wien
Wie wir leicht erkennen können, ist die Relation in erster Normalform. Angenommen, wir
verändern die Lageradresse in der ersten Zeile. Die Redundanz in dieser Spalte bewirkt eine
Anomalie nach Adressänderung, da nun das Lager mit der Nummer 1 zwei unterschiedliche
Adressen hat.
Lager
gnr lnr menge
101
1
25
078
2
340
078
1
56
204
3
3000
adresse
Neustiftg 51, 2352 Gumpoldskirchen
Lenz Moser-Str. 1, 3495 Rohrendorf bei Krems
Wiener Straße 88, 2352 Gumpoldskirchen
Billrothstr. 51, 1190 Wien
Oder wir löschen das Getränk mit gnr = 204 aus dem Lager 3. Dadurch geht uns die ganze
Zeile verloren, unter anderem auch die Information über die Adresse dieses Lagers.
Lager
gnr lnr menge
101
1
25
078
2
340
078
1
56
204
3
3000
adresse
Wiener Straße 88, 2352 Gumpoldskirchen
Lenz Moser-Str. 1, 3495 Rohrendorf bei Krems
Wiener Straße 88, 2352 Gumpoldskirchen
Billrothstr. 51, 1190 Wien
Diese Anomalien können behoben werden, wenn wir das Schema in zwei Schemata unterteilen, nämlich in Vorrat(gnr, lnr, menge) und Lager(lnr, adresse). Formal gesehen
kommen wir auf die neue Einteilung, wenn wir die funktionalen Abhängigkeiten betrachten,
die auf dem ursprünglichen Schema gelten: gnr, lnr → menge und lnr → adresse. Wenn
wir die Definition der 2. Normalform betrachten, so werden wir sehen, dass die 2. Normalform durch diese Aufteilung des Schemas in zwei Subschemata erfüllt ist. Dazu benötigen
wir jedoch erst folgende Definition:
KAPITEL 7. NORMALFORMEN
7.3
Definition 7.1 Ein Attribut A heißt prim in einem Relationenschema R, wenn es in mindestens einem Schlüssel von R enthalten ist, nichtprim, wenn es in keinem Schlüssel enthalten
ist. Formal:
A ist prim ⇔ ∃X : X ist Schlüssel ∧ A ∈ X
Definition 7.2 Ein Relationenschema R in 1NF ist in 2. Normalform (2NF), genau dann wenn
für alle nichttrivialen funktionalen Abhängigkeiten X → A auf R gilt: entweder ist X keine
echte Teilmenge eines Schlüssels oder A ist ein primes Attribut. Formal:
2NF ⇔ X → A ⇒ (A ∈ X ∨ X 6⊂ K, K ein Schlüssel von R ∨ A prim ).
Beispiel 7.3 Die primen Attribute der ursprünglichen Relation Lager sind gnr und lnr. Die
funktionale Abhängigkeit gnr, lnr → menge verletzt die 2NF nicht, lnr → adresse jedoch
schon, da lnr ein Teilschlüssel ist. Daher müssen wir durch Aufteilung des Schemas Lager
in zwei Subschemata Vorrat und Lager die 2NF wieder herstellen.
Vorrat
gnr lnr
101
1
078
2
078
1
204
3
menge
25
340
56
3000
Lager
lnr adresse
1 Wiener Straße 88, 2352 Gumpoldskirchen
2 Lenz Moser-Str. 1, 3495 Rohrendorf bei Krems
3 Billrothstr. 51, 1190 Wien
Bei der Verlegung von Lager 1 auf eine neue Adresse haben wir nun keine Probleme mehr,
die Adresse bleibt konsistent. Auch das Löschen von Getränk 204 aus Lager 3 bringt keine
Schwierigkeiten mit sich.
Wie das Beispiel im nächsten Abschnitt zeigt, reicht die 2. Normalform jedoch nicht, um
Anomalien auszuschließen und ist deshalb nur von historischem Interesse.
7.2 Die Dritte Normalform
Beispiel 7.4 Betrachten wir ein Relationenschema, das festlegt, für welchen Händler und in
welchem Lager die Lagerarbeiter arbeiten: Einsatz(svnr, lnr, firma). Wenn wir annehmen, dass jedes Lager genau einem Händler zugeordnet ist, bekommen wir die folgende
Menge funktionaler Abhängigkeiten:
F = {svnr → lnr firma, lnr → firma}
Die Relation ist in 2. Normalform, denn der Schlüssel der Relation ist svnr. Die Attribute
lnr und firma sind beide nichtprim, da sie keine Schlüsselattribute sind.
KAPITEL 7. NORMALFORMEN
7.4
Einsatz
svnr
lnr
2435020466
1
8450720768
2
5467151171
3
9876020170
2
firma
Weinbauer G. Grill
Weinkellerei Lenz Moser
Kattus Johann GmbH, Hochriegl Sekt
Weinkellerei Lenz Moser
Wollen wir das Lager 2 einem anderen Händler zuweisen oder den Angestellten 2435020466
entfernen, so erhalten wir dieselben Anomalien wie im vorigen Abschnitt.
Einsatz
svnr
lnr
2435020466
1
8450720768
2
5467151171
3
9876020170
2
firma
Weinbauer G. Grill
Weingut-Kellerei Müllner Johann
Kattus Johann GmbH, Hochriegl Sekt
Weinkellerei Lenz Moser
Auch hier hilft wieder die Zerlegung in zwei Relationen um die Anomalien zu vermeiden.
Einsatz
svnr
lnr
2435020466
1
8450720768
2
5467151171
3
9876020170
2
Firma
lnr firma
1 Weinbauer G. Grill
2 Weinkellerei Lenz Moser
3 Kattus Johann GmbH, Hochriegl Sekt
Definition 7.3 Ein Relationenschema R in 1NF ist in 3. Normalform (3NF), wenn für alle
nichttrivialen funktionalen Abhängigkeiten X → A auf R gilt: entweder ist X ein Oberschlüssel, oder A ist ein primes Attribut. Formal:
3NF ⇔ X → A ⇒ (A ∈ X ∨ X → R ∨ A prim).
Äquivalent zu dieser Definition ist auch die folgende Charakterisierung:
Theorem 7.1 Ein Relationenschema R in 1NF ist in 3. Normalform genau dann, wenn kein
nichtprimes Attribut von einem Schlüssel in R transitiv abhängt (i.e. aufgrund der Transitivitätsregel aus einem Schlüssel ableitbar ist). Formal:
3NF ⇔ (A nichtprim ⇒ Schlüssel → A nicht transitiv).
Zwischen den einzelnen Normalformen gilt die folgende Beziehung:
3N F ⇒ 2N F ⇒ 1N F
KAPITEL 7. NORMALFORMEN
7.5
7.3 Die Boyce-Codd Normalform
Die strengste Normalform ist die Boyce-Codd-Normalform.
Definition 7.4 Ein Relationenschema R in 1NF ist in Boyce-Codd Normalform (BCNF) genau dann, wenn für alle nichttrivialen funktionalen Abhängigkeiten X → A auf R gilt: X ist
ein Oberschlüssel. Formal:
BCN F ⇔ X → A ⇒ (A ∈ X ∨ X → R).
Äquivalent zu dieser Definition ist auch die folgende Charakterisierung:
Theorem 7.2 Ein Relationenschema R in 1NF ist in Boyce-Codd Normalform genau dann,
wenn kein Attribut transitiv von einem Schlüssel abhängt.
BCN F ⇔ X → A ⇒ X → R ∨ A ∈ X
Beispiel 7.5 Betrachten wir das Relationenschema R(übung, student, tutor) mit der Menge funktionaler Abhängigkeiten F = {student, übung → tutor, tutor → übung}, die
besagen, dass ein Student bei einer Übung genau einem Tutor zugeordnet ist und dass ein Tutor genau einer Übung zugeordnet ist. Die Abhängigkeit tutor → übung verletzt die BCNF
(aber nicht die 3NF).
Wenn wir das Schema R zerlegen in R1 = (student, tutor) und R2 = (tutor, übung),
so haben wir zwei neue Schemata R1 , R2 , die in BCNF sind.
Die BCNF hat als einzige Normalform folgende Eigenschaft:
Theorem 7.3 Ein Schema ist in BCNF ⇔ das Schema ist redundanzfrei (bez üglich der vorgestellten Redundanzen).
Das bedeutet, dass keine Art von Anomalien beim Löschen oder Updaten auftritt. In der
Praxis ist dennoch die 3NF wesentlich weiter verbreitet, da nur in der 3NF eine verbund- und
abhängigkeitstreue Zerlegung (siehe Abschnitt 7.4) möglich ist.
7.4 Zerlegungen von Relationenschemata
Wie wir gesehen haben, kommt es beim Datenbankentwurf darauf an, die Relationenschemata in Normalform zu bringen, um ungewünschte Nebeneffekte zu vermeiden. Dazu ist es
notwendig, ein Relationenschema R nach seinen funktionalen Abhängigkeiten zu zerlegen.
Bis jetzt haben wir diese Zerlegung immer intuitiv vorgenommen. Im Allgemeinen ist es
allerdings nicht so einfach. In diesem Abschnitt wird die dazu nötige Theorie vorgestellt.
Im Folgenden wollen wir annehmen, dass ein Relationenschema R ein Paar (S, F ) ist mit
den Komponenten
KAPITEL 7. NORMALFORMEN
7.6
• S: eine Menge von Attributen
• F : eine Menge funktionaler Abhängigkeiten über S.
Definition 7.5 Ein Relationales Datenbankschema R ist eine Menge von Relationenschemata: R = {R1 , R2 , . . . , Rn }. Dieses Datenbankschema R ist in 3NF bzw. BCNF, wenn jedes
Relationenschema in R in 3NF bzw. BCNF ist.
Sei R = (S, F ) ein Relationenschema und R1 = (S1 , F1 ) ein Relationenschema, das über
den Attributen S1 ⊆ S definiert ist. Um erkennen zu können, welche FDs auf dem Schema
R1 gelten, führen wir das Konzept der eingebetteten FDs ein:
Definition 7.6 Eine FD X → Y ∈ F ist eingebettet in S1 , wenn XY ⊆ S1 1 . Die Menge aller
in S1 eingebetteten FDs bezeichnen wir mit F [S1 ].
F [S1 ] = {X → Y ∈ F | XY ⊆ S1 }.
Intuitiv bedeutet dies, dass wir die Menge aller funktionalen Abhängigkeiten betrachten,
deren Attribute in der Teilmenge S1 vorkommen, wir projizieren sozusagen auf die Attribute
von S1 .
Beispiel 7.6 Betrachten wir nochmals das Relationenschema aus Beispiel 7.5. R = (S, F )
wobei S = {übung, student, tutor} und F = {student, übung → tutor, tutor →
übung}. Betrachten wir S1 = {übung, tutor}, so ist die Menge der darin eingebetteten
Abhängigkeiten F [S1 ] = {tutor → übung}. Für S2 = {student, tutor} ist F [S2 ] = {},
da es keine funktionale Abhängigkeit gibt, an der nur diese beiden Attribute beteiligt sind.
Definition 7.7 Eine Zerlegung eines Relationenschemas R = (S, F ) ist eine Menge von Relationenschemata {R1 = (S1 , F1 ), R2 = (S2 , F2 ), . . . , Rn = (Sn , Fn )}, wobei folgendes gilt:
1. S = S1 ∪ S2 ∪ . . . ∪ Sn
2. Fi ≡ F + [Si ]
3. (F1 ∪ F2 ∪ . . . ∪ Fn )+ ⊆ F + .
F + [Si ] ist nach der Definition von eingebetteten Abhängigkeiten die Menge aller funktionalen Abhängigkeiten aus F + , deren Attribute auf der linken und der rechten Seite im
Subschema S1 enthalten sind, formal: F + [S1 ] = {X → Y ∈ F + | XY ⊆ S1 }.
1
Die Vereinigung von Attributmengen wird im Allgemeinen ohne das Vereinigungszeichen geschrieben. d.h.
XY entspricht X ∪ Y
KAPITEL 7. NORMALFORMEN
7.7
Definition 7.8 Eine Zerlegung ist abhängigkeitstreu (dependency preserving, keine Abhängigkeit geht verloren), wenn:
(F1 ∪ F2 ∪ . . . ∪ Fn )+ = F +
Die Zerlegung ist verbundtreu (verlustfrei, lossless), wenn für jede Relation r(S) gilt:
r(S1 ) ./ r(S2 ) ./ . . . ./ r(Sn ) = r(S)
Beispiel 7.7 Die Zerlegung in Beispiel 7.5 ist verbundtreu, aber nicht abhängigkeitstreu: die
Abhängigkeit student, übung → tutor geht verloren, d.h., wir können den Umstand, dass
es für jeden Studenten in einer Übung genau einen Tutor gibt, nicht mehr modellieren.
Bei einer Zerlegung in BCNF ist es nicht immer möglich, eine verbund- und abhängigkeitstreue Zerlegung von R zu finden. In einem solchen Fall darf auf die Abhängigkeitstreue
verzichtet werden, nicht jedoch auf die Verbundtreue. Die Abhängigkeitstreue stellt nämlich
Metainformation dar, die Verbundtreue aber echte Information. Einer der größten Nachteile
der BCNF gegenüber der 3NF ist, dass die Existenz einer Zerlegung mit beiden Eigenschaften
nicht immer gegeben ist.
Das Entscheidungsproblem, ob es eine abhängigkeitstreue (und verbundtreue) Zerlegung
eines Datenbankschemas in BCNF gibt, ist NP-vollständig. Der Test, ob ein Datenbankschema in BCNF ist, hingegen ist polynomiell.
Beispiel 7.8 Sei R(S, F ) das folgende Relationenschema R mit S = (ABC) und F = {A →
B, C → B), und wir zerlegen R in R1 = ({AB}, A → B) und R2 = ({BC}, C → B). Für die
erste der beiden nachfolgenden Instanzen erhalten wir eine verbundtreue Zerlegung, für die
zweite nicht.
r
(A
a
a’
r
(A
a
a’
⇒
B C)
b c
b’ c’
⇒
B
b
b
C)
c
c’
r1
(A B)
a b
a’ b’
./
r1
(A B)
a b
a’ b
./
r2
(B C)
b c
b’ c’
=
r2
(B C)
b c
b c’
=
r0
(A
a
a’
B
b
b’
r0
(A
a
a
a’
a’
B
b
b
b
b
C)
c
c’
C)
c
c’
c
c’
Wie können wir eine verbundtreue Zerlegung sicherstellen? Aus dem Beispiel ist ersichtlich, dass die Instanzen des Attributes B für das unterschiedliche Verhalten ausschlaggebend
sind. Im ersten Fall, in dem B als Schlüssel für R1 oder R2 in Frage kommt, ist die Zerlegung
verlustfrei, im zweiten Fall nicht. Im Allgemeinen können wir feststellen, dass die Zerlegung
verbundtreu ist, wenn das Join-Attribut in einer der beiden Teilrelationen Schlüssel ist.
KAPITEL 7. NORMALFORMEN
7.8
Theorem 7.4 Eine Zerlegung von R = (S, F ) in {R
S1n = (S1 , F1 ), R2 = (S2 , F2 ), . . . , Rn =
0
(Sn , Fn )} ist verbundtreu, wenn bezüglich F = i=1 Fi die Hülle eines der generierten
Relationenschemata Si gleich S ist.
S
∃Si | Si+ = S bzgl. F 0 = ni=1 Fi
⇒
Zerlegung von S in S1 , S2 , . . . , Sn ist verbundtreu.
7.4.1 Verbundtreue Zerlegung in 3NF bzw. BCNF
Im Folgenden beschreiben wir ein Verfahren zur verbundtreuen Zerlegung in 3NF bzw. BCNF.
Algorithmus DECOM P
INPUT: Relationenschema R = (S, F )
OUTPUT: verbundtreue Zerlegung {R1 = (S1 , F1 ), . . . , Rn = (Sn , Fn )} von R in 3NF bzw.
BCNF.
METHODE (Prinzip):
1. Wir ersetzen F durch eine minimale Überdeckung, diese heiße weiterhin F .
2. Wir prüfen zunächst, ob F eine bösartige“ Abhängigkeit enthält, d.h.,
”
3NF: eine Abhängigkeit der Form X → A, wobei X kein Schlüssel ist und A nichtprim ist. Eine solche Abhängigkeit würde die 3NF-Bedingung für R = (S, F )
verletzen.
BCNF: eine Abhängigkeit der Form X → A, wobei X kein Schlüssel von R ist. Eine
solche Abhängigkeit würde die BCNF-Bedingung für R = (S, F ) verletzen.
Enthält F keine bösartige Abhängigkeit, dann ist R = (S, F ) bereits in 3NF bzw. in
BCNF. Fertig.
3. Gibt es eine bösartige Abhängigkeit X → A in F , dann spalten wir R in zwei Teile
R1 = (S1 , F1 ) und R2 = (S2 , F2 ) mit:
S1 = S \ A und
S2 = XA, wobei X der Schlüssel für die neue Relation R2 wird2 .
4. Wir berechnen nun Überdeckungen F1 und F2 für R1 und R2 , aus denen sich alle in R1
bzw. R2 gültigen funktionalen Abhängigkeiten ableiten lassen. D.h., wir berechnen
2
S und X sind Mengen von Attributen, A ist ein Element dieser Mengen. Wir vernachlässigen hier eine
eigentlich notwendige Mengenklammerung S \ {A} und X ∪ {A}, da aus dem Kontext klar ist, was gemeint ist.
KAPITEL 7. NORMALFORMEN
7.9
Abhängigkeitsmengen F1 und F2 über S1 bzw. S2 , für die gilt: F1 ≡ F + [S1 ] und
F2 ≡ F + [S2 ].
(In Abschnitt 7.4.3 werden wir im Detail auf diese Problemstellung eingehen.)
5. Das Verfahren wird nun rekursiv auf R1 = (S1 , F1 ) und R2 = (S2 , F2 ) angewendet.
6. Die Menge aller Subschemata in 3NF bzw. BCNF, die im Laufe des Verfahrens erzeugt
werden, ist eine Zerlegung in 3NF bzw. BCNF des ursprünglichen Schemas R.
7. Ist eine möglichst kleine Anzahl von Schemata erwünscht, so können wir folgende Optimierungen durchführen:
• Ist ein Schema eine Teilmenge eines anderen Schemas, so lassen wir dieses “Teilschema” einfach weg, da sich sämtliche Attribute und Abhängigkeiten ja bereits
im größeren Schema finden.
• Weiters fassen wir sämtliche Schemata mit demselben Primärschlüssel zu einem
Schema zusammen, soferne das entstehende Schema danach ebenfalls in 3NF ist.
(Ein Gegenbeispiel hierzu sind AC und AD mit den FDs A → C, A → D, und C → D.)
(Dies alleine führt nicht in allen möglichen Spezialfällen zu einem minimalen Schema,
ist für unsere Zwecke aber ausreichend.)
Das Verfahren terminiert immer, da die Kardinalität der erzeugten Schemata in jedem
Schritt abnimmt. Schlimmstenfalls erhalten wir Schemata der Kardinalität 2 (also mit 2 Attributen); diese sind immer in 3NF bzw. BCNF.
Es ist leicht zu sehen, dass diese Zerlegung verbundtreu ist. Jede Einzelzerlegung ist
verbundtreu: aus S1 = S \ A und S2 = XA kann durch den Verbund R1 ./ R2 wieder R
gewonnen werden, da X ein Schlüssel für R2 ist.
Die Korrektheit des Verfahrens ist folglich gegeben, wenn Schritt 2 ( Überprüfung der
Normalform) korrekt ist. Dafür müssten vorderhand alle Abhängigkeiten X → A ∈ F + und
nicht nur in F überprüft werden. Es kann aber gezeigt werden, dass R = (S, F ) nicht in 3NF
bzw. BCNF ist, genau dann wenn F eine bösartige Abhängigkeit enthält (wichtig: F ist eine
minimale Überdeckung).
Das schwierigste Teilproblem des Verfahrens besteht in der Berechnung von F 1 und F2
aus F und R1 bzw. R2 . Dieses Problem wird später gesondert behandelt (siehe Algorithmus
RBR).
Die während des Verfahrens entstehenden (bzw. verwendeten) Relationenschemata können
als Baum mit Wurzel R = (S, F ) dargestellt werden. Die Blätter des Baumes sind die Bestandteile der Zerlegung (siehe auch das folgende Beispiel).
Gibt es in einer Stufe mehrere bösartige Abhängigkeiten, dann kann das Verfahren – je
nach Auswahl der bösartigen Abhängigkeit – zu verschiedenen Zerlegungen führen.
KAPITEL 7. NORMALFORMEN
7.10
Im Fall von 3NF ist immer eine verbund- und abhängigkeitstreue Zerlegung möglich. Diese ist jedoch von der Reihenfolge der Eliminierung der bösartigen FDs abhängig. Im Beispiel
7.9 werden wir sehen, dass obiger Algorithmus im Gegensatz zum Synthesealgorithmus von
Bernstein (siehe 7.4.4) nicht immer eine abhängigkeitstreue Zerlegung in 3NF liefert.
Beispiel 7.9 ([Ullman, 1988 Bd. I]) Wir betrachten das Schema S = (C, T, H, R, S, G). Die
Attribute haben folgende Bedeutung:
C: Course
H: Hour
S: Student
T: Teacher
R: Room
G: Grade
Dazu betrachten wir die folgende Menge F von funktionalen Abhängigkeiten:
C → T . . . jede Vorlesung hat höchstens einen Vortragenden.
HR → C . . . in einem Hörsaal kann zu einem bestimmten Zeitpunkt nur höchstens eine Vorlesung stattfinden.
HT → R . . . ein Vortragender kann zu einem bestimmten Zeitpunkt nur in höchstens einem
Hörsaal unterrichten.
CS → G . . . jeder Student hat zu jeder Vorlesung höchstens eine Note.
HS → R . . . jeder Student kann sich zu einem bestimmten Zeitpunkt in höchstens einem
Hörsaal aufhalten.
Zuerst berechnen wir sämtliche Schlüssel des Schemas S, und stellen fest, dass HS den
einzigen (minimalen) Schlüssel darstellt.
Die einzige FD, die nicht böse ist, ist HS → R. Ein Zerlegungsbaum für R(S, F ) ist in
Abbildung 7.1 angegeben. Jeder Knoten ist mit dem entsprechenden Teilschema von R, sowie
mit den auf diesem Teilschema gültigen Abhängigkeiten markiert.
Man beachte, dass diese Abhängigkeiten nicht ganz leicht zu finden sind: z.B. muss beim
Übergang von CTHRS auf CHRS eine neue Abhängigkeit CH → R angegeben werden. Diese
Abhängigkeit folgt zwar aus F , ist aber nicht Element von F . Sie entsteht durch Verschmelzung der Abhängigkeiten C → T und TH → R durch Anwendung der Pseudotransitivitätsregel.
Auf dieses Problem wird im nächsten Abschnitt (Algorithmus RBR) eingegangen.
Wir haben allerdings die funktionale Abhängigkeit TH → R verloren. Im Falle der BCNF
können wir sagen, dass uns das egal ist, da wir nicht wissen, ob es eine abhängigkeitstreue
Zerlegung gibt oder nicht (der Baum ist sowohl in BCNF als auch in 3NF), aber für die 3NF
ist das kein akzeptables Ergebnis.
KAPITEL 7. NORMALFORMEN
7.11
HSCTRG
C->T CS->G HR->C
TH->R HS->R
CSG
CS->G
HSCTR
C->T TH->R
HR->C HS->R
CT
C->T
HSCR
CH->R HR->C
HS->R
CHR bzw. CHR
CH->R HR->C
HSC
HS->C
Abbildung 7.1: Verbundtreue Zerlegung von R(S, F ) aus Beispiel 7.9 in 3NF
7.4.2 Verbund- und abhängigkeitstreue Zerlegung in 3NF bzw. BCNF
Eine Erweiterung des obigen Algorithmus zur verbundtreuen Zerlegung in 3NF erlaubt es,
auch Abhängigkeitstreue zu erhalten. Hierzu zuerst einige Bemerkungen:
Der obige Algorithmus ist so konstruiert, dass jedes Schema R2 bereits in 3. Normalform
ist und daher eine weitere Zerlegung von R2 nicht notwendig ist.
Wenn wir die FDs aus der minimalen Überdeckung F betrachten, die wir in Schritt 1
generiert haben, so können wir folgendes feststellen:
• Ist X ein Schlüssel von R und eine FD X → Y kommt explizit in F vor, so ist eine Zerlegung, bei der jedes Subschema aus dem Abspalten einer funktionalen Abhängigkeit
besteht, eine abhängigkeits- und verbundtreue Zerlegung.
• Ist X ein Schlüssel von R und es gibt keine FD X → Y in F , so zerlegen wir R wie
oben, indem wir aus jeder FD ein Subschema erzeugen und geben zum Schluss das
Subschema hinzu, das nur aus X besteht. Wiederum erhalten wir eine verbund- und
abhängigkeitstreue Zerlegung.
Diese Zerlegung ist eine sehr naive Zerlegung, da wir aus jeder FD ein Subschema generieren und das im allgemeinen zu viele Subschemata ergibt. Aus Performancegründen ist
es nicht sehr sinnvoll, in der Praxis so vorzugehen, da bei Abfragen die Anzahl der Joinoperationen, die die aufwendigsten Operationen sind, direkt von der Anzahl der Subschemata
abhängig ist.
KAPITEL 7. NORMALFORMEN
7.12
Dieser naive Algorithmus zeigt jedoch, dass wir uns im Grunde bei einer Zerlegung auf
die FDs beschränken können, die wir in Schritt 1 erhalten haben.
Ein problematischer Fall bei einer Zerlegung sind zyklische Abhängigkeiten, wie wir im
Beispiel 7.9 gesehen haben: F = {C → T, TH → R, HR → C}. Um mit zyklischen Abhängigkeiten umgehen zu können, verwenden wir die folgende modifizierte Zerlegung:
Definition 7.9 Eine Pseudo-Zerlegung nach einer FD X → Y ∈ F ist eine Zerlegung, bei der:
R1 = (S1 , F1 ), R2 = (S2 , F2 ), mit S1 = S, F1 = F, S2 = XY, F2 ≡ F + [XY ].
Eine Pseudo-Zerlegung nach C → T ergibt nun die beiden Subschemata: S 1 = HSCTR und
S2 = CT, wobei auf dem ersten Schema wieder alle vier FDs gelten.
Wir modifizieren daher den ursprünglichen Algorithmus, indem wir auch Pseudozerlegungen durchführen. Weiters führen wir eine Variable G ein, die immer die Menge jener
FDs enthält, die wir im jeweiligen Schritt noch “unterbringen” müssen – entweder in neu
abzuspaltenden Relationen oder in der im rechten Teilbaum verbleibenden Relation.
METHODE (Prinzip):
1. Wir ersetzen F durch eine minimale Überdeckung, diese heiße G.
2. Zerlege (echte Zerlegung oder Pseudo-Zerlegung) nur nach FDs aus G.
Ist die Zerlegung G-erhaltend, so führen wir eine echte Zerlegung durch (wo R tatsächlich
reduziert wird), andernfalls führen wir eine Pseudo-Zerlegung durch.
Dabei bezeichnen wir eine Zerlegung R1 = (S1 , F1 ), R2 = (S2 , F2 ) als G-erhaltend,
wenn für jede FD X → Y ∈ G gilt XY ⊆ S1 oder XY ⊆ S2 .
3. Entferne bei jeder Zerlegung bzw. Pseudo-Zerlegung alle FDs W → Z aus G, für die
WZ ⊆ S2 gilt, gib R2 aus.
Sind etwa die beiden FDs AB → C und C → A in G enthalten, so entfernen wir nach
einer Pseudozerlegung nach AB → C beide dieser FDs aus G.
4. Das Verfahren wird nun rekursiv angewendet. Setze R := R1 und führe die Zerlegung
auf R fort.
Abbruchbedingungen:
• R hat keine bösartigen Abhängigkeiten mehr, d.h., R ist in 3NF: Gib R aus.
• G = {}: Wenn R nicht in 3NF ist, so gib R0 = (S 0 , F 0 ) aus, sodass S 0 ein Schlüssel
für R ist und F 0 ≡ F + [S 0 ].
5. Die Menge aller Subschemata in 3NF bzw. BCNF, die im Laufe des Verfahrens erzeugt
werden, ist eine Zerlegung in 3NF bzw. BCNF des ursprünglichen Schemas R.
KAPITEL 7. NORMALFORMEN
7.13
6. Ist eine möglichst kleine Anzahl von Schemata gefordert, so gehen wir wie unter 7.4.1
beschrieben vor.
Um generell so wenige Subschemata wie möglich zu erhalten, können wir nach der folgenden Heuristik vorgehen:
Heuristik: Zerlege nach bösartigen FDs vor gutartigen und nach G-erhaltenden vor nicht
G-erhaltenden.
Wenden wir nun den modifizierten Algorithmus an, der eine verbund- und abhängigkeitstreue Zerlegung von F aus Beispiel 7.9 liefert.
Beispiel 7.9 (Fortsetzung):
G := {C → T, HR → C, HT → R, CS → G, HS → R}
Bis auf HS → R sind alle FDs bösartig, die einzige G-erhaltende Zerlegung ist die Zerlegung nach CS → G. D.h., G := C → T, HR → C, HT → R, HS → R, wir geben CSG aus.
Da im nächsten Schritt keine Zerlegung nach einer der drei bösartigen FDs in G (C → T,
TH → R und HR → C) G-erhaltend ist, und R noch nicht in 3NF ist, müssen wir eine PseudoZerlegung durchführen. Wir wählen TH → R aus und zerlegen: S 1 = S = HSCTR und
S2 = THR, F1 = F und F2 = {TH → R}; wir setzen G := C → T, HR → C, HS → R und geben
THR aus.
Im nächsten Schritt zerlegen wir nach C → T (bösartig und G-erhaltend) in CT bzw. HSRC
mit den dazugehörigen FDs; wir setzen G := HR → C, HS → R und geben CT aus.
Im letzten Schritt zerlegen wir HSRC nach HR → C (bösartig und G-erhaltend) in HRC bzw.
HSR mit den dazugehörigen FDs und setzen G := HS → R und geben HRC aus. R ist nun in
3NF, da es keine bösartigen FDs mehr gibt, und wir geben R aus. Abbildung 7.2 zeigt den
entsprechenden Zerlegungsbaum.
Wie wir sehen, ist die erhaltene Zerlegung verbund- und abhängigkeitstreu.
7.4.3 Berechnung von Überdeckungen für eingebettete Abhängigkeiten
Wir suchen nun einen Algorithmus, der uns aus einem Subschema S 1 von S zu den auf S
gültigen funktionalen Abhängigkeiten F eine Überdeckung F1 findet, sodass F1 alle auf S1
gültigen Abhängigkeiten repräsentiert. Dabei nehmen wir an, dass F minimal ist.
Formal ausgedrückt bedeutet dies: Finde F1 mit F1+ = F + [S1 ].
Die triviale Lösung dieses Problems besteht in F1 = F + [S1 ]. Sie ist aber in doppelter
Hinsicht schlecht:
1. Es muss die gesamte Menge F + aller aus F folgenden Abhängigkeiten berechnet (z.B.
mittels der Armstrong Axiome) und dann auf S1 projiziert werden ⇒ großer Aufwand
(exponentiell in der Anzahl der Attribute).
KAPITEL 7. NORMALFORMEN
7.14
HSCTRG
C->T CS->G HR->C
TH->R HS->R
G:={C->T,CS->G,HR->C,TH->R,HS->R}
CSG
CS->G
G:={C->T,HR->C,TH->R,HS->R}
HSCTR
C->T TH->R
HR->C HS->R
THR
TH->R
G:={C->T,HR->C,HS->R}
HSCTR
C->T TH->R
HR->C HS->R
CT
C->T
HSCR
CH->R
HR->C,HS->R
CHR
CH->R HR->C
HSR
HS->R
G:={HR->C,HS->R}
G:={HS->R}
Abbildung 7.2: Verbund- und abhängigkeitstreue Zerlegung von R(S, F ) aus Beispiel 7.9
2. Die Überdeckung F + [S] ist von maximaler Größe und braucht daher viel Speicherplatz
(unhandlich).
Eine bessere Methode ist die im Folgenden beschriebene.
Definition 7.10 Sei f eine Abhängigkeit der Form XAY → Z, wobei X und Y möglicherweise
leere Attributmengen darstellen, A ein Attribut, und sei g eine Abhängigkeit der Form V → A.
Die aus f und g ableitbare Abhängigkeit h : XVY → Z nennen wir die A-Resolvente von f
und g.
Jede A-Resolvente von f und g folgt aus {f, g} durch Pseudotransitivität.
Beispiel 7.10 Die beiden Abhängigkeiten C → T und TH → R haben als T-Resolvente CH →
R. Daher kommt CH → R bei der Zerlegung in Beispiel 7.9 als zusätzliche Abhängigkeit in
das Subschema.
Definition 7.11 Die Menge aller nichttrivialen A-Resolventen, die unmittelbar (in einem Schritt)
aus F erzeugt werden können, bezeichnen wir mit RES(F, A). Mit nichttrivial bezeichnen
wir hier jene Abhängigkeiten der Form V → A, für die A in V nicht vorkommt.
KAPITEL 7. NORMALFORMEN
7.15
7.4.3.1 Der Algorithmus RBR (Reduction By Resolution)
[Gottlob, 1987] (modifizierte Version)
Algorithmus RBR
INPUT: Schema R = (S, F ), S1 ⊂ S
OUTPUT: Überdeckung F1 mit F1+ = F + [S1 ]
begin
F1 := kanonisch(F );
X := S \ S1 ;
while X 6= {} do
begin
wähle ein Attribut A aus X;
X := X \ A;
F1 := (F1 ∪ RES(F1 , A));
entferne alle Abhängigkeiten aus F1 , die A enthalten;
end;
return F1 ;
end.
Beispiel 7.11 Als Beispiel betrachten wir die dritte Zerlegung aus Beispiel 7.9.
INPUT R = ({HSCRT}, {C → T, TH → R, HR → C, HS → R}), S1 = {HSCR}.
begin
F1 := F ; da F bereits in kanonischer Darstellung
X := {T};
while X 6= {} do
begin
wähle T aus X;
X := {};
F1 := (F1 ∪ {CH → R});
\ ∗ F1 = {CH → R, HR → C, HS → R} ∗ \
end;
return F1 := {CH → R, HR → C, HS → R};
end.
7.4.4 Der Synthesealgorithmus
Der Synthesealgorithmus von [Bernstein, 1976] findet zu jedem gegebenen Relationenschema R = (S, F ) eine verbund- und abhängigkeitstreue Zerlegung in 3NF. Er ist damit eine
Alternative zu jenem Verfahren, das wir in Abschnitt 7.4.2 vorgestellt haben.
KAPITEL 7. NORMALFORMEN
7.16
1. Bilde eine minimale Überdeckung von F .
2. Wenn F keine Abhängigkeit mit einem Schlüssel für R auf der linken Seite enthält, so
finde einen Schlüssel (genannt K) und führe eine Abhängigkeit K → S ein.
3. Bilde Gruppen von Abhängigkeiten. Abhängigkeiten mit gleichen linken Seiten kommen in die gleiche Gruppe.
4. Vereinige zwei Gruppen von Abhängigkeiten mit den linken Seiten X i und Xj , wenn
Xi ≡ X j .
5. Bilde für jede Gruppe eine ringförmige zusammengesetzte funktionale Abhängigkeit
(annular compound FD, ACFD), wie folgt:
Die Abhängigkeiten in einer Gruppe haben die Form: X1 → Y1 , X2 → Y2 , . . . ,
Xn → Y n .
Bilde daraus: X1 → X2 , X2 → X3 , . . . , Xn → X1 , X1 → Y (wobei Y = Y1 ∪
. . . ∪ Yn ). Abgekürzte Schreibweise: (X1 , . . . , Xn ) → Y .
X1
Y
Xn
X2
...
Die Vereinigung all dieser ACFDs G ist eine Überdeckung für F und wird als ringförmige Überdeckung (annular cover) bezeichnet.
6. Reduziere G, d.h., verschiebe verschiebbare Attribute und eliminiere überflüssige Attribute.
Ein Attribut heißt verschiebbar (shiftable), wenn es in einer ACFD von einem X i nach
Y verschoben werden kann und G äquivalent zu F bleibt. Ein Attribut heißt überflüssig
(extraneous), wenn es von Y gestrichen werden kann und G äquivalent zu F bleibt.
7. Die Zerlegung von R = (S, F ) besteht aus jenen Relationen und Abhängigkeiten, die
durch die einzelnen ACFDs in G beschrieben werden. Falls unter Punkt 2 die Abhängigkeit K → S eingefügt wurde, ergänze mit der Relation R(K).3
Beispiel 7.12 Wollen wir das Beispiel 7.9 mit dem Synthesealgorithmus lösen, so werden
wir sehen, dass sich die einzelnen FDs nicht in ACFDs zusammenfassen lassen. Wir können
daher auch nicht reduzieren und erhalten für jede FD ein eigenes Schema. Dies ist dasselbe
Ergebnis, das wir auch im Zerlegungsalgorithmus schon erhalten haben.
3
Eine genaue Erklärung dieses Algorithmus und Beispiele dazu stehen in [Maier, 1983]
KAPITEL 7. NORMALFORMEN
7.17
7.5 Übungsbeispiele
Übung 7.1 Erklären Sie kurz und präzise die Motive, ein relationales Datenbankschema in 3.
Normalform zu bringen. Welche Vorteile erhoffen wir uns dadurch? Welche Probleme sollen
dadurch vermieden werden? Geben Sie für jedes angeführte Motiv je ein Beispiel, das nicht
der Vorlesung entnommen wurde, an.
Übung 7.2 Gegeben ist
R = {MATRNR, NAME, GEBDAT, ALTER,
DA BETREUER, INSTITUT, SEMESTER, LVA, NOTE }
mit dem Schlüssel {MATRNR SEMESTER LVA} und den funktionalen Abhängigkeiten
MATRNR → NAME GEBDAT ALTER DA BETREUER INSTITUT
GEBDAT → ALTER
DA BETREUER →INSTITUT
Suche eine Zerlegung von R in 3NF.
Übung 7.3 Befinden sich
1. R1 = {A, B, C, D} bzgl. F1 = {A → BCD, B → D, C → D}
2. R2 = {A, B, C} bzgl. F2 = {AB → C, C → B}
in 2NF, 3NF, BCNF ? (Begründung!)
Falls sich R1 , R2 nicht in BCNF befinden, geben Sie eine verlustfreie Zerlegung in BCNF
für die jeweilige Relation an.
Übung 7.4 Befindet sich das Relationenschema R1 = ABCD und R2 = BEF mit den
funktionalen Abhängigkeiten A → D, B → E, BA → C, E → F
1. in 2NF ? (Begründung!)
2. in 3NF ? (Begründung!)
Geben Sie eine verlustfreie Zerlegung in BCNF an.
Übung 7.5 Gegeben sind ein Relationenschema R und eine Menge von FDs F .
R = ABCDEG
F = {ABC → D, B → E, B → G}
In welcher Normalform ist R?
Geben Sie eine abhängigkeitstreue und verbundtreue Zerlegung von R in 3NF an (mit
möglichst wenig Relationen).
KAPITEL 7. NORMALFORMEN
7.18
Übung 7.6 Gegeben sind ein Relationenschema R und eine Menge von FDs F .
R = ABCDE
F = {AB → CD, D → E}
In welcher Normalform ist R?
Geben Sie eine abhängigkeitstreue und verbundtreue Zerlegung von R in 3NF an.
Übung 7.7 Beweisen Sie:
BCNF =⇒ 3NF =⇒ 2NF
Übung 7.8 Sei R ein Relationenschema und F eine Menge von FDs. Sei weiters G eine
minimale Überdeckung von F . Zeigen Sie:
• R ist in 3NF bzgl. F ⇐⇒ für jede FD X → A ∈ G gilt: X ist Schlüssel von R bzgl.
F , oder A ist prim.
• R ist in BCNF bzgl. F ⇐⇒ für jede FD X → A ∈ G gilt: X ist Schlüssel von R bzgl.
F.
Untersuchen Sie: Benötigt man die Minimalität von G?
Übung 7.9 Beweisen Sie, dass der Zerlegungsalgorithmus DECOM P korrekt ist, und eine
verbundtreue Zerlegung in 3NF bzw. BCNF liefert.
Beweisen Sie auch, dass die Erweiterung von DECOM P um Pseudo-Zerlegung wie beschrieben eine verbund- und abhängigkeitstreue Zerlegung in 3NF liefert.
Übung 7.10 Beantworten Sie Punkt 1) bis Punkt 3) für die nachfolgenden Angaben:
1. Geben Sie alle möglichen Schlüssel für R an.
2. In welchen Normalformen ist R ? (mit Begründung!)
3. Geben Sie eine abhängigkeitstreue und verbundtreue Zerlegung von R in 3NF an (mit
möglichst wenig Relationen), sofern R nicht in 3NF ist.
Gegeben sind das Relationenschema R und die Abhängigkeiten F :
1. R = GHIJKL, F = {GH → I, GH → J, I → K, → L, I → J}
2. R = ABCDGH, F = {AB → CD, B → G, G → H}
3. R = ABCDEG, F = {AB → CD, D → E, D → G}
4. R = ABCD, F = {A → D, B → A, B → C, C → D, A → B}
KAPITEL 7. NORMALFORMEN
5. R = ABCDEF, F = {AB → CD, C → E, D → F, A → B}
6. R = ABCDEF, F = {A → B, F → A, C → D}
7. R = ABCDEF, F = {AF → AB, AC → D}
8. R = ABCDEF, F = {ABD → E, E → ABCD}
9. R = ABCDEF, F = {F → E, D → F C, E → B, B → A}
10. R = ABCDEF, F = {AB → C, ABC → DEF, EF → B}
11. R = ABCDEF, F = {ABC → DEF, E → E, E → F }
12. R = ABCDEF, F = {AB → CD, E → F }
13. R = ABCDEF, F = {CD → AE, A → F, AF → B}
14. R = ABCDEF, F = {D → C, E → AF, A → D, F → E}
15. R = ABCDE, F = {ABC → D, ABCD → E}
16. R = ABCDE, F = {ABC → D, ABCD → E, CD → E}
17. R = ABCDE, F = {A → B}
18. R = ABCDE, F = {A → BC, E → D}
19. R = ABCDE, F = {E → CD, C → B}
20. R = ABCDEF, F = {EF → A, A → E, A → F, F → E, A → D}
21. R = ABCDEF, F = {AB → CD, AB → E, E → F }
Übung 7.11 Gegeben:
U = {A1 , . . . , A7 }
F = {A1 → A2 , A1 → A3 , A2 A3 → A1 , A3 → A4 ,
A4 → A 5 , A5 → A 6 , A5 → A 7 , A7 → A 4 }
R = {A4 , A5 }
Gesucht: G, sodass G+ = F + [R] (mit Hilfe des RBR- Algorithmus)
7.19
7.20
KAPITEL 7. NORMALFORMEN
Übung 7.12 Bestimmen Sie für jedes der Relationenschemata RS(R, F ) alle Schlüssel. Stellen Sie fest, in welcher NF sie sind. Geben Sie eine verlustfreie und, wenn möglich, abhängigkeitstreue Zerlegung in BCNF an (mit möglichst wenig Relationen).
1. R = ABCDEF, F = {E → F, B → D, D → C, F → BE}
2. R = ABCDEF, F = {F → E, AC → BD}
3. R = ABCDEF, F = {AF → AB, AC → D}
4. R = ABCDEF, F = {AB → C, ABC → DEF, EF → B}
Übung 7.13 Bestimmen Sie für jedes der Relationenschemata RS1 (R1 ,F1 ), RS2 (R2 ,F2 ) und
RS3 (R3 ,F3 ) alle Schlüssel. Geben Sie eine verlustfreie und, wenn möglich, abhängigkeitstreue Zerlegung in BCNF an (mit möglichst wenig Relationen). Es gelte:
R1 = ABCDE, F1 = {A → E, DB → CA}
R2 = ABCDEF, F2 = {E → F, AB → CD}
R3 = ABCDEF, F3 = {F → E, A → D, D → C, E → AF }
Übung 7.14 Bestimmen Sie für jedes der Relationenschemata RS1 (R1 ,F1 ), RS2 (R2 ,F2 ) und
RS3 (R3 ,F3 ) einen Schlüssel. Geben Sie eine verlustfreie und abhängigkeitstreue Zerlegung
in 3NF an (mit möglichst wenig Relationen). Es gelte:
R1 = ABCDEF, F1 = {CDE → F, F → A, CE → B}
R2 = ABCDEF, F2 = {CD → AE, A → F, AF → B}
R3 = ABCDEF, F3 = {A → B, F → A, C → D}
Übung 7.15 Bestimmen Sie für jedes der Relationenschemata RS1 (R1 ,F1 ), RS2 (R2 ,F2 ) und
RS3 (R3 ,F3 ) einen Schlüssel. Geben Sie eine verlustfreie und abhängigkeitstreue Zerlegung
in 3NF an (mit möglichst wenig Relationen). Es gelte:
R1 = ABCDEF, F1 = {C → A, CB → ADE, E → F }
R2 = ABCDEF, F2 = {D → CB, C → F, E → A}
R3 = ABCDEF, F3 = {D → B, B → CE, C → F E, CE → D}
Übung 7.16 Bestimmen Sie für jedes der Relationenschemata RS1 (R1 ,F1 ), RS2 (R2 ,F2 ) und
RS3 (R3 ,F3 ) alle Schlüssel. Geben Sie eine verlustfreie Zerlegung in BCNF mit möglichst
wenigen Relationen an. Es gelte:
R1 = ABCDE, F1 = {A → D, C → B}
R2 = ABCDEF, F2 = {A → BC, B → DA, D → E, CD → F }
R3 = ABCDE, F3 = {AB → CDE, E → BC, C → D}
KAPITEL 7. NORMALFORMEN
7.21
Übung 7.17 Bestimmen Sie für jedes der Relationenschemata RS1 (R1 ,F1 ), RS2 (R2 ,F2 ) und
RS3 (R3 ,F3 ) alle Schlüssel. Geben Sie eine verlustfreie Zerlegung in BCNF mit möglichst
wenigen Relationen an. Es gelte:
R1 = ABCDE, F1 = {B → E, D → C}
R2 = ABCDEF, F2 = {F → AB, A → CF, C → D, BC → E}
R3 = ABCDE, F3 = {CD → ABE, B → DE, E → A}
Übung 7.18 Geben Sie ein Beispiel für ein Relationenschema R an, das bzgl. einer Menge F
von FDs nicht abhängigkeits- und verbundtreu in BCNF zerlegbar ist.
Versuchen Sie, ein möglichst kleines Beispiel (möglichst wenige Attribute, FDs) zu finden.
Übung 7.19 Bestimmen Sie für jedes der Relationenschemata RS1 (R1 ,F1 ), RS2 (R2 ,F2 ) und
RS3 (R3 ,F3 ) alle Schlüssel. Geben Sie eine verlustfreie Zerlegung in 3NF mit möglichst wenigen Relationen an. Es gelte:
R1 = ABCDE, F1 = {AB → D, E → A}
R2 = ABCDE, F2 = {AD → C, C → E, CE → B}
R3 = ABCDE, F3 = {AB → CDE, E → BC, C → D}
Übung 7.20 Für die Verwaltung einer wissenschaftlichen Konferenz ist eine Datenbank in
3NF zu entwerfen. Unterstreichen Sie je Relation einen Schlüssel. Verwenden Sie nur die
vorgegebenen Attributnamen. (Diese sind nur bei ihrer jeweils ersten Erwähnung angeführt.)
Führen Sie keine zusätzlichen Attribute ein. Die Datenbank unterstützt keine Nullwerte.
• Alle in der Datenbank verwalteten Personen werden durch die Kombination aus ihrem
Namen (NAME) und ihrer email-Adresse (EMAIL) eindeutig identifiziert. Sie haben
eine physische Adresse (ADRESSE).
• Autoren reichen Artikel ein, die sie auf der Konferenz vortragen möchten. Jeder eingereichte Artikel wird durch eine eindeutige Nummer (ANR) identifiziert. Er hat einen
Titel (TITEL), sowie eine bestimmte Seitenanzahl (SANZ). Ein Artikel kann mehrere
Autoren haben, es gibt aber immer nur einen Hauptautor. Ein Autor kann an mehreren Artikeln beteiligt sein. Jeder Artikel wird beschrieben durch mehrere KEYWORDs
(keine fixe Anzahl). Es ist vermerkt, ob der Artikel für die Konferenz angenommen
wurde oder nicht (AANG).
• Bevor ein Artikel zum Vortrag zugelassen wird, muss er einer Begutachtung unterzogen werden. Jeder Artikel ist mehreren Gutachtern zugeordnet (keine fixe Anzahl). Jeder Gutachter gibt seine Bewertung des Artikels in puncto Lesbarkeit (LESB), Neuheit
(NEU) und Wichtigkeit (WICHT) ab.
7.22
KAPITEL 7. NORMALFORMEN
• Das Programm der Konferenz ist in einzelne, eindeutig benannte (SNAME) Sitzungen
unterteilt. Für angenommene Artikel ist gespeichert, in welcher Sitzung der Artikel
vorgetragen wird, und welcher Autor den Vortrag halten wird. Ein Artikel wird nur
einmal vorgetragen. Für die Abhaltung einer jeden Sitzung ist ein eigener Vorsitzender
bestimmt.
Übung 7.21 Eine Datenbank zur Verwaltung von Erdbebendaten soll in 3NF modelliert werden. Unterstreichen Sie je Relation einen Schlüssel. Verwenden Sie nur die vorgegebenen
Attributnamen. (Diese sind nur bei ihrer jeweils ersten Erwähnung angeführt.) Führen Sie
keine zusätzlichen Attribute ein. Die Datenbank unterstützt keine Nullwerte.
• Messstationen haben eine geographische Position, die durch Länge (L) und Breite (B)
angegeben ist. Für jede Messstation ist bekannt, für welche maximale Erdbebenstärke
(MAXBEL) sie ausgelegt ist.
• Einer Messstation können mehrere Sensoren zugeordnet sein. Jeder Sensor hat eine
(für diese Station) eindeutige Nummer (SEN#), das Jahr der Errichtung (JAHR), das
Datum der nächsten Generalüberholung (GENERAL), und den Grad der Empfindlichkeit (EMP).
• Ein Erdbeben wird identifiziert durch eine laufende Nummer (EBNR) und beschrieben
durch die Position des Epizentrums, Datum (DAT), und Uhrzeit (ZEIT).
• Angegeben ist außerdem die Stärke des Erdbebens (STAERKE) und die Tiefe des Epizentrums unter der Oberfläche (TIEFE).
• Für jede Messung ist der Sensor, das betroffene Erdbeben und die Uhrzeit bekannt, außerdem die Dauer der Messung (DAUER) und das Aktenzeichen des Originalausdrucks
(AKZ). Es kann mehrere Messungen je Erdbeben und Sensor geben.
• Ein Erdbeben besteht aus einer Reihe von Erdstößen. Jeder Erdstoß hat eine laufende
Nummer (ESNR) pro Erdbeben, und die Angaben von Uhrzeit und Stärke.
• Schadensmeldungen sind einem bestimmten Erdstoß zugeordnet. Sie sind beschrieben
durch ihre Position, die Höhe des Schadens (HOEHE) und die Anzahl der Opfer (OPFER).
Übung 7.22 Die Datenbank der NASA über die Experimente-Belegung des Hubble Space
Telescope (HST) ist in 3NF darzustellen. Unterstreichen Sie je Relation einen Schlüssel.
Verwenden Sie nur die vorgegebenen Attributnamen. (Diese sind nur bei ihrer jeweils ersten Erwähnung angeführt.) Führen Sie keine zusätzlichen Attribute ein. Die Datenbank
unterstützt keine Nullwerte.
KAPITEL 7. NORMALFORMEN
7.23
• Beobachtungszeiträume für das Teleskop werden über Projekte zugeteilt. Ein Projekt
wird von einer Forschungsgesellschaft (FGES) gefördert und hat eine innerhalb dieser
Gesellschaft eindeutige Kombination von Projektnamen (Pname) und -nummer (Pnummer). Ein Projekt hat eine Priorität (Prio), einen leitenden Astronomen (LAst) und
möglicherweise noch mehrere Mitarbeiter (PMit).
• Messgeräte an Bord des HST tragen eine eindeutige Bezeichnung (MGB). Sie werden
beschrieben durch Stromverbrauch (SV) und Wartungszustand (WZ).
• Fixe Himmelsobjekte haben eine eindeutige Bezeichnung (HOBZ), eine Positionsangabe durch Länge und Breite (L, B), sowie einen Durchmesser (DM) angegeben in
Winkelsekunden.
• Bewegliche Himmelskörper haben ebenfalls eine Bezeichnung und einen Durchmesser. Für sie ist für jedes Jahr (J) die Himmelsposition am Anfang jedes Monats (M)
angegeben.
• Beobachtungen geben das Projekt, das Gerät, Jahr, Monat, Tag (T), Uhrzeit (U) und
Dauer (D) der Beobachtung an. Eine Beobachtung dient immer nur einem Projekt.
Verschiedene Messgeräte können gleichzeitig Beobachtungen durchführen.
Übung 7.23 Eine von einer staatlichen Einrichtung geführte Datenbank über den nationalen Waldzustand ist in 3NF darzustellen. Unterstreichen Sie je Relation einen Schlüssel.
Verwenden Sie nur die vorgegebenen Attributnamen. (Diese sind nur bei ihrer jeweils ersten Erwähnung angeführt.) Führen Sie keine zusätzlichen Attribute ein. Die Datenbank
unterstützt keine Nullwerte.
• Ein Land ist in Areale unterteilt. Ein Areal ist identifiziert durch die Koordinaten eines
fix zugeordneten Hauptmessortes (X, Y) innerhalb des Areals. Es ist beschrieben durch
einen Namen (ANAME), die Fläche (FL), Orientierung (OR), und durchschnittliche
Seehöhe (DSH), sowie die darauf wachsenden Baumarten (BMART) mit der Angabe
der Bewuchsdichte (BWD) und des Prozentanteils (BPROZ) der jeweiligen Baumart.
• Alle Messorte (inkl. Hauptmessorte) werden durch ihre Koordinaten (MX, MY) identifiziert, beschrieben durch ihre Seehöhe (SH) und die Angabe des Areals, in dem sie
liegen.
• Jahresberichte geben für jedes Areal für jedes Jahr (JAHR) und jede Baumart an, wie
hoch in diesem Jahr der Prozentsatz (SPROZ) der Bäume in jeder der zehn möglichen
Schadensklassen war (SK).
• Niederschlagsberichte geben für jeden Messpunkt die monatliche (MONAT) Niederschlagsmenge (NSM) sowie die vorwiegende Niederschlagsart (NSA) an (für alle in
der Datenbank enthaltenen Jahre).
7.24
KAPITEL 7. NORMALFORMEN
• Einzelne Areale werden für Experimentierzwecke mit chemischen Wirkstoffen behandelt. Gespeichert wird das Areal, der für die Behandlung auf dem Areal benutzte Wirkstoff (WSTOFF) sowie Jahr und Monat der Behandlung (Ann.: nur eine Behandlung
pro Jahr pro Areal).
Übung 7.24 Zur Verwaltung von Konstruktionsdaten in einem System zur Entwicklung von
elektronischen Steuerungen soll eine relationale Datenbank in 3NF entworfen werden. Unterstreichen Sie je Relation einen Schlüssel. Verwenden Sie nur die vorgegebenen Attributnamen. (Diese sind nur bei ihrer jeweils ersten Erwähnung angeführt.) Führen Sie keine
zusätzlichen Attribute ein. Die Datenbank unterstützt keine Nullwerte.
• Bauteile werden durch eine eindeutige Bauteilnummer (B#) identifiziert und durch einen
Typ (TYP; z.B. Widerstand, Kondensator, ASIC) sowie die Kosten (Kosten) und den
Hersteller (Herst) beschrieben.
• ASICS werden außerdem durch die Angabe der Pin-Anzahl (PAnz) und der Anzahl der
Transistoren (TAnz) beschrieben.
• Platinen haben eine eindeutige Nummer (P#) und werden beschrieben durch Angabe ihrer Länge (L) und Breite (B) sowie der daran angebrachten Typen von Steckern
(STTyp). Da an einer Platine beliebig viele Stecker angebracht sein können, auch mehrere vom selben Typ, muss außerdem für jeden Typ auf einer Platine die Anzahl gespeichert werden (STAnz). (Anm.: Platinen sind keine Bauteile).
• Eine Baugruppe, identifiziert durch eine Typbezeichnung (BGTyp), besteht aus einer
Platine mit darauf angebrachten Bauteilen. Auf einer Platine können beliebig viele
Bauteile angebracht werden. (Annahme: pro Platine höchstens ein Bauteil von jedem
Typ.) Gleichzeitig muss gespeichert werden, welche Bauteile auf der Platine durch Leiterbahnen miteinander verbunden werden. Solche Verbindungen sind immer paarweise
(d.h., verbinden zwei Bauteile). Auf einer Platine können auch unverbundene Bauteile
existieren.
Kapitel 8
Physisches Datenbankdesign
8.1 Grundlegende Begriffe
In diesem Kapitel stellen wir die Methoden zur physischen Speicherung von Relationen vor.
Eine Relation wird dabei in einer Datei gespeichert, die aus einzelnen S ätzen (records) besteht.
Wir gehen davon aus, dass ein Satz aus einer festen Anzahl von Feldern besteht, die zusammenhängend mit fixem Platzbedarf und in fixer Reihenfolge abgespeichert sind. Ein Schl üssel
ist ein Feld oder eine Kombination von Feldern, deren Werte einen bestimmten Satz eindeutig
identifizieren. Ein Speicherverwaltungssystem bietet Zugriff auf eine Menge gleich großer
Blöcke bzw. Seiten (blocks, pages). Der Zugriff auf einen Block erfolgt direkt über dessen Blockadresse. Das Speicherverwaltungssystem liefert unbenutzte Blöcke und übernimmt
freigewordene Blöcke.
Wir setzen voraus, dass die folgenden Formen der Datenorganisation bekannt sind (siehe VO Algorithmen und Datenstrukturen): ungeordnete Dateien, indexsequentielle Dateien,
Hashorganisation, dynamisches Hashing (dynamic hashing), erweiterbares Hashing (extendible hashing) und B ∗ -Baum.
8.1.1 Clustering
Eine neue Speicherorganisation ist das Clustering.
Hierbei handelt es sich um eine Abart der indexsequentiellen Speicherung. Die Hauptdatei
wird dabei nicht nach dem Primärschlüssel (bei dem kein Wert mehr als einmal vorkommen
darf) sortiert gespeichert, sondern nach einem anderen Feld. Wir bezeichnen dieses Feld als
indiziertes Feld. Dieses wird im Gegensatz zum Relationenmodell in Systemhandbüchern
oft auch als Schlüsselfeld“ bezeichnet. Das indizierte Feld stellt im allgemeinen keinen
”
Schlüssel im Sinne des Relationenmodells dar, da seine Ausprägung nicht eindeutig einen
Datensatz identifiziert. Hingegen dürfen die indizierten Felder verschiedener Datensätze den
gleichen Wert annehmen, solche Sätze werden zusammen abgespeichert (clustered). Dies gilt
analog für den Fall, dass statt nach einem Feld nach einer Gruppe von Feldern indiziert wird.
1
KAPITEL 8. PHYSISCHES DATENBANKDESIGN
8.2
rnr
1
1
1
1
2
rnr
1
2
3
4
Indexdatei
(ind. Feld,Blockzeiger)
preis
name
2
3
3
3
3
4
4
4
4
4
Datei
Abbildung 8.1: Ein Clustering-Index der Relation Speise
Das Einfügen, Suchen und Löschen ist im Prinzip gleich wie bei der indexsequentiellen
Form.
8.1.1.1 Clustering-Index
Ein Clustering-Index ist gleich aufgebaut wie ein Index nach dem Primärschlüssel. Wie bereits gesagt besteht der Unterschied darin, dass die Hauptdatei zwar nach dem Sortierfeld geordnet ist, es aber für jeden Wert mehrere Sätze geben kann (siehe Abbildung 8.1). Der Index
enthält einen Eintrag pro tatsächlich vorkommendem Wert des Sortierfeldes. Der Blockzeiger
zeigt auf den ersten Block, in dem dieser Wert vorkommt. Um alle Sätze eines Wertes zu
finden, müssen solange alle Folgesätze – auch in den folgenden Blöcken – gelesen werden,
bis das Sortierfeld einen anderen Wert annimmt.
8.1.1.2 Geclusterte Speicherung von Datensätzen
Durch die Möglichkeit, mehrere Datensätze zusammen zu clustern, kommen wir zu dem eigentlichen Vorteil dieser Methode. Dabei werden Tupel aus einer oder mehreren Relationen,
die in bestimmten Feldern (clustering attributes) identische Werte aufweisen, in denselben
Blöcken gespeichert. Aus Effizienzgründen wird dabei meist ein Index über die clustering
attributes gelegt. Diese Organisationsform bringt den Vorteil, dass ein prejoin stattfindet, wo-
KAPITEL 8. PHYSISCHES DATENBANKDESIGN
8.3
durch die Joinoperationen weniger Zeit brauchen. Außerdem benötigen die Tupel weniger
Speicherplatz, da idente Felder jeweils nur einmal gespeichert werden. Der Nachteil ist, dass
die einzelne Relation auf mehr Blöcke verteilt werden muss, als wenn sie alleine gespeichert
wird. Dadurch müssen bei Abfragen, die nur die eine Relation betreffen, mehr Blöcke gelesen
werden und der der Zeitaufwand für die Suche erhöht sich. Angewandt wird diese Methode
dann, wenn bestimmte Dateien oft miteinander verknüpft werden.
8.1.2 Primär- und Sekundärorganisation
Bei der Speicherorganisation unterscheiden wir zwei Schritte: die Primärorganisation und
die Sekundärorganisation. Unter Primärorganisation verstehen wir die Speicherungsform der
Datensätze einer Datei, unter Umständen eng verbunden mit einer bestimmten, ausgewählten Zugriffsorganisation. Unter einer Sekundärorganisation einer Datei verstehen wir eine
neben der primären Zugriffsstruktur (Primärorganisation) alternative Zugriffsstruktur. Eine
Datei kann mehrere Sekundärorganisationen besitzen. Eine Sekundärorganisation wird dann
verwendet, wenn die Primärorganisation die Suche nach einem bestimmten Feld nicht unterstützt, wenn also die ganze Datei sequentiell gelesen werden müsste.
Indexsequentielle Organisation, Hashing und B∗ -Bäume werden sowohl für die Primärals auch für die Sekundärorganisation verwendet mit dem Unterschied, dass bei der Sekundärorganisation dort, wo sich bei der Primärorganisation der Datensatz selbst befindet,
nur ein Verweis auf den Datensatz gespeichert ist.
Bei der Sekundärorganisation wird hauptsächlich ein dichter Index (dense index) verwendet. Darin existiert für jeden Wert des indizierten Feldes ein Eintrag im Index. Dies ist vergleichbar mit dem Stichwortindex eines Buches. Ein dichter Index kann bei Dateien beliebiger
Art – auch ungeordneten und Hash-Dateien – angewendet werden. Mit einem dichten Index
kann ein beliebiges Feld indiziert werden, unabhängig davon, ob es sich um ein Schlüsselfeld
handelt oder ob und wie die Datei sortiert ist.
8.2 Speicherstrukturen f ür Relationen
Relationen werden auf Dateien abgebildet, wobei die Sätze der Datei den Tupeln der Relation
entsprechen.
8.2.1 Kriterien zur Auswahl von Speicherstrukturen
Es gibt eine Reihe von Kriterien, nach denen eine geeignete Speicherstruktur für eine Datei
gewählt werden kann. Zu den wichtigsten Kriterien zählen der Speicherplatzbedarf, die Art
der Abfragen, die häufig vorgenommen werden, Änderungsverhalten der Datei und Aufwand
für Zugriffsoperationen.
Bei den Abfragen können wir grob folgende Arten unterscheiden:
KAPITEL 8. PHYSISCHES DATENBANKDESIGN
8.4
1. Exakte Abfrage, z.B. name = 0 GreenCottage0 .
2. Bereichsabfragen, z.B. 2 ≤ haube ≤ 4.
3. Pattern matching z.B. name = 0 Gre∗0 .
4. Abfrage nach einem Teilschlüssel, z.B. wenn der Schlüssel {rnr, name}ist, die Suche
nach name = 0 Kleines Sushi0 .
Im Folgenden betrachten wir die vorgestellten Organisationsformen für Dateien und halten
kurz ihre Vor- und Nachteile und mögliche Anwendungsgebiete fest.
8.2.1.1 Ungeordnete Dateien
Die Sätze werden ungeordnet sequentiell gespeichert und sequentiell gelesen. Alle Blöcke
werden immer gefüllt.
Vorteile:
• Am schnellsten, wenn viele Sätze eingefügt werden sollen.
• Da alle Blöcke immer voll gefüllt werden, benötigt eine solche Datei vergleichsweise
wenig Platz (ACHTUNG: Spätere Fragmentierung möglich).
• Effizientes Löschen (nachdem der Satz gefunden wurde).
Nachteile:
• Sehr langsam, wenn nach einigen wenigen Sätzen gesucht wird.
• Bei Abfragen nach Werten innerhalb eines bestimmten Bereiches muss jeder Satz gelesen werden.
• Der Platz, der durch das Löschen von Sätzen frei wird, kann nur durch eine Reorganisation wiederverwendet werden.
Anwendungsgebiet:
• Kleine Dateien, die nur wenige Blöcke benötigen. Da nur wenige Blöcke gelesen werden müssen, lohnt sich zusätzlicher Verwaltungsaufwand nicht.
• Wenn bei Abfragen häufig alle Sätze gelesen werden müssen, z.B. bei statistischen Auswertungen.
• Wenn wir bei einer großen Datei Platz sparen wollen, können wir diese ungeordnet (mit
100% Füllgrad) und mit einem Sekundärindex anlegen.
KAPITEL 8. PHYSISCHES DATENBANKDESIGN
8.5
8.2.1.2 Indexsequentielle Dateien
Vorteile:
• Gutes Antwortzeitverhalten für pattern-matching, Bereichsabfragen, Suche nach einem
Teilschlüssel, aber auch für exakte Abfragen.
• Sortierung muss nicht nach dem Primärschlüssel erfolgen.
Nachteile:
• Sind sowohl Hauptdatei als auch Index statisch gespeichert, müssen neue Sätze in
Überlaufblöcken“ gespeichert werden, was die Suchoperationen verlangsamt vor al”
lem, wenn sequentiell viele Datensätze eingefügt werden.
Statisch (pinned) bedeutet, dass jeder Datensatz an einer bestimmten, festen physischen
Adresse gespeichert ist ( festgenagelt“), die nachträglich nicht mehr verändert und der
”
Datensatz daher nicht mehr verschoben werden kann. Statische Organisation vermeidet
das Problem ungültiger Verweise (dangling pointers) auf einen Datensatz, die durch
Verschieben oder Löschen entstehen können. Durch eine Reorganisation können die
Sätze in den Überlaufblöcken in die Hauptdatei eingefügt werden.
Anwendungsgebiet:
• Bei Dateien, in die später wenige Sätze eingefügt werden, und bei denen flexible Abfragen notwendig sind.
• Die Anzahl der Indexblöcke ist gering.
8.2.1.3 Clustered
Vorteile:
• Gutes Antwortzeitverhalten für pattern-matching, Bereichsabfragen, Suche nach einem
Teilschlüssel, aber auch für exakte Abfragen.
• Sortierung muss nicht nach dem Primärschlüssel erfolgen.
• Es können mehrere Dateien miteinander verwoben gespeichert werden, dadurch schnellerer Zugriff (bei Joins).
KAPITEL 8. PHYSISCHES DATENBANKDESIGN
8.6
Nachteile:
• Sind sowohl Hauptdatei als auch Index statisch (pinned) gespeichert, müssen neue Sätze
in Überlaufblöcken gespeichert werden, was die Suchoperationen verlangsamt. Durch
eine Reorganisation können die Sätze in den Überlaufblöcken in die Hauptdatei eingefügt werden.
• Langsamerer Zugriff, wenn nur die Sätze einer Datei gelesen werden, da hier mehr
Blöcke gelesen werden müssen.
• aufwendiges Einfügen
• aufwendiges Löschen
Anwendungsgebiet:
• Bei Dateien, in die später wenige Sätze eingefügt werden, und bei denen flexible Abfragen notwendig sind, oder
• bei Dateien, die oft miteinander verknüpft werden (joins).
8.2.1.4 Hashorganisation
Vorteile:
• Effizienter Zugriff: durchschnittlich d n2 e, wobei n = Zahl der Blöcke pro Bucket. (Ein
Bucket besteht aus einem oder mehreren Blöcken, die Sätze der Datei werden durch
Hashing in eine Menge von Buckets aufgeteilt.)
• Schnellste Zugriffsmethode für exakte Abfragen nach dem Schlüssel. Dies sind Abfragen, bei denen kein pattern-matching verwendet werden muss, also z.B. keine Jokerzeichen in Zeichenketten.
Nachteile:
• Bei Bereichsabfragen muss jeder Satz gelesen werden.
• Keine Sortierung möglich.
• Ungünstig für Abfragen mit pattern-matching und Abfragen nach Teilschlüsseln, da
hierfür alle Sätze gelesen werden müssen.
Anwendungsgebiet:
• Dateien, deren Abfragen überwiegend in einer exakten Abfrage nach dem Schlüssel
bestehen, z.B. Ordernummern, Sozialversicherungsnummer.
KAPITEL 8. PHYSISCHES DATENBANKDESIGN
8.7
8.2.1.5 B ∗ -Baum
(Abhängig von der Implementierung können die Blattknoten anstelle der tatsächlichen Datensätze Zeiger auf die Datensätze enthalten.)
Vorteile:
• Keine Überlaufprobleme, da sich der Index dynamisch anpasst.
• Gutes Antwortzeitverhalten für pattern-matching, Bereichsabfragen, Suche nach einem
Teilschlüssel, aber auch für exakte Abfragen.
• Der durch das Löschen von Sätzen freigewordene Platz kann ohne Reorganisation wiederverwendet werden.
• Da Sätze mit benachbarten Schlüsseln oft im gleichen Blattknoten gespeichert sind,
können auch Bereichsabfragen effizient durchgeführt werden. Wenn die Datei oft sequentiell geordnet nach Schlüssel abgearbeitet wird, empfielt es sich, die Blattknoten
mittels Zeiger zu verbinden, sodass zusätzlich zur Baumstruktur eine verkettete Liste
entsteht.
• Es ist keine Reorganisation nach einer bestimmten Zeit nötig.
Nachteile:
• Höherer Platzverbrauch bei kleinen Dateien, dieser Faktor fällt bei mittleren bis großen
Dateien nicht mehr ins Gewicht.
• Höherer Verwaltungsaufwand (Einfügen, Löschen) bedingt durch die sofortige Reorganisation.
• Zugriff etwas langsamer als bei Indexsequentieller Organisation wegen der komplexeren Zugriffsstruktur.
• Geringere Parallelität bei gleichzeitigem Zugriff mehrerer Benutzer (komplizierte Concurrency Control; gegebenenfalls ist Sperren auf allen Baumebenen für eine Änderung
notwendig, d.h., fast überhaupt keine Parallelität).
Anwendungsgebiet:
• Bei Dateien, die flexible Abfragen benötigen.
• Bei Dateien, deren Größe stark variiert (häufiges Einfügen, Löschen oder ändern der
Werte).
KAPITEL 8. PHYSISCHES DATENBANKDESIGN
8.8
Beispiel 8.1 Gegeben ist eine Datei, in der Inskriptionsdaten gespeichert sind. Die Primärorganisation ist indexsequentiell, sortiert nach MATRIKELNUMMER. Diese Organisationsform
wurde gewählt, weil einerseits viele Abfragen nach Matrikelnummern gestellt werden und
andererseits viele Listen sortiert nach der Matrikelnummer ausgegeben werden müssen.
Zusätzlich soll auch nach den Feldern STUDIENRICHTUNG, SOZIALVERSICHERUNGSNUMMER
und MATURASCHULE zugegriffen werden, was bei dieser Organisation nicht effizient möglich
ist.
Für das Feld STUDIENRICHTUNG sind nur wenige verschiedene Werte zu erwarten. Daher sollte ein Index verwendet werden, wenn ein effizienter Zugriff nach STUDIENRICHTUNG
notwendig ist.
Für das Feld SOZIALVERSICHERUNGSNUMMER wäre eine sekundäre Hashorganisation sinnvoll: es wird immer ein Datensatz mit einer bestimmten, vollständig angegebenen Sozialversicherungsnummer gesucht.
Ein Anwendungsfall für einen B ∗ -Baum als Sekundärorganisation wäre eine Zugriffsstruktur für das Feld MATURASCHULE: es sind viele unterschiedliche Werte zu erwarten, daher
kann über einen B ∗ -Baum effizienter zugegriffen werden als über einen Index. Alternativ
wäre eine Hash-Organisation denkbar. Sollen auch Abfragen nach einem Teil des Namens
der Schule möglich sein, ist die Hash-Organisation jedoch ungünstig.
8.2.2 Füllgrad
Ein wichtiges Element der Optimierung einer Datenbank ist der Füllgrad eines Blocks:
Definition 8.1 Der Füllgrad (FG) ist definiert als
FG =
Anzahl der erwünschten Sätze pro Block
Anzahl der möglichen Sätze pro Block
Ein Block enthält u.U. Verwaltungsinformation (Pointer) neben Datensätzen, so dass auch
bei F G = 100% nicht alle Bytes des Blocks mit Datensätzen belegt sind.
Jeder Block wird bis zum Füllgrad gefüllt, der verbleibende Platz wird für update-Operationen reserviert.
Das bringt den Vorteil mit sich, dass Überläufe vermieden oder zumindest vermindert
werden können, aber auch den Nachteil, dass die Datei mehr Platz benötigt (≈ F1G -fachen
Speicherbedarf).
Bei der Wahl der Speicherstruktur und besonders bei der Wahl der Sekundärorganisation
dürfen wir allerdings nie die Tatsache aus den Augen verlieren, dass jede zusätzliche Zugriffsstruktur ein Ansteigen des Verwaltungsaufwandes – besonders beim Einfügen von Datensätzen – mit sich bringt. Wir müssen also bei jeder Zugriffsstruktur kalkulieren, ob der
Mehraufwand an Verwaltung durch Einsparungen beim Zugriff gerechtfertigt werden kann.
KAPITEL 8. PHYSISCHES DATENBANKDESIGN
8.9
Ein weiterer wichtiger Aspekt ist die Frage, welches Feld für die Primärorganisation verwendet wird und auf welches Feld über eine Sekundärorganisation zugegriffen wird. Das
Entscheidungskriterium für diese Frage ist die Häufigkeit, nach der über ein bestimmtes Feld
zugegriffen wird und die Art der Abfrage. Wenn z.B. häufig eine Liste erstellt werden soll,
die nach einem bestimmten Feld geordnet ist, dann sollte eine Primärorganisation geordnet
nach diesem Feld gewählt werden, bei der dies effizient möglich ist.
8.2.3 Zugriffszeitverhalten
Wir wollen kurz das Zugriffsverhalten bei den einzelnen Organisationsformen betrachten und
zwar die Suche nach einem bestimmten Wert (exakte Abfrage).
Sei n die Anzahl der Datensätze in der Hauptdatei, und nehmen wir an, ein Block der
Hauptdatei enthalte e Datensätze und ein Block einer Indexdatei d Indexeinträge.
Hashorganisation: unter der Annahme, dass im Durchschnitt ein Bucket aus einem Block
besteht, wird ein Zugriff auf das Directory und ein weiterer auf das Bucket benötigt,
insgesamt also 2 Zugriffe.
Befindet sich im Bucket nicht der Datensatz selbst, sondern ein Verweis auf den Datensatz, z.B. bei einer Sekundärorganisation, so wird ein weiterer Zugriff auf den Block
mit dem Datensatz benötigt.
Indexsequentiell: Für die Hauptdatei werden ne Blöcke benötigt. Für jeden Block wird ein
Eintrag im Index benötigt, d dieser Einträge sind in einem Block; daher besteht die
n
Indexdatei grob aus ed
Blöcken.
n
Die binäre Suche im Index benötigt daher grob log 2 ( ed
) Blockzugriffe. Unter speziellen
Voraussetzungen kann ein anderes Verfahren, z.B. Interpolationssuche auch weniger
Zugriffe erfordern. Ein weiterer Blockzugriff wird benötigt, um den Datensatz selbst zu
lesen.
B ∗ -Baum: Hier seien d und e die Untergrenze für die Anzahl der Datensätze in den inneren
Knoten bzw. Blattknoten. Befinden sich die Datensätze in den Blättern des B ∗ -Baumes,
so hat dieser Baum höchstens ne Blätter. Die Schicht über den Blättern besteht aus
n
höchstens ed
Knoten, die darüberliegende Schicht aus edn2 Knoten usw. Geht der Pfad
von der Wurzel bis einschließlich zum Blatt über i Knoten, so muss gelten: n ≥ d i−1 e
(di+1 Blattknoten mit je e Datensätzen). Formen wir nach i um, so erhalten wir i ≤
1 + logd ( ne ).
Wir benötigen also bis zu 1+logd ( ne ) Zugriffe im B ∗ -Baum. Befinden sich in den Blattknoten nicht die Datensätze selbst, sondern nur Verweise, so kommt noch ein Zugriff
dazu. (Es ist kein großer Nachteil, wenn d e, weil dadurch unter Umständen der
Baum niedriger ist.)
8.10
KAPITEL 8. PHYSISCHES DATENBANKDESIGN
Dichter Index (Sekundärorganisation): Die Indexdatei enthält n Einträge und benötigt daher nd Blöcke. Die binäre Suche benötigt log2 ( nd ) Zugriffe1 . Um den Datensatz in der
Hauptdatei zu lesen, wird ein weiterer Zugriff benötigt.
8.2.4 Physische Datenorganisation in kommerziellen DBMS
Von relationalen Datenbanken werden unterschiedliche Arten der Datenorganisation angeboten. Nachfolgend werden die Möglichkeiten von INGRES, ORACLE und MSQL Server
aufgezeigt.
8.2.4.1 INGRES
Ingres bietet eine große Auswahl von unterschiedlichen Dateiorganisationen:
Heap: entspricht einer ungeordneten Datei – Die Sätze werden ungeordnet sequentiell gespeichert und sequentiell gelesen. Alle Blöcke werden immer voll gefüllt.
Hash: ist eine (interne) Hashorganisation, es muss ein Schlüssel dafür angegeben werden
(Index sequential access method).
Isam: entspricht einer geordneten Datei mit einem Primärindex.
Btree: implementiert eine ungeordnete Datei mit einem B ∗ -Baum als Zugriffsstruktur.
Zusätzlich können bei jeder der beschriebenen Varianten sekundäre Indexe definiert werden, wahlweise als Hash, Isam oder Btree.
8.2.4.2 ORACLE
ORACLE benutzt B ∗ -Baum-Indexe und ungeordnete Dateien, die mit INGRES-heap vergleichbar sind.
ORACLE bietet darüber hinaus die Möglichkeit des clusterings (siehe Abschnitt 8.1.1).
Wird das clustering auf eine Relation angewendet, dann entspricht dies einer Sortierung nach
einem Nichtschlüsselfeld – alle Tupel, in denen das clustering-Feld auftritt, werden zusammen
gespeichert. Mit der gleichen Vorgehensweise, allerdings bei Sortierung nach dem Primärschlüssel, kann in ORACLE eine indexsequentielle Primärorganisation erreicht werden.
8.2.4.3 MS-SQL Server
MS-SQL Server stellt ungeordnete Dateien und geordnete Dateien mit Indexen als Primärund Sekundärorganisation zur Verfügung. Unter einem Clustered Index wird in diesem Fall
die Speicherung einer Datei geordnet nach einem Index-Attribut verstanden. Es gibt keine
Möglichkeit verschiedene Dateien auf einer Seite zu speichern.
1
Vgl. Kommentar zur Indexsequentiellen Datei.
Teil III
Das Datenbankmanagementsystem
1
Kapitel 9
Optimierung
Höhere, nichtprozedurale Abfragesprachen wie z.B. SQL oder QBE verlangen keine Kenntnisse des Benutzers über die Implementierung, müssen aber zur Ausführung vom System
selbst in eine andere Form (z.B. Relationenalgebra) umgesetzt werden. Um eine effiziente
Bearbeitung von Abfragen zu erzielen, gibt es eine interne Umformulierung der Abfragen in
eine optimierte Form (Query Optimization). Die dabei verwendeten Strategien erzielen keine
optimale Lösung, sondern meist nur eine Verbesserung. Wir stellen im nächsten Abschnitt
einen Algorithmus vor, der zur Optimierung verwendet wird. Weiters gibt es unterschiedliche Strategien zur Durchführung von Joins, die, wie wir sehen werden, zu den aufwendigsten
Operationen bei der Ausführung einer Abfrage zählen. In Abschnitt 9.2 stellen wir einige der
in der Praxis verwendeten Algorithmen vor. Im letzten Abschnitt dieses Kapitels zeigen wir,
wie die Operation des Semijoins verwendet werden kann, um Joins von Relationen, die in
einer verteilten Datenbank gespeichert sind, zu optimieren.
9.1 Logische Abfragenoptimierung
Die aufwendigste Operationen in relationalen Sprachen sind kartesisches Produkt und Join.
Bei einfachster Implementierung eines Joins zwischen A und B ist ein Durchlauf aller Tupel
von B für jedes Tupel von A notwendig. Sei n die Anzahl der Tupel von A, m die Anzahl der
Tupel von B, so beträgt der Aufwand zur Berechnung des Joins oder kartesischen Produktes
O(nm). Besonders aufwendig werden diese Operationen in verteilten Datenbanken.
• Die Projektion ist aufwendig, da die durch das Projizieren entstandenen Duplikate entfernt werden müssen.
• Wenn die Selektionen so früh wie möglich durchgeführt wurde, führt das zu kleineren
Zwischenresultaten und erleichtert somit die nachfolgenden Operationen.
• Unäre Operationen bedingen je einen Durchlauf aller Tupel, daher sollten mehrere
möglichst zusammengezogen werden.
1
KAPITEL 9. OPTIMIERUNG
9.2
−
πX
πX
./
./
s
r
./
q
s
r
Abbildung 9.1: Darstellung der Abfrage aus Beispiel 9.1 in einem Operatorbaum
• Gemeinsame Teilausdrücke brauchen nur einmal ausgewertet werden. Der Aufwand
kann dadurch reduziert werden.
Der Zeitaufwand für das Untersuchen der verschiedenen Möglichkeiten, eine Abfrage
durchzuführen, ist im allgemeinen viel geringer als für das Durchführen einer ineffizienten
Abfrage.
9.1.1 Algebraische Optimierung
Bei der algebraischen Optimierung verwenden wir zur Darstellung von Abfragen einen Operatorbaum.
Beispiel 9.1 Wir stellen den Ausdruck πX (s ./ r) − πX (q ./ r ./ s) in Abbildung 9.1 in
einem Operatorbaum dar.
Der Operatorbaum wird Bottom-up ausgewertet. Daher ist es für die Laufzeit nicht günstig,
wenn die Join-Operatoren nahe bei den Blättern stehen. Andererseits steigt der Zeit- und
Platzaufwand binärer Operationen mit der Anzahl der Tupel und der Anzahl der Attribute in
den Argumentrelationen. Eines der Grundprinzipien bei der Optimierung ist daher, die unären
Operatoren in Richtung der Blätter des Baumes zu verschieben, um eine möglichst frühzeitige
Reduktion der Größe der Operanden von binären Operationen (Join, Differenz etc.) zu bewirken. Außerdem erreichen wir durch die Zusammenfassung unärer Operationen, dass diese in
einem Schritt durchgeführt werden. Da Projektion eine Entfernung doppelter Tupel bedingt,
ist es besser, die Selektion möglichst vor der Projektion durchzuführen.
KAPITEL 9. OPTIMIERUNG
9.3
9.1.1.1 Zusammenfassen gleicher Teilausdrücke
Das Zusammenfassen gleicher Teilausdrücke geschieht in einem Baum von unten nach oben.
Dabei werden die Ausdrücke schrittweise zusammengefasst. Allerdings können algebraische
Transformationen die Existenz gleicher Teilausdrücke verschleiern.
Beispiel 9.2 Betrachten wir nochmals den in Abbildung 9.1 dargestellten Operatorbaum. In
einem ersten Schritt fassen wir die Blätter s und r zusammen, im zweiten den Join, der die
beiden Relationen verbindet. Es folgt, dass wir die Operation s ./ r nur einmal durchführen
müssen.
9.1.1.2 Regeln für Join und kartesisches Produkt
Der Join und das kartesische Produkt sind kommutativ und assoziativ.
1. Kommutativität:
E1 ./ E2 ≡ E2 ./ E1
E1 × E 2 ≡ E 2 × E 1
2. Assoziativität:
(E1 ./ E2 ) ./ E3 ≡ E1 ./ (E2 ./ E3 )
(E1 × E2 ) × E3 ≡ E1 × (E2 × E3 )
9.1.1.3 Regeln für Selektion und Projektion
In diesem Abschnitt beschreiben wir, unter welchen Umständen wir Selektion und Projektion
in Richtung der Blätter verschieben können.
3. Zusammenfassung von Projektionen: Die Zusammenfassung von zwei Projektionen zu
einer geht nur unter der Voraussetzung, dass die Menge der Attribute der äußeren Projektion eine Teilmenge der Attribute der inneren Projektion ist. Formal:
falls {Ai | i = 1, ..., n} ⊆ {Bi | i = 1, ..., m} so gilt:
πA1 ,...,An (πB1 ,...,Bm (E)) ≡ πA1 ,...,An (E)
4. Zusammenlegung/Kommutativität von Selektionen:
σF1 (σF2 (E)) ≡ σF1 ∧F2 (E)
σF1 (σF2 (E)) ≡ σF2 (σF1 (E))
KAPITEL 9. OPTIMIERUNG
9.4
5. Kommutativität Selektion-Projektion: Die Projektion ist mit der Selektion eingeschränkt
kommutativ. Wenn sich die Bedingung F der Selektion nur auf Attribute A i bezieht,
nach denen projiziert wird, so gilt
πA1 ,...,An (σF (E)) ≡ σF (πA1 ,...,An (E))
Wenn sich F auf alle Attribute Bj und möglicherweise auf Attribute Ai bezieht, dann
gilt
πA1 ,...,An (σF (E)) ≡ πA1 ,...,An (σF (πA1 ,...,An,B1 ,...,Bm (E)))
Das bedeutet, dass wir nur nach jenen Attributen zuerst projizieren dürfen, die wir in
der Selektion noch brauchen. Erst in einem zweiten Schritt können wir die gewünschte
Projektion durchführen.
6. Kommutativität Selektion-Kartesisches Produkt: Die Selektion kommutiert mit dem kartesischen Produkt nur unter der Bedingung, dass sich F = F1 ∧ F2 auf die Attribute von
E1 und E2 beschränkt. Wenn sich Fi nur auf Attribute von Ei beziehen, so gilt
σF (E1 × E2 ) ≡ σF1 (E1 ) × σF2 (E2 )
Wenn F1 sich nur auf Attribute von E1 , F2 aber auf Attribute von E1 und E2 bezieht, so
gilt:
σF (E1 × E2 ) ≡ σF2 (σF1 (E1 ) × E2 )
7. Kommutativität Selektion-Vereinigung:
σF (E1 ∪ E2 ) ≡ σF (E1 ) ∪ σF (E2 )
8. Kommutativität Selektion-Mengendifferenz/Durchschnitt:
σF (E1 − E2 ) ≡ σF (E1 ) − σF (E2 )
Daher gilt natürlich analog auch die Kommutativität zwischen Selektion und Durchschnitt (überlegen Sie sich warum)!
9. Kommutativität Projektion-Kartesisches Produkt: Seien Bi Attribute von E1 , Ci Attribute von E2 und {Ai | i = 1, ..., n} = {Bi | i = 1, ..., m} ∪ {Ci | i = 1, ..., k}, so
gilt:
πA1 ,...,An (E1 × E2 ) ≡ πB1 ,...,Bm (E1 ) × πC1 ,...,Ck (E2 )
KAPITEL 9. OPTIMIERUNG
9.5
πnname,gehalt,name
σhaube>2∧preis>30
./
./
Speise
Mitarbeiter
Restaurant
Abbildung 9.2: Operatorbaum zur Abfrage aus Beispiel 9.3
10. Kommutativität Projektion-Vereinigung:
πA1 ,...,An (E1 ∪ E2 ) ≡ πA1 ,...,An (E1 ) ∪ πA1 ,...,An (E2 )
Der Join ist darstellbar als Kombination von kartesischem Produkt, Projektion und Selektion. (Wollen wir zwei Relationen R1 und R2 nach dem Attribut A joinen, so müssen wir
zuerst das kartesische Produkt der beiden Relationen bilden, wobei wir das Attribut A einmal umbenennen müssen, da das Ergebnis ansonsten zwei gleiche Attribute enthält. Dann
selektieren wir jene Tupel, die auf A und dem umbenannten Attribut gleich sind, und zum
Schluss projizieren wir das umbenannte Attribut wieder weg.) Daher folgen die Regeln für
Kommutativität von Selektion und Join aus den Regeln 4, 5, und 6.
Es gilt keine Kommutativität zwischen Mengendifferenz und Projektion und daher auch
keine Kommutativität zwischen dem Durchschnitt und der Projektion (überlegen Sie sich
warum)!
9.1.2 Ein einfacher Optimierungsalgorithmus
1. Zerlege Selektionen der Art σF1 ∧...∧Fn (E) nach Regel 4 in σF1 (...(σFn (E))...).
2. Schiebe jede Selektion soweit wie möglich in Richtung Blätter mit den Regeln 4-8.
3. Schiebe jede Projektion soweit wie möglich in Richtung Blätter mit den Regeln 3,5,9
und 10.
4. Fasse alle direkt aufeinanderfolgenden Selektionen und Projektionen zu einer einzigen
Selektion, einer einzigen Projektion oder einer Selektion gefolgt von einer Projektion
mit den Regeln 3-5 zusammen.
KAPITEL 9. OPTIMIERUNG
9.6
πnname,gehalt,name
πnname,gehalt,name
./
./
πname,rnr
./
πrnr
σpreis>300
πpreis,rnr
Speise
πnname,gehalt,rnr
πname,rnr
Mitarbeiter
πrnr,name
πrnr
σhaube>2
σpreis>300
πrnr,name,haube
Restaurant
./
Speise
πnname,gehalt,rnr
Mitarbeiter
πrnr,name
σhaube>2
Restaurant
Abbildung 9.3: Operatorbaum nach Verschiebung der Selektion und Projektion und der optimierte Operatorbaum
Beispiel 9.3 Betrachten wir die Relationenschemata Restaurant, Speise und Mitarbeiter
aus R EINE. Wir wollen folgende Abfrage formulieren: Wie hoch ist das Gehalt und wie ist
der Name der Mitarbeiter, die in Restaurants mit mehr als 2 Hauben arbeiten, in denen es
Speisen zu mehr als 30 Euro gibt, und wie heißen die Restaurants? Die Abfrage sieht in SQL
wie folgt aus:
select distinct m.nname, m.gehalt, r.name
from mitarbeiter m, restaurant r, speise s
where m.rnr = r.rnr and
r.haube > 2 and
r.rnr = s.rnr and
s.preis > 30;
In Relationale Algebra übersetzt ergibt sich folgende Abfrage:
πnname,gehalt,name [σhaube>2∧preis>30 (Mitarbeiter ./ Restaurant ./ Speise)]
Den Operatorbaum zu dieser Abfrage sehen wir in Abbildung 9.2
Im nächsten Schritt verschieben wir die Selektion nach den Regeln 4-8 so weit wie möglich
in Richtung der Blätter, danach die Projektion nach den Regeln 3, 5, 9 und 10 (siehe Abbildung 9.3).
Zum Schluss fassen wir die Kaskaden von Selektionen und Projektionen zusammen (Regeln 3 und 4), was in diesem Beispiel nicht notwendig ist, aber Regel 5 ist zweimal anwendbar,
also werden die zwei untersten Projektion mit den darüberliegenden Selektionen permutiert
und mit der nächsten Projektion verschmolzen. Das garantiert uns, dass die Selektion zuerst
ausgeführt wird. Den optimierten Operatorbaum sehen wir in Abbildung 9.3.
KAPITEL 9. OPTIMIERUNG
A
B
9.7
B
C
1 2
Abbildung 9.4: Verbesserte Lösung des nested-loop Join
9.2 Join-Algorithmen
Wir haben in Kapitel 8 gesehen, wie die Daten der Datenbank in Haupt- bzw. Hintergrundspeicher gehalten werden. Bei der Abarbeitung einer Abfrage müssen die Daten zur Bearbeitung in den Hauptspeicher geladen werden. Join-Algorithmen, d.h. Algorithmen, die den
Verbund durchführen, sind, da der Verbund die aufwendigste Operation ist, kritisch für das
Laufzeitverhalten einer Abfrage. Wir beschreiben in den nächsten Abschnitten die Prinzipien der wichtigsten Algorithmen zur Ausführung des Verbunds zweier Relationen R(A, B) und
S(BC) (kurz: AB ./ BC). Wir gehen dabei davon aus, dass die Relationen in verschiedenen
Dateien gespeichert sind.
9.2.1 Nested-loop Join
Die einfachste Lösung ist die Ausführung des Verbundes mit zwei Schleifen (nested-loop
Join). Beim primitiven nested-loop Join werden in der äußeren Schleife alle Tupel der Datei R
durchlaufen und für jedes Tupel ab in der inneren Schleife alle Tupel der Datei S durchlaufen,
wobei für jedes Tupel b0 c der Datei S, für das b = b0 gilt, das Tupel abc gebildet wird. Beim
primitiven nested-loop Join wird jeder Block der Datei S so oft gelesen, wie R Sätze hat:
nR
nS
nR
+
bR
bS
m−1
wobei nR die Anzahl der Sätze in R, nS die Anzahl der Sätze in S, bR die Anzahl der Sätze
von R in einem Block, bS die Anzahl der Sätze von S in einem Block und m die Anzahl der
Blöcke im Hauptspeicher ist (d e = nächst größere ganze Zahl).
Beim verbesserten nested-loop Join (vgl. Abbildung 9.4) werden in der äußeren Schleife
soviele Blöcke der Datei R wie möglich in den Hauptspeicher geladen, wobei jedoch Platz
für einen Block der Datei S gelassen wird. In der inneren Schleife werden nacheinander
alle Blöcke von S gelesen, wobei für jeden Block jedes Tupel b 0 c nicht nur mit einem Tupel
ab, sondern mit allen Tupeln der Datei R, die sich im Hauptspeicher befinden, verglichen
KAPITEL 9. OPTIMIERUNG
9.8
A
B
B
C
u
v
w
x
A
B
B
C
u
u
v
v
w
w
x
x
Abbildung 9.5: Join mit Index über S, bzw über R und S
wird. Danach werden alle Blöcke der Datei R im Hauptspeicher auf einmal ausgetauscht und
der nächste Durchlauf von S wird ausgeführt. Der Aufwand (gemessen an der Anzahl der
Blocktransfers zwischen Hauptspeicher und Sekundärspeicher) für den verbesserten nestedloop Join beträgt:
nS
nR
nR
+
bR
bS
(m − 1)bR
9.2.2 Join mit Hilfe von Indexen
Hat eine der beiden Dateien einen Index auf das Join-Attribut B, dann kann der Verbund in
einem Schleifendurchlauf durchgeführt werden. Wenn etwa auf S ein Index für B liegt, dann
werden in einer Schleife über R für jedes durchlaufene Tupel ab die Tupel b 0 c mit b = b0 über
den Index gesucht. (vgl. Abbildung 9.5).
Wenn sowohl auf R als auch auf S ein Index für B liegt, dann können wir den Join als
Merge-Operation durchführen. Der Aufwand dabei ist ungefähr
nR
nS
d e+d e
bR
bS
wenn wir annehmen, dass genügend Pufferspeicher für die verbundfähigen Datensätze mit
gleichem Attributwert vorhanden ist.
KAPITEL 9. OPTIMIERUNG
9.9
Abbildung 9.6: Illustration: Hash-Join
R
S
R1
S1
R2
S2
R3
S3
Abbildung 9.7: Der Hash-Join
Wenn wir vor dem Durchführen des Joins zuerst beide Dateien nach dem Join-Attribut
B sortieren und danach die Dateien mischen, so erhalten wir das selbe Ergebnis. Dieses
Verfahren heißt sort-merge Join (vgl. Abbildung 9.5).
9.2.3 Hash-Join
Beim Hash-Join wird zunächst in je einem Durchlauf durch beide Dateien ein Hashindex auf
das Join-Attribut B gelegt. Danach partitionieren wir die Operandenrelationen R, S in Buckets
Ri , Si in Abhängigkeit vom Wert der Join-Attribute; alle Tupel mit gleichem Attributwert
liegen im selben Bucket. Allerdings können auch mehrere verschiedene Werte pro Bucket
vorkommen.
Im zweiten Schritt führen wir den Join durch: für jedes Paar Buckets wird der Join mit
einem normalen“ Verfahren gebildet. Zuletzt vereinigen wir die Einzelresultate, d.h., wir
”
ersetzen einen großen Join durch mehrere kleine, wie wir in Abbildung 9.7 sehen können.
R ./ S =
n
[
Ri ./ Si
i=1
9.2.4 Clustering
Beim Clustering sind die zu verknüpfenden Tupel der Operanden bereits in denselben Blöcken
gespeichert, daher benötigen wir nur einen Zugriff auf jeden Block der beiden Relationen. Das
Problem dabei ist aber der aufwendige Aufbau einer geclusterten Datei. Weiters ist Clustering
nur für einen Join pro Relation möglich.
KAPITEL 9. OPTIMIERUNG
9.10
9.3 Der Semijoin (Semiverbund)
Am Ende dieses Kapitels wollen wir noch zeigen, wie der Semijoin verwendet werden kann,
um Verbundoperationen auf verteilten Datenbanken zu beschleunigen.
Wenn in einer verteilten Datenbank ein Teil der Tabellen an einem Knoten, der andere an
einem anderen Knoten gespeichert ist, und wir zwei Relationen verbinden wollen, die nicht
am selben Knoten liegen, so kann es sehr aufwendig sein, eine ganze Tabelle von einem
Knoten zum anderen zu übertragen.
Sei R eine Relation, die auf dem Knoten 1 gespeichert ist, S eine Relation auf dem Knoten
2 und B das gemeinsame Attribut. Wenn wir an einem Verbund der beiden Relationen auf
Knoten 1 interessiert sind, so ist eine Lösung, Relation S zu Knoten 1 zu schicken und den
Verbund durchzuführen. Es kann aber sein, dass nicht alle Tupel, oder nur ein kleiner Teil
der Tupel von S den Verbund mit R eingehen können und wir daher viele Daten umsonst
übertragen. Als Lösung bietet sich folgende Vorgangsweise an:
1. Wir schicken zuerst r0 = πB (r) von 1 nach 2.
2. Wir bilden s0 = s ./ r0 auf Knoten 2.
3. Wir schicken s0 von 2 nach 1.
4. Wir bilden r ./ s0 .
s0 ist gerade der Semijoin s n r.
Beispiel 9.4 Seien die folgenden Relationen R und S auf den Knoten 1 und 2 gegeben.
R
(A
1
1
1
2
2
3
3
3
B)
4
5
6
4
6
7
8
9
S
(B
4
4
7
1
1
2
2
2
C
10
11
12
12
12
23
14
15
D)
12
13
14
12
13
14
15
16
R0 = πB (R)
(B)
4
5
6
7
8
9
S0 = S ./ R0
(B C D)
4 10 12
4 11 13
7 12 14
Wir sind an einem Verbund von R und S auf Knoten 1 interessiert. Wenn wir S von Knoten 2
nach Knoten 1 schicken, so müssen wir 3 ∗ 8 = 24 Attributwerte übertragen, wobei die letzten
5 Tupel übertragen werden, obwohl wir sie für den Verbund nicht benötigen. Verwenden wir
obigen Algorithmus, so übertragen wir zuerst R0 (6 Attributwerte) von Knoten 1 nach 2 und
dann S0 (3 ∗ 3 Attributwerte), alle Tupel, die den Verbund mit R eingehen können, von Knoten
2 nach Knoten 1. In diesem Fall übertragen wir in Summe nur 15 Attributwerte.
KAPITEL 9. OPTIMIERUNG
9.11
9.4 Übungsbeispiele
Übung 9.1 Geben Sie für folgende Ausdrücke den Operatorbaum an, und wenden Sie die
algebraische Optimierung darauf an. Die Schemata der Datenbank sind q(AB)D), r(BDF )
und s(F G).
1. σD=d (πBDF (q ./ r) − πBDF (r ./ s))
2. πAD (q ./ r ./ σG=g (s))
3. πB (σA=a (σD=d (q) ./ (r − πBDF (r ./ s))))
Übung 9.2 Gegeben sind die Relationen q(ABC), r(BCD) und s(DE) sowie folgender
Ausdruck der Relationalen Algebra
πAE σB=b πAEB σ(E<e)&(C>c) ((q ./ r) ./ s)
Geben Sie den zugehörigen Operationsbaum an und optimieren Sie den Ausdruck algebraisch.
Übung 9.3 Gegeben sind die Relationen r(ABC), q(BDF ), s(BEF ) und folgender Ausdruck der Relationenalgebra:
πAB σB>b πABC σ(D=d)∨(E=e) (r ./ (q ./ s))
Geben Sie den zugehörigen Operationsbaum an und optimieren Sie den Ausdruck algebraisch.
Übung 9.4 Gegeben sind die Relationen q(ABG), r(BCD) und s(CDEF ) und folgender
Ausdruck der Relationenalgebra:
πAE σE=e πACEG σ(B<b)&(D>d) (q ./ (r ./ s))
Geben Sie den zugehörigen Operationsbaum an und optimieren Sie den Ausdruck algebraisch.
Übung 9.5 Gegeben sind die Relationenschemata: p(BCDF G), q(BDF ), r(BCDEG).
Optimieren Sie den folgenden algebraischen Ausdruck:
σB=3∧D>5 (πBDF (p − (q ./ πCG (r))))
Übung 9.6 Gegeben sind die Relationenschemata: a(BCD), b(ADE), c(ABE). Optimieren
Sie den folgenden algebraischen Ausdruck:
σB=3∨C<6 πBCD ( (c ./ πCD (a)) ∪ σE6=5 (a ./ b) )
KAPITEL 9. OPTIMIERUNG
9.12
Übung 9.7 Gegeben sind die Relationenschemata: p(ABC), q(CDE), r(ADE). Optimieren
Sie den folgenden algebraischen Ausdruck:
σB=5∨A<3 πABC ( (r ./ πBC (p)) ∪ σD6=5 (p ./ q) )
Übung 9.8 Gegeben sind die Relationen q(ABE), r(BCDFE) und s(ABD). Optimieren Sie
den folgenden Ausdruck algebraisch:
πAB σ(D=d)∧(A>a) ((πABD (q ./ r)) − s)
Übung 9.9 Gegeben sind folgende zwei Relationen p und q:
p (A
a1
a1
a2
a2
a2
a2
a2
B
b1
b2
b1
b1
b1
b2
b2
C)
c1
c1
c2
c4
c6
c8
c9
q (C
c1
c1
c3
c5
c6
c7
D)
d1
d2
d1
d2
d2
d1
Berechnen Sie p n q. Angenommen p und q sind auf verschiedenen Rechnern, p ./ q
wird auf dem Knoten 2 benötigt. Wieviele Attributwerte müssen bei der Bildung von p ./ q
übertragen werden, wieviele bei vorheriger Bildung des Semijoin?
Übung 9.10 Gegeben sind folgende zwei Relationen r und s:
r
(A
a1
a2
a2
B
b1
b2
b2
C)
c1
c1
c2
s (B
b1
b3
b4
D)
d1
d1
d2
Berechnen Sie r n s.
Angenommen, r ist auf dem Rechner 1, s auf dem Rechner 2 gespeichert. Sie benötigen
r ./ s auf dem Rechner 2. Um wieviele Attributwerte müssen bei vorheriger Bildung des
Semiverbundes weniger zwischen den Rechnern übertragen werden als ohne Verwendung
eines Semiverbundes?
Übung 9.11 Gegeben sind r(A B C) und s(C D E). Berechnen Sie q1 = r n s:
r(
A B C)
a1 b1 c1
a2 b2 c3
a2 b3 c3
s (C D E)
c1 d1 e1
c1 d2 e1
c2 d2 e1
c1 d3 e4
KAPITEL 9. OPTIMIERUNG
9.13
Angenommen, r und s sind auf verschiedenen Rechnern, R1 und R2, und r ./ s wird auf
dem Rechner R2 benötigt. Wieviele Attributwerte müssen ohne, wieviele mit Verwendung
eines Semijoins übertragen werden.
Übung 9.12 Ist das Verfahren mit Bilden des Semijoin p n q beschrieben immer effizienter
als die normale Vorgangsweise“ ? Begründen Sie die Antwort (Beweis oder Gegenbeispiel).
”
Übung 9.13 Welche der Operationen ./ (join) und n (semijoin) sind
1. kommutativ,
2. assoziativ?
9.14
KAPITEL 9. OPTIMIERUNG
Kapitel 10
Mehrbenutzerkontrolle (Concurrency
Control)
In den letzten beiden Kapiteln beschäftigen wir uns mit zwei Grundaufgaben eines Datenbankmanagementsystems, nämlich der parallelen Verarbeitung von Benutzeraufträgen und
der Realisierung eines bestimmten Grades der Fehlertoleranz.
Da im Allgemeinen mehrere Benutzer gleichzeitig auf eine Datenbank zugreifen, muss
das DBMS sicherstellen, dass die Benutzeraufträge einander bei der Abarbeitung nicht stören
und die Benutzer auch nichts voneinander bemerken. Diese Anforderungen werden von der
Concurrency-Control Komponente eines DBMS erfüllt. Weiters soll das System von sich
aus mit gewissen Fehlersituationen, wie etwa einem Plattenfehler, umgehen können. Diese
Anforderung wird von der recovery-Komponente des DBMS realisiert.
10.1 Begriffskl¨
arungen
Eine Datenbank ist konsistent, wenn sie eine Menge vorgegebener logischer Bedingungen
erfüllt, die Integritätsbedingungen genannt werden.
Ein Benutzer verwendet eine Datenbank, indem er eine logisch zusammengehörende Folge von Zugriffsbefehlen (Lese- und Schreib-Befehle) auf dieser Datenbank ausführt. Eine derartige Befehlsfolge wird Transaktion genannt und führt die Datenbank von einem konsistenten
Zustand in einen anderen, nicht notwendigerweise verschiedenen, konsistenten Zustand über
(z.B. Umbuchung von Lohnkonto auf Sparbuch).
Beispiel 10.1 Betrachten wir eine Transaktion, die 500 Euro von Konto 123 abbucht und auf
das Sparbuch 333 bucht. Wir haben dabei die Relationen Sparbuch(spnr, einlage) und
Konto(knr, kstand) zur Verfügung. Die entsprechende Transaktion sieht wie folgt aus:
begin transaction
update konto
1
KAPITEL 10. CONCURRENCY CONTROL
10.2
set kstand=kstand-500
where knr=123;
update sparbuch
set einlage=einlage+500
where spnr=333;
end transaction
Für die Abarbeitung dieser Transaktion muss das DBMS folgende Schritte durchführen:
1. Syntaxüberprüfung und Autorisierungskontrolle
2. Wahl einer Methode zur Ausführung der Operationen (Query-Optimierung)
3. Feststellung, wie die Relationen gespeichert sind und wie auf diese Datenstrukturen
zugegriffen werden kann (Indexe)
4. Erzeugung von ausführbarem Code, der
• die Relationen aus der Datenbank (dem Hintergrundspeicher) in den DatenbankPuffer (im Hauptspeicher) transferiert,
• die oben gewählte Methode implementiert,
• das Ergebnis ausgibt.
5. Ausführen des Codes.
Wenn wir davon ausgehen, dass wir einen Index über die Attribute knr und spnr angelegt
haben, so wäre ein mögliches Programm zur Ausführung der Abfrage:
1. Lade Index von Konto in den Hauptspeicher, suche die passende Kontonummer, lade
die entsprechende Seite der Datenbank und verändere den Kontostand.
2. Lade Index von Sparbuch in den Hauptspeicher, suche die passende Sparbuchnummer,
lade die entsprechende Seite der Datenbank und verändere den Einlagenstand.
Dieser Algorithmus läuft, wie jedes Programm, im Hauptspeicher des betreffenden Datenbankrechners ab, wobei es allerdings Zugriff auf einen Teil des Datenbank-Puffers hat, in
welchen Daten aus der Datenbank zur Bearbeitung eingelagert und von wo aus die geänderten
Daten wieder in die Datenbank übernommen werden.
Für jeden Benutzer einer Datenbank werden die Zugriffe auf die Daten über Transaktionen realisiert. Für jede der Transaktionen werden die oben angeführten Schritte durchgeführt.
Daher wird für jede Transaktion ein Programm erstellt und ein eigener Bereich im DatenbankPuffer bereit gestellt, von wo aus die Daten der Datenbank gelesen bzw. wohin sie geschrieben werden. Es kann daher passieren, dass zwei Transaktionen zur gleichen Zeit nicht nur auf
KAPITEL 10. CONCURRENCY CONTROL
10.3
derselben Datenbank, sondern auch auf demselben Datensegment arbeiten wollen, z.B. Änderung des Kontostandes des Kontos mit der Kontonummer 123. Beide Transaktionen haben
sich die Datenbankseite mit dem aktuellen Kontostand in ihren privaten Datenbank-Puffer geladen und verändern den Kontostand. Danach wird die veränderte Datenbankseite wieder in
die Datenbank im Hintergrundspeicher geschrieben. In diesem Fall ist eine Synchronisation
notwendig, damit die Effekte auf der Datenbank so sind, als ob zuerst die eine Transaktion,
danach die zweite Transaktion den Kontostand geändert hätte.
Definition 10.1 Mehrere Transaktionen heißen parallel, wenn ihr Programmcode gleichzeitig im Hauptspeicher des Datenbankrechners existiert.
Wenn wir eine Transaktion als ein Datenbankprogramm betrachten, so sehen wir, dass
der eigentlich kritische Punkt an der Abarbeitung jener ist, wo die Daten aus der Datenbank
gelesen, bzw. in die Datenbank geschrieben werden, da diese Zugriffe sich unter Umständen
gegenseitig stören können. Die restliche Ausführung des Programmes läuft unter der Kontrolle des jeweiligen Betriebssystems ab. Diese Abstraktion einer Transaktion auf Lese- und
Schreibzugriffe ist ausreichend, um eine Theorie der Synchronisation und der Fehlerbehandlung aufbauen zu können, die in den kommerziellen Systemen angewendet wird.
10.1.1 Synchronisationsprobleme
Wir wollen nun anhand von drei Beispielen aufzeigen, zu welchen Problemen es kommen
kann, wenn mehrere Transaktionen auf dieselben Daten zugreifen, diese Zugriffe aber nicht
korrekt synchronisiert sind.
Beispiel 10.2 Zwei Transaktionen T1 und T2 wollen dasselbe Datenobjekt x (z.B. den Kontostand des Kontos 123) verändern, nämlich im ersten Fall 2.000 Euro aufbuchen, im zweiten
Fall 5.000 Euro abbuchen.
Zeit
1
2
3
4
5
6
T1
READ(x)
T2
READ(x)
UPDATE(x)
UPDATE(x)
WRITE(x)
WRITE(x)
Dieses Problem nennt sich Lost Update, denn das Update der Transaktion T 1 geht verloren. Generell ist unerheblich, was die Transaktionen in ihrem Puffer mit dem Objekt x
machen, entscheidend ist, dass T2 unkontrolliert auf die Datenbank schreibt und dadurch die
Schreiboperation von T1 überschreibt.
KAPITEL 10. CONCURRENCY CONTROL
10.4
Beispiel 10.3 Zwei Transaktionen T1 und T2 wollen dasselbe Datenobjekt x verändern. Die
erste Transaktion wird aber nach der Veränderung von x aufgrund eines Fehlers abgebrochen.
Zeit
1
2
3
4
5
6
7
T1
T2
READ(x)
UPDATE(x)
WRITE(x)
READ(x)
UPDATE(x)
ABORT
WRITE(x)
Offensichtlich liest T2 einen falschen Wert, da nach dem Abbruch von T1 die Veränderungen von T1 wieder rückgängig gemacht werden müssen. Dieses Problem nennt sich Dirty
Read.
Beispiel 10.4 Eine Transaktion T1 berechnet die Summe dreier Werte, z.B. dreier Kontostände,
während T2 eine Umbuchung von einem der drei Kontos auf ein zweites durchführt.
Zeit
1
2
3
4
5
6
7
8
9
10
11
12
13
T1
SUM := 0
READ(x)
READ(y)
SUM := SUM + x
SUM := SUM + y
T2
READ(z)
UPDATE(z)
WRITE(z)
READ(x)
UPDATE(x)
WRITE(x)
READ(z)
SUM := SUM + z
T1 berechnet offensichtlich den falschen Wert, da sie den Wert von x vor der Veränderung, den Wert von z aber erst nach der Veränderung durch T 2 liest. Dieses Problem heißt
Inconsistent Read oder Unrepeatable Read.
Um bei der Abarbeitung mehrerer paralleler Transaktionen solchen Problemen aus dem
Weg zu gehen, ist eine Synchronisation der einzelnen Lese- und Schreibzugriffe auf die Datenbank notwendig, die auch mit bestimmten Fehlersituationen (etwa Transaktionsabbrüchen)
umgehen kann. Das Transaktionskonzept dient dazu, diese Probleme zu lösen, damit es nach
außen für jeden Benutzer scheint, als ob nur seine Abfrage aktiv sei und verschiedene Transaktionen immer nur seriell, d.h. eine nach der anderen und nicht parallel, so wie in den drei
letzten Beispielen, ablaufen.
KAPITEL 10. CONCURRENCY CONTROL
10.5
10.1.2 ACID Eigenschaften von Transaktionen
Wir erwarten klarerweise, dass eine Transaktion wie geplant abläuft und die vorgesehenen
Schritte tätigt. Bei der Ausführung von einer bzw. von mehreren Transaktionen kann es aber
zu Störungen bzw. Fehlern kommen, die das verhindern. Um diese Störungen auszuschließen,
werden gewisse Eigenschaften von Transaktionen gefordert. Diese sind Atomarität, Parallelität, Isolation und Dauerhaftigkeit. Nach den Anfangsbuchstaben der englischen Bezeichnungen werden sie auch ACID Eigenschaften genannt.
Atomarität (atomicity): Eine Transaktion wird entweder zur Gänze oder gar nicht ausgeführt.
Wenn nicht alle Operationen einer Transaktion ausgeführt werden können, so muss diese abgebrochen werden, und bereits ausgeführte Änderungen müssen rückgängig gemacht werden.
Beispiel 10.5 Bei der Umbuchungstransaktion aus Beispiel 10.1 müssen wir sicherstellen,
dass beide Aktionen durchgeführt werden, einerseits die Abbuchung vom Lohnkonto, andererseits die Buchung auf das Sparbuch. Bricht die Transaktion nach der Abbuchung und vor
der Buchung ab, so wäre das eine Verletzung der Atomarität.
Parallelität (concurrency): Das Gesamtergebnis einer parallelen Ausführung von Transaktionen entspricht irgendeiner Hintereinanderausführung dieser Transaktionen. (Da eine Transaktion alleine konsistenzerhaltend ist, ist auch eine Hintereinanderausführung konsistenzerhaltend.)
Beispiel 10.6 Angenommen neben der Umbuchungstransaktion aus Beispiel 10.1 findet eine
Transaktion statt, die eine Bankomatbehebung vom Lohnkonto abbucht. Der Gesamteffekt ist
entweder:
1. vom Lohnkonto abbuchen und am Sparbuch aufbuchen,
2. vom verringerten Lohnkontostand den am Bankomat abgehobenen Betrag abziehen.
oder
1. Lohnkontostand um den beim Bankomat abgehobenen Betrag verringern,
2. vom verringerten Lohnkontostand abbuchen und am Sparbuch aufbuchen.
Isolation: Teilergebnisse von Transaktionen bleiben bis zum Ende der Transaktion für alle
anderen Transaktionen unsichtbar.
Beispiel 10.7 Bei der Umbuchungstransaktion wird die Abbuchung vom Lohnkonto erst sichtbar, nachdem auch die Aufbuchung aufs Sparbuch durchgeführt worden ist.
Dauerhaftigkeit (durability): Die Ergebnisse einer erfolgreich durchgeführten Transaktion
bleiben erhalten.
KAPITEL 10. CONCURRENCY CONTROL
10.6
Beispiel 10.8 Nach der Durchführung der Umbuchung muss der neue Kontostand sowohl
auf dem Lohnkonto als auch auf dem Sparbuch aufscheinen und kann nicht mehr etwa aus
Systemgründen rückgängig gemacht werden.
Die Gewährleistung von Atomarität und Dauerhaftigkeit wird von einer Recovery Komponente (siehe Kapitel 11) übernommen, die Sicherstellung der Isolation verhindert Probleme wie das Dirty Read, Konsistenzerhaltung wird durch eine Komponente für Concurrency
Control sichergestellt. Im Concurrency Control wird dabei ein Verfahren verwendet, das die
Serialisierbarkeit von parallel ablaufenden Transaktionen gewährleistet.
10.1.3 Ausführung mehrerer Transaktionen
Wir nehmen ein vereinfachtes Modell der Datenbank an. Sie besteht aus atomaren Objekten,
die jeweils einen Namen und einen Wert haben. Der Zugriff auf diese Objekte geschieht mittels der zwei atomaren Operationen READ und WRITE, die einerseits den Wert eines Objektes
lesen und andererseits den Wert eines Objektes schreiben.
Beispiel 10.9 In unserem Modell sehen die Transaktionen folgendermaßen aus: Sei T 1 eine
Transaktion, die eine Überweisung von einem Konto auf ein Sparbuch vornimmt und T 2 eine
Transaktion, die die Überweisung einer Telefonrechnung erledigt.
Zeit
1
2
3
4
5
6
7
8
T1
T2
READ Konto
WRITE Konto
READ Sparbuch
WRITE Sparbuch
READ Konto
WRITE Konto
READ TEL-Konto
WRITE TEL-Konto
Definition 10.2 Eine Transaktion T ist eine Folge von Paaren (a1 ,e1 ), . . . , (ai ,ei ), . . . ,(an ,en ),
i = 1 . . . n, von Operationen ai auf Objekten ei . Ein Paar (ai ,ei ) nennt man einen Transaktionsschritt, mit |T | bezeichnen wir die Anzahl der Schritte n.
Ein Transaktionsschritt zusammen mit der Angabe der ihn ausführenden Transaktion T
wird als Ausführungsschritt bezeichnet: (T ,ai ,ei )
Definition 10.3 Die Ausführung I einer Transaktionsmenge T = {T1 , T2 , . . . , Tn } ist eine
beliebige Folge von Ausführungsschritten I(k) = (Tj , ai , ei ), k = 1, . . . , m, die folgende
Bedingungen erfüllt:
P
1. m = nj=1 |Tj |, d.h., I enhält genau soviele Ausführungsschritte wie alle Transaktionen
Tj Transaktionsschritte in Summe;
KAPITEL 10. CONCURRENCY CONTROL
10.7
2. j ∈ {1, . . . , n} und i ∈ {1, . . . , |Tj |}, d.h., I enthält nur Ausführungsschritte von Transaktionen Tj aus T; und
3. ist I(k) = (Tj , aik , eik ) und I(`) = (Tj , ai` , ei` ) und k < `, dann gilt ik < i` , d.h., alle
Transaktionsschritte (ai , ei ) ∈ Tj finden in I in derselben Reihenfolge statt wie in Tj .
I(k) wird k-ter Ausführungsschritt genannt. Die Schreibweise I(k) = (T j , ai , ei ) besagt,
dass der i-te Transaktionsschritt der Transaktion Tj der k-te Ausführungsschritt in I ist. Definition 10.4 Eine Ausführung I von T ist seriell, wenn für jede Transaktion aus T gilt,
dass alle ihre Ausführungsschritte in I unmittelbar hintereinander liegen, d.h., wenn I(k) =
(Tj , aik , eik ), I(k ∗ ) = (Tj , aik∗ , eik∗ ), und I(`) = (Tj ∗ , ai` , ei` ) mit k ≤ ` ≤ k ∗ , dann gilt
j = j ∗ . (Intuitiv ist I ist von der Form Tπ1 , Tπ2 , . . . , Tπn , wobei π eine Permutation von
1, . . . , n ist.)
Beispiel 10.10 Die eben formal definierten Begriffe wollen wir anhand des Beispiels 10.9
anwenden.
Ein Transaktionsschritt ist z.B. das Paar (READ, Konto), ein Ausführungsschritt das
Paar (T2, WRITE, TEL-Konto). Eine Ausführung von T= {T1,T2} ist z.B. jene, die in
Beispiel 10.9 gegeben ist. Sie ist auch seriell.
Würden in einem DBMS nur serielle Transaktionen zugelassen, so müssten wir uns nicht
um Synchronisation kümmern, denn es könnte zu keinen wie auch immer gearteten Problemen
kommen. Durch eine strikte Hintereinander-Ausführung von Transaktionen wäre die Performance des Systems jedoch nicht sehr hoch. Denn bevor ein Benutzer seine Abfrage starten
könnte, müsste er warten, bis alle anderen Abfragen, die vor der seinen gestartet wurden,
abgearbeitet sind. Daher ist es notwendig, dass wir auch verzahnte Ausführung von Transaktionen erlauben, d.h. aus der Sicht des Benutzers existieren die Transaktionen parallel im
System. Wir wollen in den nächsten Abschnitten untersuchen, welche Klasse von Transaktionen einerseits Parallelität erlauben, andererseits aber Probleme, wie wir sie in den Beispielen
10.2, 10.3 und 10.4 gesehen haben, vermeiden.
10.1.4 Konfliktrelation einer Ausführung
Bei der Ausführung von mehreren Operationen auf einem Objekt spielt die Reihenfolge der
einzelnen Operationen im allgemeinen eine Rolle. Die Probleme in den Beispielen 10.2,
10.3, 10.4 kommen, wie wir leicht sehen können, daher, dass die einzelnen Transaktionen
nicht hintereinander, sondern parallel ablaufen.
Definition 10.5 Operationen ai , aj auf einem Objekt, deren Reihenfolge eine Rolle spielt,
nennen wir Konfliktoperationen und sprechen von einem Konflikt, wenn a i und aj zu verschiedenen Transaktionen gehören.
10.8
KAPITEL 10. CONCURRENCY CONTROL
Wie wir leicht sehen, stellen die Paare (WRITE, WRITE), (WRITE, READ) und
(READ, WRITE) Konfliktoperationen dar, das Paar (READ, READ) hingegen nicht. Die
Konflikte zwischen Transaktionen werden in der Konfliktrelation erfasst.
Definition 10.6 Sei I eine Ausführung einer Menge T von Transaktionen auf einer Menge
von Objekten E. Die Konfliktrelation D(I) ist jene Teilmenge T ×E× T, die wie folgt definiert ist:
(Ti , e, Tj ) ist in D(I) genau dann, wenn es k und l ,1 ≤ k < l ≤ |I|, I(k) = (T i , ain , e),
I(l) = (Tj , ajm , e) gibt, so dass gilt:
1. Ti 6= Tj und (ain = WRITE oder ajm = WRITE)
2. Es gibt kein h für k < h < l, sodass I(h) = (Tg , ago , e) wobei Tg 6= Ti und Tg 6= Tj
und ago = WRITE
Entsprechend dieser Definition gehört ein Tupel (Ti , e, Tj ) zur Konfliktrelation D(I),
wenn die folgenden Bedingungen erfüllt sind:
Im Schritt k einer Ausführung I wird durch eine Transaktion Ti eine Operation ain auf
einem Objekt e ausgeführt. In einem späteren Schritt l der Ausführung I wird durch eine andere Transaktion Tj eine Operation ajm auf demselben Objekt e ausgeführt. Mindestens eine
der beiden Operationen ist eine Schreib-Operation. In den Ausführungsschritten dazwischen
wird keine Schreib-Operation auf e ausgeführt.
Definition 10.7 Zwei Ausführungen I1 und I2 über derselben Transaktionsmenge T heißen
(konflikt-)äquivalent genau dann, wenn ihre Konfliktrelationen D(I1 ) und D(I2 ) identisch
sind.
Beispiel 10.11 Betrachten wir drei verschiedene parallele Ausführungen I 1 , I2 und I3 von
zwei Transaktionen T1 und T2 :
T1
T2
READ A
WRITE A
READ A
WRITE A
READ B
WRITE B
READ B
WRITE B
I1
T1
T2
READ A
WRITE A
READ B
WRITE B
READ A
WRITE A
READ B
WRITE B
I2
T1
READ A
WRITE A
T2
READ A
WRITE A
READ B
WRITE B
READ B
WRITE B
I3
KAPITEL 10. CONCURRENCY CONTROL
10.9
Die Konfliktrelation von I1 ist D(I1 ) = {(T1 , a, T2 ), (T1 , b, T2 )}, die Konfliktrelation von
I2 ist D(I2 ) = {(T1 , a, T2 ), (T1 , b, T2 )}. Da I1 und I2 dieselbe Konfliktrelation haben, sind I1
und I2 konfliktäquivalent.
Die Konfliktrelation von I3 ist D(I3 ) = {(T1 , a, T2 ), (T2 , b, T1 )}. Sie stimmt mit den
Konfliktrelationen der beiden anderen Ausführungen nicht überein.
10.1.5 Serialisierbarkeit
Definition 10.8 Eine Ausführung I1 heißt serialisierbar genau dann, wenn es eine zu I1 äquivalente serielle Ausführung I2 gibt.
Serialisierbarkeit besagt, dass eine Ausführung I einer anderen seriellen Ausführung
entspricht; dies sichert die Konsistenz-Eigenschaft von Transaktionen. Die serialisierbaren
Transaktionen sind also jene Transaktionen, die, da sie zu seriellen Transaktionen äquivalent
sind, Probleme vermeiden.
Theorem 10.1 Eine Ausführung I über einer Transaktionsmenge T ist genau dann serialisierbar, wenn es eine lineare Ordnung “<” auf T gibt, so dass f ür jedes Paar I(k) =
(Ti , a, e), I(l) = (Tj , a0 , e), wo Ti 6= Tj und a, a0 Konfliktoperationen sind, gilt: k < l ⇔
Ti < T j .
Es gibt in der Datenbankliteratur auch noch einen schwächeren Begriff der Serialisierbarkeit. Eine Ausführung heißt demnach effektserialisierbar (view-serializable), wenn sie
denselben Output und dieselben Effekte auf eine Datenbank hat, wie eine beliebige serielle
Ausführung. Es ist natürlich klar, dass jede in unserem Sinn serialisierbare Ausführung auch
effektserialisierbar ist. Die Umkehrung muss damit aber nicht gelten.
Unsere Serialisierbarkeit ist eine hinreichende, aber keine notwendige Bedingung dafür,
dass eine gegebene parallele Ausführung von Transaktionen effektserialisierbar ist. Sie ist
nur dann eine notwendige Bedingung, wenn die Constrained Write Assumption (CWA) gilt.
Die CWA besagt, dass alle Transaktionen vor einem Schreibzugriff auf ein Objekt dieses auch
lesen müssen.
Wenn Transaktionen Objekte ohne vorheriges Lesen überschreiben können, so kann Effektserialisierbarkeit auch dann vorliegen, wenn es keine äquivalente serielle Ausführung gibt.
Wir gehen aber im Folgenden davon aus, dass die CWA gilt.
Beispiel 10.12 Betrachten wir nochmals die drei verschiedenen Ausführungen I 1 , I2 und I3
aus Beispiel 10.11.
I2 ist eine mögliche serielle Ausführung. Da I1 und I2 äquivalent sind, ist I1 serialisierbar.
Die Konfliktrelation von I3 ist nicht gleich der Konfliktrelation von I2 . Wir können daraus
aber nicht schließen, dass I3 nicht serialisierbar ist, da wir zuerst überprüfen müssen, ob
es nicht vielleicht eine andere serielle Ausführung gibt, zu der I 3 äquivalent ist. Bei zwei
Transaktionen gibt es zwei mögliche serielle Ausführungen: T1 vor T2 bzw. T2 vor T1 . Die
KAPITEL 10. CONCURRENCY CONTROL
10.10
Konfliktrelation für die zweite serielle Ausführung ist D(I4 ) = {(T2 , a, T1 ), (T2 , b, T1 )}. I3
ist auch zu dieser Konfliktrelation nicht äquivalent, daher ist I3 nicht serialisierbar.
10.1.6 Test auf Serialisierbarkeit
Die Serialisierbarkeit von Ausführungen kann auch mit graphentheoretischen Mitteln überprüft werden, denn im Allgemeinen ist es langwierig, alle Konfliktrelationen der n! seriellen
Ausführungen von n Transaktionen zu finden.
Definition 10.9 Der Präzedenzgraph für eine Ausführung I über einer Transaktionsmenge T
ist ein gerichteter Graph G(T ) = (N, E), dessen Knoten N die Transaktionen in T sind, und
in dem eine Kante von Ti nach Tj führt, genau dann wenn (Ti , e, Tj ) ∈ D(I), d.h.,
• Tj liest oder schreibt ein Objekt, das zuletzt von Ti geschrieben wurde, oder
• Ti liest ein Objekt, auf das Tj danach als erste Transaktion schreibt.
Die Kanten Ti → Tj in G werden manchmal mit einer Liste jener Objekte e markiert, für
die (Ti , e, Tj ) ∈ D(I) gilt.
Theorem 10.2 Eine Ausführung I ist serialisierbar genau dann, wenn der Präzedenzgraph
G(I) zyklenfrei ist. Durch topologisches Sortieren erhält man eine äquivalente serielle Ausführung. Der Präzedenzgraph gibt uns auch die lineare Ordnung auf T, da diese nat ürlich
nur dann existiert, wenn der Graph azyklisch ist.
Beispiel 10.13 Wenn wir wieder die Transaktionen aus dem Beispiel 10.11 betrachten, so erhalten wir für I1 und I2 denselben zyklenfreien Präzedenzgraphen. G(I1 ) gibt uns die lineare
Ordnung T1 < T2 . Für I3 hingegen ist der Präzedenzgraph zyklisch.
a
a,b
T1
T2
G(I1 ) = G(I2 )
T1
T2
b
G(I3 )
10.2 Sperrprotokolle
Die am weitesten verbreitete Methode, Serialisierbarkeit von Ausführungen zu erlangen, ist
dynamisches Sperren und Freigeben von Objekten einer Datenbank.
Sperren ist eine Aktion auf einem Objekt, die eine Transaktion durchführt, um dieses
Objekt vor Zugriffen durch andere Transaktionen zu schützen, während es in einem inkonsistenten Zustand ist.
Sperren werden benutzt, um die relative Abfolge von in Konflikt stehenden Operationen
zu kontrollieren.
KAPITEL 10. CONCURRENCY CONTROL
10.11
10.2.1 Gültige Ausführungen
Definition 10.10 Eine Ausführung heißt gültig, wenn für jeden Ausführungsschritt gilt: wenn
ein Objekt von einer Transaktion gesperrt ist, dann ist es durch keine weitere Transaktion
gesperrt.
D.h., für die Gültigkeit einer Ausführung ist es belanglos, ob auf die gesperrten Objekte
auch tatsächlich zugegriffen wird.
Beispiel 10.14 Betrachten wir die beiden Transaktionen T1 und T2 .
Zeit
1
2
3
4
5
6
T1
LOCK A
WRITE A
LOCK B
UNLOCK A
WRITE B
UNLOCK B
Zeit
1
2
3
4
5
6
7
8
T2
LOCK A
WRITE A
LOCK B
WRITE B
WRITE A
UNLOCK A
WRITE B
UNLOCK B
Folgende Tabelle zeigt zwei gültige Ausführungen I1 und I2 dieser beiden Transaktionen:
Zeit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
T1
T2
LOCK A
WRITE A
LOCK B
UNLOCK A
LOCK A
WRITE A
WRITE B
UNLOCK B
LOCK B
WRITE B
WRITE A
UNLOCK A
WRITE B
UNLOCK B
Zeit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
T1
T2
LOCK A
WRITE A
LOCK B
WRITE B
WRITE A
UNLOCK A
LOCK A
WRITE A
WRITE B
UNLOCK B
LOCK B
UNLOCK A
WRITE B
UNLOCK B
Die Abhängigkeitsrelationen der obigen Ausführungen sind:
D(I1 ) = {(T1 , A, T2 ), (T1 , B, T2 )}
D(I2 ) = {(T2 , A, T1 ), (T2 , B, T1 )}
KAPITEL 10. CONCURRENCY CONTROL
10.12
10.2.2 Wohlgeformte Transaktionen
Definition 10.11 Eine Transaktion ist wohlgeformt, wenn sie folgende Bedingungen erfüllt:
1. Eine Transaktion greift auf ein Objekt nur zu, wenn sie dieses zuvor gesperrt hat.
2. Eine Transaktion sperrt niemals ein Objekt, das sie bereits selbst gesperrt hat.
3. Eine Transaktion versucht niemals, ein Objekt freizugeben, das sie nicht zuvor gesperrt
hat.
4. Vor Beendigung einer Transaktion werden die Sperren auf alle Objekte, die von ihr
gesperrt wurden, wieder freigegeben.
Sperren alleine ist nicht hinreichend, damit eine Transaktion im allgemeinen Fall serialisierbar ist. Die Ausführung in Beispiel 10.15 ist nicht serialisierbar, obwohl jedes Objekt vor
dem Schreiben gesperrt wurde. Der Präzedenzgraph enthält einen Zyklus.
Beispiel 10.15 Betrachten wir die folgende Ausführung der Transaktionen T 1 und T2
Zeit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
T1
T2
LOCK a
LOCK c
WRITE a
WRITE c
UNLOCK a
LOCK a
WRITE a
LOCK b
UNLOCK a
WRITE b
UNLOCK b
UNLOCK c
LOCK b
WRITE b
UNLOCK b
LOCK c
WRITE c
UNLOCK c
Der dazugehörige Präzedenzgraph sieht folgendermaßen aus:
a,c
T1
T2
b
KAPITEL 10. CONCURRENCY CONTROL
10.13
10.2.3 Das 2-Phasen-Sperrverfahren (2-Phase-Locking)
Definition 10.12 Eine Transaktion T = h(ai , ei )i, i = 1, . . . , n ist eine 2-Phasen-Transaktion,
wenn für ein j < n und für alle i = 1, . . . , n gilt:
1. i < j ⇒ ai 6= UNLOCK
2. i = j ⇒ ai = LOCK
3. i > j ⇒ ai 6= LOCK
Die Schritte 1, 2, . . . , j sind die Sperrphase, die Schritte j + 1, . . . , n sind die Schrumpfungsphase der Transaktion. Der Zeitpunkt des Belegens der letzten Sperre wird als Sperrpunkt (locked point) bezeichnet.
Sperren
locked point
Wachstumsphase
Schrumpfungsphase
Zeit
Eine hinreichende Bedingung für Serialisierbarkeit ist nun die folgende:
Theorem 10.3 Wenn alle Transaktionen einer Transaktionsmenge T wohlgeformt und 2-PhasenTransaktionen sind, dann ist jede gültige Ausführung von T serialisierbar.
Die Serialisierungsreihenfolge einer solchen Ausführung entspricht der Reihenfolge der
Sperrpunkte der einzelnen Transaktionen aus T.
Beispiel 10.16 Die folgenden beiden Tabellen zeigen zwei Transaktionen, von denen die erste
das 2-Phasen-Sperrprotokoll erfüllt, die zweite nicht.
T1
LOCK a
LOCK b
LOCK c
UNLOCK c
UNLOCK a
UNLOCK b
locked point
T2
LOCK a
LOCK b
UNLOCK a
LOCK c
←− Nicht 2-Phasen
UNLOCK c
UNLOCK b
In der Praxis werden meist alle UNLOCK-Befehle bis zum Ende der Transaktion verzögert
und/oder zu einem Befehl (COMMIT) zusammengefasst, der gleichzeitig das Ende der Transaktion darstellt.
KAPITEL 10. CONCURRENCY CONTROL
10.14
10.2.4 Deadlock
Dynamisches Sperren von Objekten führt zum Problem des Deadlocks. Deadlocks müssen
entweder von vornherein vermieden oder erkannt und aufgelöst werden.
T1
LOCK a
T2
LOCK b
(LOCK b)
(LOCK a)
← T1 wartet auf b
← T2 wartet auf a
10.2.5 Das Baumprotokoll
In diesem und im nächsten Abschnitt wollen wir zwei Sperrverfahren vorstellen, die Serialisierbarkeit sicherstellen. Das erste, das Baumprotokoll, ist auch deadlockfrei.
Gehen wir davon aus, dass wir eine Ansammlung von Objekten, wie z.B. Datenbanken,
Anwendungen (Menge von Relationen), Relationen, oder Tupel als Knoten eines Baumes
gespeichert haben. Dieser Baum kann z.B. ein B ∗ -Baum (siehe: VO Algorithmen und Datenstrukturen) sein.
Definition 10.13 Eine Transaktion T erfüllt das Baumprotokoll, wenn gilt:
1. Ein Objekt O wird nur dann von T gesperrt, wenn T bereits eine Sperre auf den Vater
von O hält.
2. Regel 1. gilt nicht für das erste Objekt im Baum, das von T gesperrt wird.
3. Ein Objekt O, das von einer Transaktion T gesperrt und wieder freigegeben wurde,
kann von T anschließend nicht mehr gesperrt werden.
Eine hinreichende Bedingung für Serialisierbarkeit ist nun:
Theorem 10.4 Wenn alle Transaktionen einer Transaktionsmenge T wohlgeformt sind und
das Baumprotokoll erfüllen, dann ist jede gültige Ausführung von T serialisierbar.
Beispiel 10.17 Betrachten wir den folgenden Baum mit der dazugehörigen Ausführung I.
Die Transaktionen T1 , T2 und T3 erfüllen das Baumprotokoll, die Transaktionsmenge T ist
wohlgeformt und I ist gültig. Aus diesem Grund ist I serialisierbar, mit T 1 < T3 < T2 oder
T3 < T 1 < T 2
KAPITEL 10. CONCURRENCY CONTROL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
T1
LOCK A
LOCK B
LOCK D
UNLOCK B
T2
10.15
T3
LOCK B
A
LOCK C
LOCK E
B
UNLOCK D
C
LOCK F
UNLOCK A
D
E
LOCK G
UNLOCK C
UNLOCK E
F
G
LOCK E
UNLOCK F
UNLOCK B
UNLOCK G
UNLOCK E
10.2.6 Das Hierarchische Sperrprotokoll
Beim Hierarchischen Sperrprotokoll betrachten wir zwei Arten von Sperren, das Exclusive
Lock (X-Sperre) und das Intention Lock (I-Sperre). Das Intention Lock ist eine Absichtser”
klärung“, dass später ein Subobjekt (Teilbaum) gesperrt wird.
Definition 10.14 Eine wohlgeformte 2-Phasen-Transaktion T gehorcht dem Hierarchischen
Sperrprotokoll, wenn gilt:
1. T greift auf die Knoten des Baumes in hierarchischer Reihenfolge von der Wurzel ausgehend zu.
2. T sperrt einen Knoten K nur dann, wenn sie eine I-Sperre auf alle Vorgänger von K
besitzt.1
3. T gibt einen Knoten K erst dann frei, wenn sie alle Nachfolger von K freigegeben hat.
Eine hinreichende Bedingung für Serialisierbarkeit ist nun:
1
Es ist nicht nötig einen Knoten mit einer X-Sperre zu belegen, wenn sein Vorgängerknoten schon eine XSperre besitzt.
KAPITEL 10. CONCURRENCY CONTROL
10.16
Theorem 10.5 Wenn alle Transaktionen einer Transaktionsmenge T wohlgeformt sind und
das Hierarchische Sperrprotokoll erfüllen, dann ist jede gültige Ausführung von T serialisierbar.
Kompatibilitätsrelation:
Sperranforderung
I-Lock
X-Lock
Bestehende Sperre
I-Lock
X-Lock
+
−
−
−
+ . . . Verträglich, − . . . Konflikt
Beispiel 10.18 Betrachten wir den folgenden Baum mit der dazugehörigen Ausführung I.
Die Transaktionen T1 , T2 und T3 erfüllen das Hierarchische Sperrprotokoll, die Transaktionsmenge T ist wohlgeformt und I ist gültig. Aus diesem Grund ist I serialisierbar, mit
T1 < T2 < T3 oder T2 < T1 < T3
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14
15.
16.
17.
18.
19.
20.
T1
I-LOCK A
T2
T3
I-LOCK A
I-LOCK B
I-LOCK A
I-LOCK B
X-LOCK E
X-LOCK D
A
UNLOCK E
UNLOCK D
B
UNLOCK B
UNLOCK A
C
UNLOCK B
X-LOCK B
I-LOCK C
X-LOCK F
D
E
F
G
UNLOCK A
UNLOCK
UNLOCK
UNLOCK
UNLOCK
B
F
C
A
In den meisten kommerziellen DBMS gibt es noch einen weiteren Sperrtyp: das S-LOCK
(Shared lock), das verwendet wird, wenn ein Objekt nur zum Lesen gebraucht wird. Wie wir
KAPITEL 10. CONCURRENCY CONTROL
10.17
aus der folgenden Kompatibilitätstabelle sehen, kann eine Transaktion für ein Objekt, auf dem
eine andere Transaktion schon ein S-lock hält, auch ein S-lock erhalten, ohne dass sie auf die
Freigabe des Objekts warten muss.
Kompatibilitätsrelation:
Sperranforderung
S-Lock
X-Lock
Bestehende Sperre
S-Lock
X-Lock
+
−
−
−
+ . . . Verträglich, − . . . Konflikt
10.3 Zeitstempelverfahren (Time Stamping)
Beim Zeitstempelverfahren wird ein Konflikt nicht durch das Setzen von Sperren vermieden,
sondern wenn ein Konflikt entdeckt wird, wird die Transaktion, die zu dem Konflikt geführt
hat abgebrochen und neu gestartet. Zum Erkennen von Konflikten werden Transaktionen und
Datenbankobjekten Zeitstempel (timestamps) zugeordnet:
• Jede Transaktion erhält als eindeutigen Zeitstempel den Zeitpunkt des Transaktionsbeginns.
• Jedes Datenbankobjekt übernimmt sowohl den Zeitstempel der letzten zugreifenden
Schreib-Transaktion, als auch den der letzten Lese-Transaktion.
Durch folgende Bedingungen wird die Konsistenz der Datenbank sichergestellt:
1. Eine Transaktion mit Zeitstempel t1 darf ein Objekt mit Schreibstempel tw nicht lesen,
wenn tw > t1 gilt, also das Objekt bereits von einer jüngeren Transaktion verändert
wurde. Die Transaktion muss in diesem Fall abgebrochen werden.
2. Eine Transaktion mit Zeitstempel t1 darf ein Objekt mit Lese-Zeitstempel tr nicht verändern, wenn tr > t1 gilt, also das Objekt bereits von einer jüngeren Transaktion gelesen
wurde. Die Transaktion muss in diesem Fall abgebrochen werden.
Eine abgebrochene Transaktion wird neu gestartet und erhält die dem Zeitpunkt des Neustarts entsprechende Zeitmarke.
Zu beachten ist, dass zwei Lesezugriffe keinen Konflikt darstellen, und von zwei Schreibzugriffen nur der jüngere - d.h., der von der später gestarteten Transaktion durchgeführte erhalten bleibt, da der ältere Wert überschrieben bzw. gar nicht geschrieben wird.
Die Serialisierungsreihenfolge der Transaktionen entspricht der Reihenfolge der Zeitstempel, also der Startzeitpunkte.
10.18
KAPITEL 10. CONCURRENCY CONTROL
Um beim Abbruch einer Transaktion alle bereits erfolgreich durchgeführten Operationen
dieser Transaktion rückgängig machen zu können, werden die geänderten Werte eines Objekts
vorerst in einen zu dem Objekt gehörenden privaten Arbeitsbereich geschrieben (Phase 1);
erst bei der erfolgreichen Beendigung der Transaktion werden die geänderten Werte in die
Datenbank übernommen (Phase 2).
Wir geben nun einen Algorithmus an, der bei diesem Verfahren Zeitstempel verändert und
gegebenenfalls Transaktionen abbricht.
Angenommen, die Transaktion T will die Operation X auf dem Datenbankobjekt O ausführen. Sei t der Zeitpunkt des Beginns von T , tr der Lesestempel von O, tw der Schreibstempel von O. Nach den Werten dieser Stempel wird genau eine der Aktionen (1) bis (4)
ausgeführt.
Algorithmus T IM EST AM P
INPUT: X Operation der Transaktion T auf einem Datenobjekt O
OUTPUT: Lese- oder Schreibstempel von O oder Abbruch von T
(1) if X = READ and t ≥ tw
then READ
if t > tr
then tr := t endif;
endif;
(2) if X = WRITE and t ≥ tr and t ≥ tw
then WRITE
tw := t;
endif;
(3) if X = WRITE and tr ≤ t < tw
then {do nothing} endif;
(4) if (X = READ and t < tw ) or (X = WRITE and t < tr )
then abort(T ) endif;
Im Fall (3) ist zu beachten: da die aktuelle Schreiboperation keinerlei Effekte auf die
Datenbank hat, kann sie ignoriert werden.
Beispiel 10.19 Seien T1 , T2 , T3 drei Transaktionen mit den Zeitstempeln 200, 150 und 175.
Zu Beginn der Ausführung haben alle Objekte sowohl Lese- als auch Schreibstempel auf Null
gesetzt. Da T1 als erstes auf B lesend zugreifen will, wird der Lesestempel von B auf 200
gesetzt. Danach werden die anderen beiden Lesestempel gesetzt nach (1), T 1 greift schreibend
auf B zu, der Schreibstempel wird nach (2) gesetzt. Dasselbe passiert auch mit A. Nun will
T2 C beschreiben; der Zeitstempel von T2 ist 150, C hat aber einen Lesestempel von 175.
KAPITEL 10. CONCURRENCY CONTROL
10.19
Deshalb wird T2 nach (4) abgebrochen. T3 will noch auf A schreiben, was nach (3) auch geht.
T2 bekommt einen neuen Zeitstempel, der größer als 200 ist, z.B. 250. Die Reihenfolge der
Transaktionen ist nun: T3 < T1 < T2 .
T1
200
1.
2.
3.
4.
5.
6.
7.
T2
150
T3
175
A
RT = 0
WT = 0
READ B
READ A
B
RT = 0
WT = 0
RT = 200
C
RT =0
WT = 0
RT = 150
READ C
WRITE B
WRITE A
RT = 175
WT = 200
WT = 200
WRITE C
WRITE A
WT = 200
Beim Zeitstempelverfahren gibt es keine Deadlocks wie beim Sperrverfahren. Allerdings
kann es auch hier zu unbeschränkter Verzögerung kommen, durch eine unendliche Folge von
Abbrüchen, einem sogenannten Livelock (indefinite postponement):
T1
100
1.
2.
3.
4.
5.
6.
7.
T2
110
T1
120
T2
130
A
RT = 0
WT = 0
WRITE B
WRITE A
B
RT =0
WT = 0
WT = 100
WT = 110
READ A
WRITE B
WT = 120
READ B
WRITE A
WT =130
READ A
Nach dem Abbruch von T1 wird diese Transaktion neu gestartet. Es tritt wieder ein Konflikt mit T2 auf, diesmal wird T2 abgebrochen und neu gestartet. Durch zyklisches Abbrechen
tritt eine unbeschränkte Verzögerung auf.
10.4 Transaktionen in SQL
In SQL gibt es keinen speziellen Befehl zum Starten einer Transaktion. Die meisten SQLStatements können nur innerhalb einer Transaktion ablaufen (z.B. SELECT, INSERT, CREATE
TABLE, nicht aber z. B. CONNECT). Soll ein solches Statement bearbeitet werden und es ist
noch keine Transaktion aktiv, wird vom System implizit eine Transaktion gestartet. Eine
Transaktion wird mit dem Befehl COMMIT beendet. Alle durchgeführten Änderungen werden dadurch dauerhaft gespeichert. Eine Transaktion kann mit ROLLBACK abgebrochen werden. Alle durchgeführten Änderungen werden ungültig und dadurch zurückgenommen. Mit
SET TRANSACTION können verschiedene Attribute gesetzt werden.
10.20
KAPITEL 10. CONCURRENCY CONTROL
Durch SET TRANSACTION READ ONLY ist nur ein lesender Zugriff innerhalb der Transaktion
möglich, das Gegenteil ist SET TRANSACTION READ WRITE.
Im Laufe einer Transaktion können die Probleme auftreten, die wir in den Beispielen 10.3
und 10.4 gesehen haben.
Dirty Read: T1 liest einen von T2 veränderten Wert, bevor T2 mit COMMIT abgeschlossen
wurde.
Nonrepeatable Read: T1 liest einen Satz. Während der Transaktion wird derselbe Satz von
T1 noch einmal gelesen. Zwischen den beiden Lesevorgängen hat T 2 Werte dieses Satzes verändert. T1 erhält daher zwei verschiedene Werte für denselben Satz.
Phantom Read: T1 liest eine Menge von Sätzen aufgrund bestimmter Kriterien (SELECT
* FROM tabelle WHERE bedingung). Dieser Lesevorgang wird später wiederholt. Inzwischen ändert T2 einige Werte. Dadurch erfüllt eine andere Menge von Sätzen die
WHERE− Bedingung, sodass T1 beim zweiten Lesevorgang eine andere Menge von
Sätzen bekommt.
SQL-3 unterstützt zur Vermeidung dieser Phänomene verschiedene Isolationsstufen (Isolation levels). Die folgende Tabelle zeigt, durch welche Optionen welche Phänomene vermieden werden können.
Stufe
SERIALIZABLE
REPEATABLE READ
READ COMMITTED
READ UNCOMMITTED
Dirty Read
nicht möglich
nicht möglich
nicht möglich
möglich
Nonrepeatable Read
nicht möglich
nicht möglich
möglich
möglich
Phantom Read
nicht möglich
möglich
möglich
möglich
Die gewünschte Isolationsstufe wird mit SET TRANSACTION ISOLATION LEVEL für eine
Transaktion festgelegt, z. B. SET TRANSACTION ISOLATION LEVEL SERIALIZABLE. Um alle
Anomalien zu verhindern, müssten wir nur serialisierbare Transaktionen zulassen. Das ist jedoch aus Performancegründen nicht immer möglich. Es ist daher unsere Aufgabe beim Design
der Datenbankapplikation diese Effekte zu überlegen und die richtigen Designentscheidungen
zu treffen.
KAPITEL 10. CONCURRENCY CONTROL
10.5
10.21
Übungsbeispiele
Übung 10.1 Ist die angegebene Ausführung der Transaktionen T 1, T 2, T 3 und T 4 serialisierbar? Warum (nicht)? (Begründung mit Hilfe des Präzedenzgraphen, oder Angabe der
äquivalenten seriellen Ausführung)
T 1:
T 2:
READ a
T 3:
T 4:
READ a
UPDATE b
UPDATE a
READ b
READ b
UPDATE c
UPDATE a
UPDATE b
Übung 10.2 Angenommen wir verwenden das Zeitstempel-Verfahren für die Synchronisierung der Transaktionen in Beispiel 10.1. Welche der 4 Transaktionen wird abgebrochen, wenn
wir folgende Voraussetzung für die Zeitstempel der Transaktionen T 1 − T 4 treffen:
1. 300, 310, 320 und 330
2. 250, 200, 210 und 275
Übung 10.3 Das Hierarchische Sperrprotokoll mit I-Sperren und X-Sperren (siehe Vorlesung) wird um S-Sperren (shared locks) erweitert:
IS
IX
S
SIX
X
...
...
...
...
...
Absicht für S-Belegung
Absicht für X-Belegung
S-Sperre (shared)
S-Sperre und Absicht für X-Belegung
X-Sperre (exclusive)
Geben Sie die Kompatibilitätsrelation mit den Spalten (bzw. Zeilen) X, S, IS, SIX, IX
an.
Übung 10.4 Gegeben ist folgende Hierarchie von Objekten:
KAPITEL 10. CONCURRENCY CONTROL
10.22
A
B
D
C
E
F
G
Sind alle möglichen, gültigen Ausführungen der Transaktionen T 1, T 2 und T 3 serialisierbar? (Begründung oder Gegenbeispiel)
T 1: lock A, lock B, unlock B, lock C,
unlock A, unlock C
T 2: lock B, lock E, unlock B, lock G,
unlock E, unlock G
T 3: lock E, lock F , lock G,
unlock E, unlock F , unlock G
Übung 10.5 Gegeben ist folgende Parallelausführung von Transaktionen:
T 1:
UPDATE a
T 2:
T 3:
UPDATE b
READ a
UPDATE c
READ c
READ b
1. Stellen Sie die Abhängigkeitsbeziehungen von T 1, T 2 und T 3 durch Angabe des Präzedenzgraphen dar.
2. Ist die angegebene Ausführung von T 1, T 2 und T 3 serialisierbar?
Übung 10.6 Gegeben ist eine Ansammlung von Objekten O, die Knoten eines Baumes sind,
sowie die Transaktionen T 1 und T 2. Angenommen T 1 und T 2 erfüllen das Hierarchische
Sperrprotokoll: Kann es bei einer Ausführung von T 1 und T 2 zu einem Deadlock kommen?
Betrachten Sie dazu den Baum mit der Wurzel A und den zwei Kindern B und C.
Übung 10.7 Parallele Transaktionen werden mit Hilfe des Zeitstempelverfahrens synchronisiert. Gegeben sind folgende Transaktionen mit ihren Zeitstempeln:
KAPITEL 10. CONCURRENCY CONTROL
T 1:
80
T 2:
70
WRITE c
10.23
T 3:
60
a
RT = W T = 0
READ a
RT = ..
b
RT = W T = 0
c
RT = W T = 0
W T = ..
W T = ..
WRITE b
W T = ..
WRITE a
W T = ..
WRITE c
READ b
RT = ..
RT = ..
READ c
1. Tragen Sie in der obigen Darstellung die fehlenden Werte für die Lese- und Schreibstempel der Objekte a, b und c ein. Kennzeichnen Sie den Abbruch einer Transaktion
mit “∗”.
2. Welche Serialisierungsreihenfolge von T 1, T 2, T 3 wird in der obigen Ausführung
durch die Anwendung des Zeitstempelverfahrens erzwungen?
Übung 10.8 Gegeben ist folgende Parallelausführung von Transaktionen:
T 1:
READ a
T 2:
T 3:
READ b
UPDATE a
UPDATE b
READ a
READ a
1. Stellen Sie die Abhängigkeitsbeziehungen von T 1, T 2 und T 3 durch Angabe des Präzedenzgraphen dar.
2. Ist die angegebene Ausführung von T 1, T 2 und T 3 serialisierbar?
Übung 10.9 Gegeben ist folgende Ansammlung von Objekten, die Knoten eines Baumes
sind:
A
B
D
C
E
F
G
KAPITEL 10. CONCURRENCY CONTROL
10.24
Geben Sie für die Transaktionen T 1, T 2 und T 3 an, ob sie das Baumprotokoll erfüllen.
Falls eine Transaktion das Baumprotokoll verletzt, geben Sie das Objekt an, das falsch gesperrt wird.
T 1: LOCK A, LOCK B, UNLOCK A, LOCK C, UNLOCK C, UNLOCK B
T 2: LOCK B, LOCK E, UNLOCK E, LOCK D, UNLOCK B, UNLOCK D
T 3: LOCK A, LOCK E, LOCK F , UNLOCK F , UNLOCK E, UNLOCK A
Übung 10.10 In Abschnitt 10.1.5 ist das Konzept der Effektserialisierbarkeit (view serializability) vorgestellt worden. Beweisen oder widerlegen Sie:
• Jede serialisierbare Ausführung ist view-serializable.
• Unter constraint write assumption (CWA) ist eine Ausführung genau dann serialisierbar,
wenn sie view-serializable ist.
• Unter Aufgabe der constraint write assumption (CWA) ist eine view-serializable Ausführung
nicht notwendigerweise serialisierbar.
Übung 10.11 Ist das 2-Phasen-Sperrprotokoll deadlockfrei?
Übung 10.12
• Ist das gewöhnliche Baumprotokoll deadlockfrei?
• Ist das Hierarchische Sperrprotokoll deadlockfrei?
• Angenommen, das Hierarchische Sperrprotokoll verwende nur X-Locks. Ist es unter
dieser Annahme deadlockfrei?
Übung 10.13 Gegeben ist folgende Parallelausführung von Transaktionen:
T 1:
T 2:
READ b
T 3:
UPDATE a
READ a
UPDATE c
READ b
UPDATE b
UPDATE c
1. Stellen Sie die Abhängigkeitsbeziehungen von T 1, T 2 und T 3 durch die Angabe des
Präzedenzgraphen dar.
2. Ist die angegebene Ausführung von T 1, T 2, und T 3 serialisierbar?
KAPITEL 10. CONCURRENCY CONTROL
10.25
Übung 10.14 Parallele Transaktionen werden mit Hilfe des Zeitstempelverfahrens synchronisiert. Gegeben sind folgende Transaktionen mit ihren Zeitstempeln:
T 1:
45
READ a
T 2:
65
T 3:
90
a
RT = W T = 0
RT = 45
b
RT = W T = 0
c
RT = W T = 0
W T = 65
WRITE b
WRITE c
W T = 65
WRITE a
WT = ...
WT = ...
RT = . . .
WRITE c
READ C
RT = . . .
READ b
1. Tragen Sie in der obigen Darstellung die fehlenden Werte für die Lese- und Schreibstempel der Objekte a, b und c ein. Kennzeichnen Sie den Abbruch einer Transaktion
mit “∗” .
2. Welche Serialisierungsreihenfolge von T 1, T 2 und T 3 wird in der obigen Ausführung
durch die Anwendung des Zeitstempelverfahrens erzwungen?
Übung 10.15 Geben Sie für die nachfolgende parallele Ausführung der Transaktionen T 1–
T 3 den Präzedenzgraphen an.
T1
T2
WRITE C
T3
READ D
WRITE B
WRITE C
READ A
WRITE A
WRITE D
READ C
WRITE B
Ist die Ausführung serialisierbar? Wenn nein, wieviele Operationen müssen mindestens
gestrichen werden, sodass die Ausführung serialisierbar wird, und welche Operationen?
Übung 10.16 Die nachfolgende Parallelausführung von Transaktionen werde mithilfe von
Zeitstempeln synchronisiert.
KAPITEL 10. CONCURRENCY CONTROL
10.26
T1
....
T2
....
READ a
T3
....
a
RT=WT=0
RT= . . . .
WRITE b
b
RT=WT=0
c
RT=WT=0
WT= . . . .
WRITE c
WT= . . . .
RT= . . . .
READ c
WRITE b
WT= . . . .
WT= . . . .
WRITE b
WRITE a
WT= . . . .
1. Wählen Sie Zeitstempel für die Transaktionen so, dass möglichst wenige abgebrochen
werden.
2. Welche Reihenfolge zwischen Transaktionen Ti , Tj ist dadurch garantiert?
Übung 10.17 Geben Sie für die nachfolgende parallele Ausführung der Transaktionen T 1 −
T 3 einen Präzedenzgraphen an:
T1
T2
write c
T3
write b
read a
read b
read c
Präzedenzgraph
write a
read c
read b
write b
write a
Ist die Ausführung serialisierbar?
Die Ausführung wird aber nach Streichen von (mindestens)
lisierbar, z.B.:
Operation(en) seria-
Übung 10.18 Parallele Transaktionen werden mit Hilfe des Zeitstempelverfahrens synchronisiert. Gegeben sind folgende Transaktionen mit ihren Zeitstempeln:
KAPITEL 10. CONCURRENCY CONTROL
T1
100
write c
T2
200
T1
300
write a
a
WT=RT=0
b
WT=RT=0
10.27
c
WT=RT=0
WT=
WT=
write b
WT=
read c
read b
write a
RT=
RT=
WT=
read c
read b
RT=
RT=
read a
RT=
1. Tragen Sie in der obigen Darstellung die fehlenden Werte für die Lese- und Schreibstempel der Objekte a, b und c ein. Kennzeichnen Sie den Abbruch einer Transaktion
mit “∗” .
2. Welche Serialisierungsreihenfolge von T 1, T 2 und T 3 wird in der obigen Ausführung
durch die Anwendung des Zeitstempelverfahrens erzwungen?
10.28
KAPITEL 10. CONCURRENCY CONTROL
Kapitel 11
Wiederanlauf (Recovery)
11.1 Grundlagen
11.1.1 Zielsetzung
Das Ziel der Recovery ist die Wiederherstellung eines konsistenten Datenbankzustandes nach
einem Fehler. Wir können folgende Arten von Fehlern unterscheiden:
1. Transaktionsfehler: eine Transaktion muss nach einem logischen Fehler (z.B. “Konto
nicht gedeckt”) abgebrochen werden.
2. Systemfehler: alle Änderungen, die nur im Hauptspeicher, aber noch nicht auf dem
Hintergrundspeicher durchgeführt wurden, gehen verloren.
3. Plattenfehler: alle Änderungen, die seit der letzten Sicherung auf dem Hintergrundspeicher durchgeführt wurden, gehen verloren.
Ein korrektes Wiederanlaufverfahren garantiert Dauerhaftigkeit und Atomarit ät, d.h., die
Effekte bereits erfolgreich abgeschlossener Transaktionen bleiben zur Gänze erhalten. Nicht
erfolgreich abgeschlossene Transaktionen hinterlassen keinerlei Effekte in der Datenbank.
Eine Transaktion kann sich selbst abbrechen (z.B. durch Entscheidung des Programmierers oder durch Laufzeitfehler im Anwendungsprogramm) oder durch das Datenbankmanagementsystem (z.B. durch Concurrency Control oder bei Auftreten von Deadlocks) abgebrochen werden. Die teilweise durchgeführte Transaktion soll keinerlei Effekt auf die Datenbank
haben. Alle bereits durchgeführten Aktionen von unvollständig ausgeführten Transaktionen
werden rückgängig gemacht (Rückwärts-Recovery, Rollback; siehe Abschnitt 11.3.1).
Es ist möglich, Punkte innerhalb einer Transaktion zu definieren, die das Rückgängigmachen nur bis zu diesem Punkt nötig machen. Solche Punkte nennt man Synchronisationspunkte (siehe Abschnitt 11.3.4).
1
11.2
KAPITEL 11. WIEDERANLAUF (RECOVERY)
Beispiel 11.1 Betrachten wir wieder das Bankenszenario (Umbuchung) mit den folgenden
Datenstrukturen und Integritätsbedingungen.
Datenstruktur:
SPARBUCH (SPNR, EINLAGE, BESITZER)
KONTO (KNR, KSTAND)
SPAREINLAGEN GESAMT
Integritätsbedingung:
KSTAND >= 0
EINLAGE > 0
SPAREINLAGEN GESAMT = Summe EINLAGE
Transaktion: Umbuchung von 50 Euro von Konto 123 auf das Sparbuch 321
begin transaction
update KONTO
set KSTAND=KSTAND-50
where KNR=123;
update SPARBUCH
set EINLAGE=EINLAGE+50
where SPNR=321
SPAREINLAGEN_GESAMT:= SPAREINLAGEN_GESAMT+50
print (Ueberweisung, Betrag, KNR, SPNR)
end transaction
Ein Systemabsturz während einer Umbuchung kann eine einseitige Buchung bedeuten.
Beim Systemanlauf muss ein konsistenter DB-Zustand (d.h., Buchungen werden vollständig
durchgeführt oder gar nicht) wiederhergestellt werden.
Beispiel 11.2 In der nächsten Abbildung sehen wir fünf Transaktionen, von denen die Transaktionen T1, T2 und T3 beim Systemabsturz bereits abgeschlossen sind. Ihre Änderungen
sind in der Datenbank und gültig, dadurch ist die Dauerhaftigkeit gewährt. Um auch Atomarität zu gewährleisten, müssen T4 und T5 rückgängig gemacht werden, da sie nicht abgeschlossen sind.
KAPITEL 11. WIEDERANLAUF (RECOVERY)
11.3
T1
T2
T3
T4
T5
Zeit
Absturz
11.1.2 Reihenfolge von Ausführungen
Definition 11.1 Eine Transaktion Tj liest X von einer Transaktion Ti falls:
1. Tj liest X zum Zeitpunkt tj , Ti schreibt X zum Zeitpunkt ti , und ti < tj .
2. Ti wird nicht vor tj abgebrochen,
3. jede Transaktion Tk , die X zum Zeitpunkt tk , ti < tk < tj schrieb, wurde vor tj abgebrochen.
Diese Definition werden wir im weiteren benötigen, um in gewisser Weise eine Reihenfolge von Transaktionen bestimmen zu können und Anomalien zu vermeiden.
Beispiel 11.3 Die Transaktion Ti schreibt den Wert X, Tj liest den Wert X und keine andere
Transaktion greift dazwischen lesend oder schreibend auf X zu.
kein Tk schreibt auf X
Ti
write(X)
Tj
read(X)
11.1.3 Nichtwiederherstellbare Ausführung
Wenn eine Transaktion z.B. wegen eines Systemabsturzes zurückgesetzt werden muss, kann
es zum Problem führen, dass sukzessive auch Transaktionen, die schon erfolgreich abgeschlossen waren, zurückgesetzt werden müssen, was im Widerspruch zur Forderung der Dauerhaftigkeit steht. Diese Problematik heißt kaskadierendes Zurücksetzen (Cascading Abort
oder Cascading Rollback). Die Ausführung ist daher nicht mehr wiederherstellbar.
KAPITEL 11. WIEDERANLAUF (RECOVERY)
11.4
Beispiel 11.4 Wegen des Systemabsturzes muss T3 zurückgesetzt werden. Da x bereits früher
freigegeben und sofort von T1 und T2 gelesen wurde, müssen auch T1 und T2 zurückgesetzt
werden, um die Atomarität von T3 zu garantieren, da sie auf dem von T3 geschriebenen Wert x
aufbauen1 . Da T1 und T2 bereits erfolgreich abgeschlossen waren, stellt dies eine Verletzung
der Dauerhaftigkeit dar.
read x
read y
T1
T2
read x
write y
T3
write x
read y
Zeit
Absturz
Cascading Abort kann nicht nur bei einem Systemabsturz, sondern auch beim Abbruch
einer Transaktion auftreten.
Um Cascading Abort zu vermeiden, darf eine Transaktion ihre Änderungen erst freigeben, wenn sichergestellt ist, dass die Transaktion ordnungsgemäß beendet werden kann (Isolation). Die Isolation wird also eingeführt, um den Widerspruch zwischen Dauerhaftigkeit
einerseits und dem Zurücksetzen zur Sicherstellung der Atomarität andererseits zu verhindern
und so Wiederherstellbarkeit zu garantieren. In der Praxis erreicht man Isolation, indem alle UNLOCK-Befehle bis zum Ende der Transaktion verzögert werden oder zu einem Befehl
(COMMIT) zusammengefasst werden, der gleichzeitig das Ende der Transaktion anzeigt.
11.1.4 ACA Ausführungen
Definition 11.2 Eine Ausführung I von Transaktionen verhindert kaskadierendes Zur ücksetzen (avoids cascading aborts, ACA), wenn gilt: immer wenn Ti X von Tj liest, kommt das
Commit der Transaktion Tj vor dem readi (X) von Ti in I, d.h., dass eine Transaktion nur von
schon erfolgreich abgeschlossenen Transaktionen lesen kann.
11.1.5 Strikte Ausführung von Transaktionen
Viele Datenbankmanagementsysteme implementieren das Zurücksetzen einer Transaktion dadurch, dass sie für alle Änderungsoperationen der Transaktion den alten Wert (Before Image)
restaurieren, den sie sich bei der Transaktionsausführung gemerkt haben. Dieses einfache
Verfahren ist jedoch nur unter der Annahme korrekt, dass Transaktionen Objekte nur dann
schreiben, wenn sie zuletzt von erfolgreich abgeschlossenen Transaktionen geschrieben wurden. Die Ausführung in der Abbildung unten verletzt diese Annahme.
1
Rücksetzen von T1 , T2 kann seinerseits das Rücksetzen weiterer Transaktionen veranlassen usw.
KAPITEL 11. WIEDERANLAUF (RECOVERY)
11.5
Beispiel 11.5 Das Before Image von X ist in T1 = 1, in T2 = 2. Angenommen, dass nach
einem Abbruch zuerst T1 , dann T2 restauriert werden, so bedeutet dies, dass am Ende des
Rücksetzens X = 2 gilt.
T1
WRITE(X,2)
T2
WRITE(X,3)
x=1
x=2
x=3
x=3
Wie wir gesehen haben, ist die Reihenfolge der Rücksetzungen vom Startzeitpunkt der
Transaktionen abhängig. Um diese Anomalie zu vermeiden, wird eine strikte Ausführung
von Transaktionen verlangt.
Definition 11.3 Eine Ausführung von Transaktionen ist strikt (ST), wenn jede Transaktion
nur Objekte liest und schreibt, die zuletzt von abgeschlossenen Transaktionen geschrieben
wurden.
Es gilt folgende Beziehung:
ST ⊂ ACA
Die serialisierbaren Transaktionen schneiden alle diese drei Klassen, sind aber unvergleichbar
mit ihnen, wie die nächste Abbildung zeigt. Die seriellen Transaktionen sind natürlich im
Schnitt aller dieser Klassen enthalten.
Ausführungen
serialisierbar
ACA
ST
seriell
In der Praxis wird strictness für 2-Phasen Sperrverfahren (siehe Kapitel 10) erreicht, wenn
folgende Regeln eingehalten werden:
1. Eine Transaktion kann erst schreiben, wenn sie ihren locked point erreicht hat.
2. Eine Transaktion kann erst Locks freigeben, wenn sie das Schreiben in die Datenbank
beendet hat.
Sperren werden daher nicht freigegeben, bis unmittelbar nach dem Commit. Commit und
Freigabe aller Sperren werden auch oft zu einer einzigen Operation zusammengezogen, die
die Transaktion beendet.
KAPITEL 11. WIEDERANLAUF (RECOVERY)
11.6
11.2 Pufferverwaltung
Wir unterscheiden die folgenden drei Arten von Speicher:
• Primär- oder Hauptspeicher (non-persistent storage, volatile Storage)
• Sekundär- oder Hintergrundspeicher (persistent storage, non-volatile storage)
• Stabiler Speicher (stable storage): Information geht nie verloren. (Kann mit Mehrfachkopien annähernd erreicht werden, aber nie zu 100%!)
Das Datenbankmanagementsystem bewegt Blöcke, die jeweils mehrere Datensätze umfassen, vom Hintergrundspeicher in den Hauptspeicher und umgekehrt (vergleiche die Abbildung
unten). Den Teil des Hauptspeichers, der zur Aufnahme von Datenbank-Blöcken gedacht ist,
bezeichnet man als Puffer. Blöcke auf dem Hintergrundspeicher werden als physische Bl öcke,
Blöcke im Hauptspeicher als Pufferblöcke bezeichnet.
input(A)
A
B
B
output(B)
Hauptspeicher
Platte
input(X) überträgt den physischen Block, der das Datenobjekt X enthält, in den Hauptspeicher.
output(X) überträgt den Pufferblock, der das Datenobjekt X enthält, auf den Hintergrundspeicher und ersetzt dort den entsprechenden physischen Block.
Transaktionen interagieren mit dem Datenbanksystem, indem Daten aus Programmvariablen in die Datenbank und Daten aus der Datenbank in Programmvariable übertragen werden:
read(X,xi ) weist den Wert des Datenobjekts X der Programmvariable xi zu.
1. Ist der Block, auf dem sich X befindet, noch nicht im Hauptspeicher, dann führe
input(X) aus.
2. Weise xi den Wert von X im Pufferblock zu.
write(X,xi ) weist den Wert der Programmvariable xi dem Datenobjekt X im Pufferblock zu.
KAPITEL 11. WIEDERANLAUF (RECOVERY)
11.7
1. Ist der Block, auf dem sich X befindet, noch nicht im Hauptspeicher, dann führe
input(X) aus.
2. Ersetze den Wert von X im Pufferblock durch den Wert von xi .
Es ist zu beachten, dass eine Änderung des Wertes von X auf dem Hintergrundspeicher
nicht unmittelbar nach der Änderung des Wertes von X im Puffer erfolgen muss. Aus Effizienzgründen ist es sinnvoll, ein Datenobjekt, auf das oft zugegriffen wird, länger im Puffer zu
behalten.
Ein Pufferblock wird vom Pufferverwalter automatisch auf den Hintergrundspeicher übertragen, wenn
1. der Puffer zu klein wird, oder
2. dies mittels output(X) vom Wiederanlaufverwalter verlangt wird (forced write).
(Wir werden die Gründe dafür später kennenlernen.)
Es ergeben sich demnach folgende mögliche inkonsistente Datenbankzustände nach einem
Systemabsturz:
• Änderungen abgeschlossener Transaktionen wurden vom Datenbankmanagementsystem
nur im Puffer, aber noch nicht auf dem Hintergrundspeicher durchgeführt.
• Änderungen noch nicht abgeschlossener Transaktionen wurden bereits auf dem Hintergrundspeicher durchgeführt.
Beispiel 11.6 Betrachten wir folgende Transaktion:
Zeit
1
2
3
4
5
6
T
read(A,a1 )
a1 :=a1 - 50
write(A,a1 )
read(B,b1 )
b1 :=b1 + 50
write(B,b1 )
Die nächsten drei Abbildungen stellen eine mögliche Abfolge des Hauptspeicherzustandes
und Hintergrundspeicherzustandes bei der Abarbeitung der Transaktion T dar. Nach dem
erfolgreichen Abschluss der Transaktion sind die Änderungen nur im Hauptspeicher, aber
nicht auf der Platte durchgeführt.
KAPITEL 11. WIEDERANLAUF (RECOVERY)
11.8
A=1000
A=1000
B=2000
Hauptspeicher
Platte
A=950
A=1000
B=2000
B=2000
Hauptspeicher
Platte
A=950
A=1000
B=2000
B=2050
Hauptspeicher
Platte
Bei einem Systemfehler geht der Hauptspeicherinhalt verloren, und dadurch auch das Ergebnis der bereits abgeschlossenen Transaktion (Verletzung der Eigenschaft der Dauerhaftigkeit). Es könnte sich aber während der Ausführung von T auch ein Zustand ergeben, bei dem
ein Teil der Änderungen bereits auf den Hintergrundspeicher übertragen wurde. Bei einem
Systemfehler hinterlässt die Transaktion dann einen Teileffekt auf der Datenbank (Verletzung
der Eigenschaft der Atomarität).
11.2.1 Privater Arbeitsbereich
Dies ist eine Art der Pufferverwaltung mit dem Zweck, jeder Transaktion einen separaten
Puffer zuzuordnen, in dem die Änderung der Daten durchgeführt wird.
Die Effekte einer Transaktion T nach diesem Modell können wie folgt beschrieben werden.
Begin Transaction T : T wird ein privater Arbeitsbereich als Puffer für Datenbankobjekte
zugeordnet.
Read Object X: Der private Arbeitsbereich von T wird nach dem Objekt X durchsucht.
Nur wenn X nicht gefunden wird, wird X aus der Datenbank in den Arbeitsbereich
übertragen.
KAPITEL 11. WIEDERANLAUF (RECOVERY)
11.9
Write Object X: Wenn das Objekt X im Arbeitsbereich gefunden wird, wird es dort überschrieben. Andernfalls wird der neue Wert im Arbeitsbereich eingetragen.
End Transaction T : Alle im Arbeitsbereich geänderten oder neu geschaffenen Werte von
Objekten werden in die Datenbank übertragen. Ein spezielles Protokoll garantiert, dass
entweder alle oder keine Werte übertragen werden. Danach wird der private Arbeitsbereich freigegeben.
11.2.2 Write Ahead-Protokoll
Ein Protokoll, das die obige Anforderung erfüllt, d.h., das das Konzept des privaten Arbeitsbereiches realisiert, ist das Write Ahead-Protokoll.
1. Phase: Alle zu ändernden Werte werden aus dem privaten Arbeitsbereich in einen stabilen
Speicherbereich, der sicher zuverlässig ist, übertragen.
2. Phase: Die geänderten Werte werden in die Datenbank selbst eingetragen.
Wenn ein Systemausfall während der 1. Phase eintritt, gilt die Transaktion als nicht durchgeführt. Die Datenbank ist und bleibt unverändert. Nach einem Systemausfall während der 2.
Phase muss das Datenbanksystem während des Wiederanlaufs alle Updates aus dem stabilen
Speicher übernehmen.
11.3 Wiederanlaufverfahren mit Logprotokoll
Die private Speicherverwaltung ist zwar korrekt, kann aber in ihrer Realisierung sehr kompliziert sein. Durch das Führen eines Logprotokolls kann der private Speicher ersetzt werden,
wenn alle Änderungen sofort in das Logprotokoll eingetragen werden. Weiters können alle
Daten im globalen Puffer gehalten werden.
11.3.1 Das Logprotokoll
Sämtliche für einen korrekten Wiederanlauf notwendigen Informationen werden in einem
Logprotokoll festgehalten. Das Logprotokoll enthält spezielle Logeinträge, die den Start (begin transaction), das Ende (commit transaction) oder den Abbruch (abort transaction) einer
Transaktion vermerken, sowie Standard-Logeinträge, die sämtliche durchgeführte Änderungen registrieren.
Ein Standardeintrag im Logprotokoll ist wie folgt aufgebaut:
1. Identifikator der Transaktion
2. Identifikator des geänderten Datensatzes
KAPITEL 11. WIEDERANLAUF (RECOVERY)
11.10
3. Art der Änderung (insert, delete, update)
4. alter Wert (wird für UNDO benötigt)
5. neuer Wert (wird für REDO benötigt)
6. Hilfsinformation (Zeiger auf vorigen Logeintrag der Transaktion, etc.)
Das Logprotokoll kann verwendet werden, um Transaktionen rückgängig zu machen (Rollback, backward recovery): U N DO(T ) oder um Transaktionen nachzufahren (forward recovery): REDO(T ).
alter Wert
DO
neuer Wert
Logprotokoll
neuer Wert
UNDO
alter Wert
REDO
neuer Wert
Logprotokoll
alter Wert
Logprotokoll
Da auch während des Wiederanlaufs ein Fehler auftreten kann, müssen die Operationen
U N DO und REDO idempotent sein, d.h.:
U N DO(U N DO(T )) = U N DO(T )
REDO(REDO(T )) = REDO(T ).
Beim Log-Write-Ahead-Protokoll muss der Eintrag in das Logprotokoll vor der Änderung
in der Datenbank durchgeführt werden. Wird das Logprotokoll gepuffert, muss vor der Übernahme einer Änderung in die Datenbank die UNDO-Information auf den stabilen Speicher
geschrieben werden; weiters müssen vor dem commit einer Transaktion sämtliche Logeinträge der Transaktion auf den stabilen Speicher übernommen werden.
Die sequentielle Führung des Logprotokolls auf dem Hintergrundspeicher ist einfacher,
als die Änderungen jeweils sofort in den komplexen Datenstrukturen der Datenbank auf dem
Hintergrundspeicher vorzunehmen. Außerdem ist es aus Sicherheitsgründen üblich, das Logprotokoll auf einem anderen Hintergrundspeicher als die Datenbank selbst zu führen. Dadurch
wird es möglich, nicht nur nach einem Systemabsturz, sondern auch nach einem Plattenfehler
wieder aufzusetzen.
KAPITEL 11. WIEDERANLAUF (RECOVERY)
11.11
11.3.2 Wiederanlauf nach einem Transaktionsabbruch
Nach einem Transaktionsabbruch wird für den Wiederanlauf das Logprotokoll mit den alten
Werten gebraucht.
Algorithmus:
UNDO(T): Lies das Logprotokoll vom letzten Eintrag in Richtung Anfang bis zum Eintrag
begin transaction T und ersetze sämtliche Änderungen von T in der Datenbank durch
die alten Werte.
RESTART(T): Starte T neu.
11.3.3 Wiederanlauf nach einem Systemabsturz
Im Falle eines Systemabsturzes muss ebenfalls für den Wiederanlauf das Logprotokoll mit den
alten Werten verwendet werden. In diesem Fall müssen jedoch nicht nur jene Transaktionen,
die beim Systemabsturz aktiv waren, rückgängig gemacht und neu gestartet werden, sondern
auch die schon abgeschlossenen Transaktionen müssen nochmals nachgefahren werden, da
alle Änderungen im Hauptspeicher verloren gegangen sind und nicht bekannt ist, ob diese
Änderungen auch alle auf dem Hintergrundspeicher durchgeführt wurden.
Algorithmus:
1. Baue zwei Listen UndoListe und RedoListe auf:
• Lies das Logprotokoll von Beginn vorwärts. Wird ein Eintrag begin transaction
Ti gefunden, füge Ti zur UndoListe hinzu.
• wird ein Logeintrag commit transaction Ti gefunden, füge Ti zur RedoListe hinzu und streiche Ti von der UndoListe.
2. Lies das Logprotokoll vom letzten Eintrag ausgehend rückwärts und mache alle Änderungen von Transaktionen in der UndoListe rückgängig. D.h., führe das UNDO für alle
Transaktionen in der UndoListe durch.
3. Lies im Logprotokoll weiter rückwärts, bis die begin transaction-Einträge für alle
Transaktionen in der RedoListe gefunden wurden.
4. Lies das Logprotokoll vorwärts und schreibe für jede von einer Transaktion in der RedoListe durchgeführte Änderung den neuen Wert in die Datenbank. D.h., führe ein
REDO durch.
5. Starte alle Transaktionen in der UndoListe neu.
Beispiel 11.7 Transaktion T 4 wird abgebrochen. Daher muss sie durch ein UNDO zurückgesetzt werden und danach neu gestartet werden. Im Falle eines Systemabsturzes müssen
hingegen auch die anderen Transaktionen nachgefahren werden.
KAPITEL 11. WIEDERANLAUF (RECOVERY)
11.12
REDO
T1
T1
T2
T2
T3
T3
UNDO
REDO
UNDO
T4
T4
Zeit
REDO
Transaktionsabbruch
Zeit
Systemabsturz
11.3.4 Checkpoints
Checkpoints werden zur Vereinfachung des Wiederanlaufs eingeführt um das im letzten Beispiel beschriebene Problem des Nachfahrens von Transaktionen zu verringern.
Bei einem Checkpoint werden
1. alle Logeinträge auf den stabilen Speicher geschrieben,
2. alle schmutzigen Pufferblöcke auf die Platte geschrieben (ein Pufferblock ist schmutzig
(dirty), wenn dessen Inhalt nicht mit dem ihm entsprechenden physischen Block auf der
Platte übereinstimmt),
3. ein spezieller Logeintrag, checkpoint L, auf den stabilen Speicher geschrieben, wobei L
die Menge der zum Zeitpunkt des Checkpoints aktiven Transaktion darstellt.
Bis zum nächsten Synchronisationspunkt werden sämtliche Änderungen unter Umständen
nur im Hauptspeicher und nicht in der Datenbank vorgenommen, jedoch auf alle Fälle im
Logprotokoll auf dem Hintergrundspeicher vermerkt.
11.3.5 Wiederanlauf mit Checkpoints nach einem Systemabsturz
Die Voraussetzung für einen korrekten Wiederanlauf nach einem Systemabsturz ist, dass das
Logprotokoll ab dem Startzeitpunkt der ältesten beim letzten Checkpoint aktiven Transaktionen auf dem stabilen Speicher vorhanden ist.
Algorithmus:
1. Baue zwei Listen UndoListe und RedoListe auf:
• Suche den letzten Checkpoint-Eintrag checkpoint L; initialisiere die UndoListe
mit L und lies von diesem Eintrag an vorwärts im Log (in Richtung des letzten
Eintrags).
• wird ein Logeintrag commit transaction Ti gefunden, füge Ti zur RedoListe hinzu und streiche Ti von der UndoListe.
KAPITEL 11. WIEDERANLAUF (RECOVERY)
11.13
• wird ein Logeintrag begin transaction Ti gefunden, füge Ti zur UndoListe hinzu.
2. Lies das Logprotokoll vom letzten Eintrag ausgehend rückwärts und mache alle Änderungen von Transaktionen in der UndoListe rückgängig. D.h., führe das UNDO für alle
Transaktionen in der UndoListe durch.
3. Lies im Logprotokoll weiter rückwärts bis die begin transaction-Einträge für alle Transaktionen in der RedoListe gefunden wurden.
4. Lies das Logprotokoll vorwärts und schreibe für jede von einer Transaktion in der RedoListe durchgeführte Änderung den neuen Wert in die Datenbank. D.h., führe ein
REDO durch.
5. Starte alle Transaktionen in der UndoListe neu.
Beispiel 11.8 Die Aktionen, die in der folgenden Situation gesetzt werden müssen (unter der
Annahme einer strikten Ausführung) sind:
T1
REDO
T2
T3
REDO
UNDO
T4
UNDO
T5
Zeit
Checkpoint
Absturz
• UNDO T4, T5
• REDO T2, T3
• RESTART T4, T5
Anmerkung: Unter Annahme einer strikten Ausführung genügt es, das REDO (Schritte 3
und 4) ab dem Checkpoint durchzuführen.
Beispiel 11.9 Bei einer nicht strikten Ausführung macht das UNDO von write(X) in T4 ein
REDO von write(X) in T2 notwendig.
KAPITEL 11. WIEDERANLAUF (RECOVERY)
11.14
T1
write(X)
REDO
T2
T3
T4
REDO
UNDO
write(X)
UNDO
T5
Zeit
Checkpoint
Absturz
11.3.6 Wiederanlauf nach einem Plattenfehler
Bei einem Plattenfehler müssen die Sicherungskopie (Backup) und das Logprotokoll ab dem
Zeitpunkt der Sicherungskopie vorhanden sein. Außerdem darf keine Transaktion während
der Sicherung aktiv sein.
Algorithmus
1. Ersetze die Datenbank durch die Sicherungskopie.
2. Bestimme die RedoListe wie folgt: Eine Transaktion T ist in der RedoListe, falls ein
Eintrag begin transaction T und ein Eintrag commit transaction T im Logprotokoll
aufscheint.
3. Lies das Log vom Anfang bis zum Ende und übernimm für Änderungen von Transaktionen in der RedoListe die neuen Werte in die Datenbank.
Beispiel 11.10 Die Aktionen, die in der folgenden Situation gesetzt werden müssen, sind:
T1
T2
REDO
T3
T4
T5
Zeit
• DB:=Backup
• REDO T3
• RESTART T5
Backup
Plattenfehler
KAPITEL 11. WIEDERANLAUF (RECOVERY)
11.15
In der Praxis ist es nicht sinnvoll, zu verlangen, dass während der Durchführung des
Backups keine Transaktionen aktiv sein dürfen. Sind Transaktionen aktiv, so muss das Logprotokoll ab dem Startzeitpunkt der ältesten während des Backups aktiven Transaktion vorhanden sein.
Algorithmus
1. Ersetze die Datenbank durch die Sicherungskopie.
2. Bestimme die Undo- und RedoListe wie folgt:
• Eine Transaktion T ist in der RedoListe, falls ein Eintrag begin transaction T
und ein Eintrag commit transaction T nach dem Backup Eintrag im Logprotokoll
aufscheint.
• Eine Transaktion T ist in der UndoListe, falls ein Eintrag begin transaction T,
aber kein Eintrag commit transaction T im Logprotokoll aufscheint.
3. Lies das Logprotokoll vom Backup Eintrag rückwärts und mache alle Änderungen von
Transaktionen in der UndoListe rückgängig.
4. Lies das Log vom Backup Eintrag bis zum Ende und übernimm für Änderungen von
Transaktionen in der RedoListe die neuen Werte in die Datenbank.
5. Starte alle Transaktionen in der UndoListe neu.
Beispiel 11.11 Die Aktionen, die in der folgenden Situation gesetzt werden müssen, sind:
T1
REDO
T2
T3
REDO
UNDO
T4
T5
Zeit
• DB:=Backup
• UNDO T4
• REDO T2, T3
• RESTART T4, T5
Backup
Plattenfehler
11.16
KAPITEL 11. WIEDERANLAUF (RECOVERY)
11.4 Schattenkopieverfahren (shadow paging)
11.4.1 Die Grundidee
Die Grundidee des Schattenkopieverfahrens ist es, bei der Ausführung einer Transaktion zwei
Kopien der Datenbank zu verwalten:
1. Die Schattenkopie enthält den Datenbankzustand vor dem Start der Transaktion. Sie
repräsentiert den nach der letzten erfolgreich abgeschlossenen Transaktion gültigen Datenbankzustand.
2. Die Transaktion führt sämtliche Änderungen auf einer Arbeitskopie durch. Sie wird zu
Beginn der Transaktion mit der Schattenkopie initialisiert.
Wird die Transaktion abgebrochen, wird die Arbeitskopie verworfen. Wird die Transaktion erfolgreich abgeschlossen, wird die Arbeitskopie die neue Schattenkopie.
11.4.2 Die Realisierung
Die Datenbank ist in Seiten (pages) aufgeteilt. (Eine Seite umfasst eine vorgegebene Anzahl Blöcke fixer Länge.) Die Seiten sind nicht notwendigerweise sequentiell gespeichert.
Eine Seitentabelle (page table) ordnet jeder Seite, identifiziert durch die Seitennummer, ihre
Adresse auf der Platte zu (siehe: Abb. 11.1).
Beim Schattenspeicherfahren werden zwei Seitentabellen verwendet: die Schattenseitentabelle und die Arbeitsseitentabelle, die auf die Schatten- bzw. die Arbeitskopie zeigen. Seiten, die in der Schattenkopie und in der Arbeitskopie gleich sind, werden nur einmal gespeichert und von beiden Tabellen referenziert (siehe Abb. 11.2). Eine fixe Speicheradresse auf
der Platte enthält einen Zeiger auf die Schattenseitentabelle.
Zum Transaktionsbeginn wird die Schattenseitentabelle in die Arbeitsseitentabelle kopiert.
Eine Schreiboperation write(X, xj ) auf ein Objekt X, das auf der i-ten Seite liegt, wird
wie folgt behandelt:
1. Ist die i-te Seite nicht im Puffer, dann übertrage sie mit input(X).
2. Wird die i-te Seite zum ersten Mal verändert, dann suche eine freie Seite auf der Platte
und ordne dieser die i-te Seite in der Arbeitsseitentabelle zu.
3. Weise den Wert xi dem Objekt X im Puffer zu.
Um eine Transaktion erfolgreich abzuschließen, werden folgende Schritte gesetzt:
1. Schreibe alle schmutzigen Seiten im Puffer auf die Platte.
2. Schreibe die Arbeitsseitentabelle auf die Platte.
KAPITEL 11. WIEDERANLAUF (RECOVERY)
11.17
1
.
.
.
2
3
4
5
.
.
.
.
.
.
n
Seitentabelle
Seiten auf der Platte
Abbildung 11.1: Seitentabelle
3. Schreibe die Adresse der Arbeitsseitentabelle auf jene fixe Speicheradresse, die die
Adresse der Schattenkopie enthält.
Das Wiederanlaufverfahren nach einem Systemfehler oder Transaktionsfehler ist einfach: setze die Arbeit mit der Schattenkopie fort.
Die Vorteile des Schattenspeicherverfahrens sind die folgenden:
1. Der Aufwand für die Verwaltung eines Logprotokolls entfällt.
2. Der Wiederanlauf ist beträchtlich schneller.
Dazu kommen aber die folgenden Nachteile:
• Datenfragmentierung
• Freispeicherverwaltung
• Schwerer als Verfahren mit Logprotokoll auf Mehrbenutzerbetrieb erweiterbar
KAPITEL 11. WIEDERANLAUF (RECOVERY)
11.18
AST
SST
1
2
3
1
.
.
.
2
3
4
4
5
5
6
6
7
7
8
.
.
.
Abbildung 11.2: Schattenseitentabelle und Arbeitsseitentabelle
KAPITEL 11. WIEDERANLAUF (RECOVERY)
11.5
11.19
Übungsbeispiele
Übung 11.1 Das Recovery wird mit Hilfe eines Logprotokolles mit Checkpoints durchgeführt.
Gegeben ist folgende Situation vor dem Crash:
T1
T2
T3
T4
T5
T6
T7
Checkpoint
Crash
Welche UNDO- und REDO-Protokolle müssen durchgeführt werden?
Welche Transaktionen müssen neu gestartet werden?
Übung 11.2 Das Recovery wird mit Hilfe eines Logprotokolls mit Sicherungskopien durchgeführt. Die Situation vor dem Crash ist wie im vorhergehenden Beispiel. Nach dem Einspielen der Backup-Kopie ergibt sich folgendes Bild:
T1
T2
T3
T4
T5
T6
T7
Checkpoint
Crash
Welche UNDO- und REDO-Protokolle müssen durchgeführt werden?
Welche Transaktionen müssen neu gestartet werden?
Übung 11.3 Für die Durchführung des Recovery nach einem Crash wird ein Logprotokoll
mit Checkpoints geführt. Der Crash ereignet sich in folgender Situation:
KAPITEL 11. WIEDERANLAUF (RECOVERY)
11.20
T1
T2
T3
T4
T5
T6
T7
Checkpoint
Crash
Für den Wiederanlauf wird die zum Sicherungspunkt angelegte Backup-Kopie verwendet.
Nach dem Einspielen der Sicherungskopie ergibt sich folgende Situation:
T1
T2
T3
T4
T5
T6
T7
Checkpoint
Crash
1. Zeichnen Sie im obigen Diagramm die notwendigen UNDO- und REDO-Protokolle
ein, die nun anhand des Logprotokolles zur Wiederherstellung des konsistenten Datenbankzustandes ausgeführt werden müssen.
2. Welche Transaktionen müssen anschließend neu gestartet werden?
Übung 11.4 Die Recovery wird mit Hilfe eines Logprotokolls mit Checkpoints (mit Backup)
durchgeführt. Gegeben ist folgende Situation vor dem Crash. Zeichnen Sie die erforderlichen
UNDO- und REDO-Protokolle ein.
T1
T2
T3
T4
T5
Checkpoint
Crash
KAPITEL 11. WIEDERANLAUF (RECOVERY)
11.21
Annahme: Aus- und Einspielen eines Backups kostet keinen Zeitaufwand. Ist es möglich,
dass bei einem Synchronisationspunkt mit Backup trotzdem mehr Aufwand für Recovery
anfällt als bei einem Synchronisationspunkt ohne Backup?
11.22
KAPITEL 11. WIEDERANLAUF (RECOVERY)
Herunterladen