102kB - Praktische Informatik

Werbung
Implementierung relationaler Operationen
Udo Kelter
30.11.2002
Zusammenfassung dieses Lehrmoduls
Aus der formalen Definition der relationalen Operationen ergeben sich
unmittelbar triviale Implementierungen. Diese sind in vielen Fällen
sehr ineffizient, besonders bei Selektionen und Verbunden. Dieses
Lehrmodul stellt effizientere Implementierungen vor; meist werden
hierbei Primär- oder Sekundärindexe ausgenutzt.
obligatorisch:
– Das relationale Datenbankmodell
Stoffumfang in Vorlesungsdoppelstunden:
1
0.8
Implementierung relationaler Operationen
2
Inhaltsverzeichnis
1 Einleitung
3
2 Triviale Implementierungen
3
3 Exkurs: Indexstrukturen
3.1 Primärindexe . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2 Sekundärindexe . . . . . . . . . . . . . . . . . . . . . . . . . .
5
5
7
4 Optimierungen der Selektion
8
5 Optimierungen der Projektion
11
6 Optimierungen der Verbundberechnung
11
Literatur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Glossar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
15
16
16
c
2002
Udo Kelter
Stand: 30.11.2002
Dieser Text darf für nichtkommerzielle Nutzungen als Ganzes und unverändert in elektronischer oder
gedruckter Form beliebig weitergegeben werden und in WWW-Seiten, CDs und Datenbanken aufgenommen werden. Jede andere Nutzung, insb. die Veränderung und Überführung in andere Formate, bedarf
der expliziten Genehmigung. Die jeweils aktuellste Version ist über http://kltr.de erreichbar.
Implementierung relationaler Operationen
1
3
Einleitung
Die Bedeutung der relationalen Operationen kann in sehr präziser,
aber dennoch abstrakter Weise unter Benutzung mathematischer Begriffe (insb. der Mengenlehre) definiert werden, s. [RDBM]. Diese Definitionen kann man auch direkt in triviale Implementierungen umsetzen. Man erkennt aber leicht, daß diese trivialen Implementierungen
teilweise extrem ineffizient und daher inpraktikabel sind. In diesem
Lehrmodul betrachten wir effizientere Implementierungen; diese beruhen teilweise auf Indexen.
Wir betrachten hier nur die Implementierung einzelner relationaler Operationen; die Abarbeitung komplexer algebraischer Ausdrücke
wird in einem separaten Lehrmodul behandelt [AVO].
Ferner betrachten wir nur die wichtigsten Operationen der relationalen Algebra, wir konzentrieren uns auf Selektionen und Verbunde.
Dieses Lehrmodul erhebt nicht den Anspruch, die enorme Vielfalt an Optimierungsmöglichkeiten und Indexstrukturen auch nur
annähernd zu repräsentieren. Ziel ist es vielmehr, anhand der simplen
Optimierungstechniken zu zeigen, welche Größenordnung des Rechenaufwands für die relationalen Operationen erreichbar ist.
2
Triviale Implementierungen
Die mathematischen Definitionen der relationalen Operationen können
unmittelbar in die folgenden “trivialen” Implementierungen umgesetzt
werden. Wir bestimmen noch jeweils den Aufwand unter der Annahme, daß die betroffenen Relationen n bzw. m Tupel enthalten.
Selektion: Man durchläuft alle Tupel einer Relation, wertet jedesmal
das Selektionsprädikat aus und gibt ggf. das Tupel aus. Der
Aufwand hat die Größenordnung O(n). Wenn A Identifikationsschlüssel ist, muß bei einer Selektionsbedingung der Form σA=x
im Durchschnitt die halbe Relation durchlaufen werden, bis das
gesuchte Tupel gefunden ist, sofern alle vorhandenen Schlüsselwerte gleichhäufig gesucht werden. Bei großen Relationen ist
c
2002
Udo Kelter
Stand: 30.11.2002
Implementierung relationaler Operationen
4
dies sehr ineffizient.
Projektion: Man durchläuft alle Tupel einer Relation und gibt die
gewünschten Attribute aus. Der Aufwand hierfür ist exakt n,
die Relation muß komplett durchlaufen werden.
Wenn zusätzlich eine Duplikateliminierung verlangt ist, muß
die Ergebnismenge sortiert werden (zusätzlicher, insg. dominierender Aufwand in der Größenordnung O(n*log(n))). Wenn
die Projektionsattribute einen Identifizierungsschlüssel enthalten, können natürlich keine Duplikate auftreten, und eine Duplikateliminierung ist überflüssig.
Mengenoperationen: Die Algorithmen für die Mengenoperationen sind
ebenfalls trivial. Sofern die Mengen schon geeignet sortiert sind,
ist der Aufwand linear, ansonsten kommt der Aufwand für die
Sortierung hinzu.
Kreuzprodukt: Man durchläuft geschachtelt beide Relationen und gibt
jeweils die Konkatenation der beiden aktuellen Tupel aus. Der
Aufwand hat die Größenordnung O(n*m), wenn n bzw. m die
Zahl der Tupel in den beiden Relationen ist.
Verbunde: Man kann den Verbund auf ein Kreuzprodukt, gefolgt von
einer Selektion und einer Projektion zurückführen (s. Abschnitt
3.6.2 in [RDBM]). Den größten Aufwand darin wird i.a. das
Kreuzprodukt verursachen.
Diese trivialen Implementierungen sind, wie die vorstehenden Größenordnungsangaben für den Aufwand zeigen, oft sehr ineffizient. Dies gilt
vor allem für die Verbundbildung. I.f. besprechen wir daher diverse
Optimierungsmaßnahmen für die einzelnen Operationen.
Optimierungsziele. Vorrangiges Optimierungsziel bei der Implementierung der elementaren Operationen ist eine möglichst geringe
Zahl von Plattenzugriffen. Die CPU-Belastung spielt nur eine sekundäre Rolle.
c
2002
Udo Kelter
Stand: 30.11.2002
Implementierung relationaler Operationen
3
5
Exkurs: Indexstrukturen
Indexe spielen für effiziente Implementierungen der Selektion und des
Verbunds eine große Rolle. Die Optimierungsmöglichkeiten hängen dabei stark von den Strukturen innerhalb der Indexe ab; wir geben daher
vorab einen Überblick über die wichtigsten Indexstrukturen und deren
Eigenschaften.
3.1
Primärindexe
Primärindexe sind Datenstrukturen, die in die “Nutzdaten” eingebettet sind und die Primärschlüssel realisieren. Bis auf wenige Ausnahmen kann ein Datenbestand nur einen Primärindex haben.
B*-Bäume. B- bzw. B*-Bäume sind bekanntlicherweise Baumstrukturen, die auf die Besonderheiten einer blockorientierten Speicherung
adaptiert sind. Ihre wesentlichen Eigenschaften sind:
– Die Struktur der Indexblöcke hat einen sehr hohen Verzweigungsgrad (typischerweise >10), d.h. die Zahl der Indexblöcke ist signifikant kleiner als die Zahl der Primärdatenblöcke. Die Baumstruktur
hat meist nur 3 - 4 Ebenen.
– Bei der Suche nach einem Satz mit gegebenem Primärschlüsselwert
müssen zunächst die Indexblöcke durchlaufen werden. Wegen der
geringen Anzahl können aber meist die oberen Ebenen der Struktur
im Hauptspeicher gepuffert werden, d.h. hierdurch werden nur sehr
wenige oder keine Blockübertragungen verursacht.
– B*-Bäume ermöglichen effiziente Implementierungen von Intervallabfragen und von sequentiellen Durchläufen in steigender oder fallender Reihenfolge der Primärschlüsselwerte.
– Verarbeitet man eine Menge von Sätzen in steigender oder fallender
Reihenfolge ihrer Primärschlüsselwerte, so wird jeder Index- oder
Primärdatenblock nur einmal von der Platte gelesen.
c
2002
Udo Kelter
Stand: 30.11.2002
Implementierung relationaler Operationen
6
Hash-Verfahren. Die Grundidee des Hash-Verfahrens, die zu speichernden Einheiten in einem Array zu verwalten, läßt sich direkt
auf die Verhältnisse bei eine Speicherung auf Platte adaptieren: Als
Array-Elemente wählt man Blöcke (bzw. Seiten), die ja ebenfalls direkt
adressierbar sind. In der Regel passen mehrere Sätze in einen Block;
man benötigt also noch interne Verwaltungsstrukturen innerhalb eines
Blocks.
Die grundlegenden Hash-Verfahren sehen bei einem Tabellenüberlauf ein komplettes Rehashing vor; im Hauptspeicher und bei kleinen
Datenbeständen mag das gehen, bei großen Datenbeständen auf Platte
ist dieses Vorgehen völlig unrealistisch. Beim offenen Hashing können
sehr lange Überlaufketten entstehen, was ebenfalls unattraktiv ist.
Eine praktikable Lösung dieses Problems besteht darin, in zwei
Schritten über eine Blockadreßtabelle auf Blöcke zuzugreifen:
Schlüsselwert
k
Hashfunktion
hash(k)
Seiten/Blöcke
Blockadreßtabelle
Abbildung 1: Erweiterbares Hashing
1. Schritt: Berechnung einer Position in der Blockadreßtabelle
2. Schritt: Zugriff auf den Datenblock und Durchsuchen desselben
Die Blockadreßtabelle sollte ca. 100 bis 1000 Mal kleiner als die
Datenbank gewählt werden und möglichst im Hauptspeicher gehalten werden. Verschiedene Einträge in der Blockadreßtabelle können
auf den gleichen Datenblock verweisen, d.h. in einem Block befinden
sich Sätze mit unterschiedlichem Hash-Wert. Schlecht gefüllt Datenblöcke können so vermieden werden. Die Blockadreßtabelle kann mit
vertretbarem Aufwand reorganisiert werden, ohne alle Datenblöcke zu
kopieren; daher nennt man dieses Verfahren auch erweiterbares Hac
2002
Udo Kelter
Stand: 30.11.2002
Implementierung relationaler Operationen
7
shing. Auf die möglichen Varianten von Reorganisationen und die
Behandlung von Blocküberläufe gehen wir hier nicht weiter ein.
Der prinzipielle Vorteil von Hash-Verfahren gegenüber Suchbäumen, daß keine Indexknoten durchlaufen werden müssen, bleibt erhalten: Im Idealfall wird über den Hashwert eines vorgegebenen
Primärschlüsselwerts sofort der Block gefunden, der den zugehörigen Satz enthält. Je nach der Überlaufbehandlung und der Änderungshäufigkeit im Datenbestand geht dieser Vorteil aber teilweise wieder verloren; auf Details gehen wir hier nicht ein.
Hash-Verfahren unterstützen keine Intervallabfragen.
3.2
Sekundärindexe
Sekundärindexe existieren separat vom Primärdatenbestand und unterstützen insb. auch die Suche nach nicht-identifizierenden Attributen
und Attributkombinationen.
Ein Sekundärindex unterstützt die Suche für eine Attributmenge A
(meist ist A einelementig); A wird auch als zugehöriger Suchschlüssel
bezeichnet. Konzeptuell ist der Sekundärindex eine Datenstruktur, die
für jede Wertekombination der Attribute aus A eine Trefferliste liefert.
Die Trefferliste enthält in irgendeiner Form Referenzen auf die Sätze,
bei denen die Wertekombination der Attribute auftritt. Beispielsweise
könnte es zu der Relation lieferungen einen Sekundärindex für das
Attribut Kundennummer geben; der Sekundärindex würde dann die Suche nach den Lieferungen an einen Kunden unterstützen.
Sekundärindexe stellen die Originaldaten in gewisser Weise umgekehrt (invertiert) dar; ein normales Tupel t enthält die Information,
daß ein Attribut A den Wert x hat, ein Index zum Attribut A enthält die
Information, daß der Wert x u.a. im Tupel t auftritt. Datenbestände
mit Index werden daher auch invertiert genannt.
Eine naheliegende Wahl für die Referenzen in den Trefferlisten sind
Primärschlüsselwerte. Die Trefferliste ist dann zu durchlaufen, und für
jeden Eintrag kann über den Primärindex auf den entsprechenden Satz
zugegriffen werden.
c
2002
Udo Kelter
Stand: 30.11.2002
Implementierung relationaler Operationen
8
Aktualisierung von Sekundärindexen. Wie schon erwähnt enthalten Sekundärindexe im Prinzip redundante Daten; werden die
Primärdaten geändert, müssen die Sekundärindexe entsprechend angepaßt werden. Wird z.B. beim Tupel t der Wert des Attributs A von
x1 nach x2 geändert, muß im Sekundärindex für den Suchschlüssel A
im Eintrag für x1 die Referenz auf t gelöscht und im Eintrag für x2
die Referenz auf t eingefügt werden. Wenn die beiden Einträge nicht
zufällig in der gleichen Seite liegen, müssen also wenigstens 2 Seiten
geschrieben1 und, falls sie nicht schon gepuffert waren, vorher gelesen
werden.
Änderungsoperationen werden also durch Sekundärindexe deutlich
teurer. Bei einer hinreichend hohen Änderungshäufigkeit können sich
(zu viele) Sekundärindexe daher insgesamt negativ auf die Systemleistung auswirken.
4
Optimierungen der Selektion
Bei der Selektion können Indexe unter bestimmten Umständen vorteilhaft ausgenutzt werden. Wir müssen hierzu verschiedene Formen
von Selektionsbedingungen unterscheiden:
Selektionsbedingung der Form σA=x . Wenn das Attribut A der
Primärschlüssel ist, kann sehr effizient mit konstantem Aufwand (also
O(1)) auf den einen Treffer zugegriffen werden.
Sofern ein Sekundärindex für das Attribut A vorliegt, hängt es von
bestimmten Umständen ab, ob es sich lohnt, den Index auszunutzen.
Der Einsatz lohnt nicht bei einer geringen Selektivität des Attributs.
Um dies präziser zu fassen, benötigen wir einige Größen; sei
sr
der durchschnittliche Speicherplatzbedarf eines Tupels
(incl. Hilfsdaten) der Relation r
1
Das Schreiben kann eine Zeitlang aufgeschoben werden, da die Indexdaten
aus den Primärdaten rekonstruiert werden können. Hier bestehen komplexe Zusammenhänge mit der Transaktionsverarbeitung, auf die wir hier nicht eingehen
können.
c
2002
Udo Kelter
Stand: 30.11.2002
Implementierung relationaler Operationen
9
b
die Größe eines Blocks
bf
= ⌊b / sr ⌋ der Blockungsfaktor, also die Zahl der Sätze,
die in einen Block passen
Beispiel: mit b=4096 Bytes und sr =200 ist bf=20.
|r|
die Zahl der Tupel in der Relation r
V(A,r)
die Zahl der verschiedenen Werte, die Attribut A in Relation r annimmt
Wenn man vereinfachend annimmt, daß jeder Wert des Attributs A
gleichhäufig auftritt, dann liefert eine Selektion der Form σA=x ungefähr | r | / V(A,r) Tupel zurück, oder anders gesagt den V(A,r)-ten
Teil der Relation r. Diesen “Verkleinerungsfaktor” bezeichnet man
auch als die Selektivität des Attributs A. Wenn nun
V(A,r) ≤ bf
ist, die Selektivität also kleinergleich dem Blockungsfaktor ist, ist unter
der Annahme, daß die Treffertupel gleichmäßig über die Blöcke verstreut liegen, in jedem Block wenigstens ein Treffertupel vorhanden,
d.h. praktisch alle Blöcke müssen übertragen werden. Durch den Einsatz des Sekundärindex können dann also keine Blockübertragungen
eingespart werden. Im Gegenteil führt die Benutzung des Sekundärindex zu zusätzlichen Blockübertragungen für Blöcke des Sekundärindex.
Hieraus folgt - insb. wenn man zusätzlich den Änderungsaufwand für
den Sekundärindex berücksichtigt -, daß Sekundärindexe für Attribute
mit geringer Selektivität nicht sinnvoll sind.
Selektionsbedingung der Form σA>x ∧ A<y (Intervallabfrage
zum Attribut A). Sofern die internen Zugriffsmethoden auch Intervallabfragen unterstützen (z.B. bei B-Bäumen), können auch diese
effizient bearbeitet werden, wobei hier der Aufwand linear von der
Größe der Treffermenge abhängt. Entscheidend ist hier die kompakte
(clusternde) Speicherung von Sätzen bzw. Tupeln mit aufeinanderfolgenden Schlüsselwerten innerhalb eines Blocks. Hierdurch braucht für
jeweils bf Sätze nur ein Block übertragen zu werden (mit Ausnahme
der “Randblöcke”).
c
2002
Udo Kelter
Stand: 30.11.2002
Implementierung relationaler Operationen
10
Selektionsbedingung der Form σA>x . Bei Selektionskriterien, in
denen Vergleichsoperatoren wie > verwendet werden, wird unter bestimmten Gleichverteilungsannahmen im Schnitt die halbe Relation
zurückgeliefert, d.h. im Sinne der vorstehenden Bemerkungen liegt eine
extrem schlechte Selektivität vor. Eine wesentliche Aufwandsreduktion gegenüber dem sequentiellen Durchsuchen der Relation ist also bei
>-Vergleichen durch Indexe nicht möglich.
Selektionsbedingung mit mehreren Attributen und einem
Index. Wenn das Selektionskriterium die Form σA=x ∧X hat und
für A ein Primär- oder Sekundärindex vorhanden ist, kann die undVerknüpfung in der Selektion konzeptionell auf die Schachtelung
σX (σA=x (...)) zurückgeführt werden, d.h. unter Ausnutzung des Index werden nur relativ wenige Tupel von der Platte gelesen; für diese
Tupel werden dann die weiteren Bedingungen direkt überprüft.
Vorteilhaft ist es in diesem Zusammenhang, wenn Tupel, die im
gleichen Block liegen, hintereinander verarbeitet werden und so letztlich jeder Block nur einmal übertragen werden muß. Werden die Tupel
in einem B*-Baum gespeichert, so kann man dies erreichen, indem man
die Tupel nach ihren Primärschlüsselwerten sortiert verarbeitet.
Selektionsbedingung mit mehreren Attributen und mehreren
Indexen. Sind mehrere elementare Bedingungen vorhanden, bei denen jeweils ein Sekundärindex für das auftretende Attribut vorhanden
ist, so können ggf. zunächst, bevor auf die eigentlichen Daten zugegriffen wird, Trefferlisten für die einzelnen Elementarbedingungen erstellt
und die logischen Verknüpfungen zwischen den Elementarbedingungen
durch entsprechende Mengenoperationen realisiert werden. Speziell
bei und-Verknüpfungen kann es sein, daß die Treffermenge auf diese
Weise deutlich verkleinert wird und weniger Blöcke übertragen werden
müssen
c
2002
Udo Kelter
Stand: 30.11.2002
Implementierung relationaler Operationen
5
11
Optimierungen der Projektion
Bei der Projektion läßt sich der Aufwand, die komplette Eingaberelation zu verarbeiten und ggf. Duplikate zu eliminieren, im Prinzip nicht
reduzieren.
Der Aufwand für das Lesen der Eingaberelation kann allerdings
komplett vermieden werden, wenn es sich bei der Eingaberelation um
ein Zwischenergebnis einer vorherigen Operation handelt, z.B. einer
Selektion oder einem Verbund, indem man die Projektion in die vorgeschaltete Operation integriert und gleich bei der Generierung des Zwischenergebnisses berücksichtigt. Konzeptionell handelt es sich dann
um neue, kombinierte Operationen. Die Annahme, daß eine Projektion nach einer anderen Operation erfolgt, ist sehr häufig schon bei
der Formulierung einer Abfrage erfüllt und kann oft vom Optimierer
durch Umstellung der Anfrage erreicht werden.
6
Optimierungen der Verbundberechnung
Verbunde sind häufig, da infolge der Normalisierung vielfach Daten,
die für eine Anwendung benötigt werden, auf mehrere Relationen verteilt werden. Die Ineffizienz des Grundalgorithmus für den Verbund
ist daher äußerst nachteilig, und es sind diverse Varianten und Optimierungsmaßnahmen entwickelt worden.
Einfaches Iterieren. Die oben skizzierte Implementierung wird
auch als Einfaches Iterieren oder nested loop join bezeichnet und
ist in Varianten für den natürlichen Verbund, den Θ-Verbund, die
äußeren Verbunde und das Kreuzprodukt anwendbar. In vereinfachter
Form handelt es sich um folgende geschachtelte Schleife:
for each tuple t1 in r1
for each tuple t2 in r2
pruefe, ob <t1|t2> in Ergebnismenge kommt
c
2002
Udo Kelter
Stand: 30.11.2002
Implementierung relationaler Operationen
12
Wenn z.B. | r1 | = 10.000 und | r2 | = 200 ist, dann wird die innere
Anweisung 2.000.000 Mal durchlaufen.
Eine wichtige Frage ist, ob die Relation r2 immer wieder neu von
der Platte gelesen werden muß und somit Blockübertragungen notwendig werden. Bei den heute üblichen Hauptspeichergrößen kann man
erhebliche Datenmengen im Hauptspeicher puffern. Wenn wir wenigstens eine Relation (also die kleinere) komplett im Hauptspeicher puffern können, tun wir das und brauchen somit beide Relationen nur
einmal zu lesen.
Relationen können aber trotzdem zu groß sein, um komplett gepuffert werden zu können. Die folgenden Überlegungen gehen zur Vereinfachung davon aus, daß immer nur ein Block gepuffert werden kann.
Sofern die Tupel der Relation r2 in zufälliger Reihenfolge, also
gestreut im entsprechenden DB-Segment, verarbeitet werden, muß
i.a. für jedes Tupel ein Block übertragen werden. Dies ist extrem
ungünstig, in unserem obigen Beispiel kommen wir auf 2.000.000
Blockübertragungen.
Eine offensichtliche Verbesserung liegt darin, die Relation r2 geblockt zu speichern - falls sie es nicht sowieso ist, lohnt es sich, eine
temporäre Kopie anzulegen - und sie bei jedem Durchlauf in physischer Reihenfolge zu lesen. Die Zahl der Blockübertragungen reduziert sich dann um den Blockungsfaktor. In unserem Beispiel würde
r2 bei einem Blockungsfaktor 20 nur 10 Blöcke belegen, bei 10.000
Schleifendurchläufen wären 100.000 Blockübertragungen nötig.
Blockorientiertes Iterieren. Eine weitere deutliche Verbesserungsmöglichkeit ergibt sich, wenn auch r1 einen hohen Blockungsfaktor hat. Anstatt nun für jedes Tupel in r1 jeweils die ganze Relation
r2 zu lesen, lesen wir immer einen Block in r1 und r2 und verarbeiten
alle darin enthaltenen Paare von Tupeln:
for each block B1 in r1
for each block B2 in r2
for each tuple t1 in B1
c
2002
Udo Kelter
Stand: 30.11.2002
Implementierung relationaler Operationen
13
for each tuple t2 in B2
pruefe, ob <t1|t2> in Ergebnismenge kommt
Die Zahl der Blockübertragungen reduziert sich dann noch einmal
um den Blockungsfaktor. Wenn in unserem Beispiel auch r1 einen
Blockungsfaktor 20 hat, also 500 Blöcke belegt, sind nur noch 5.000
Blockübertragungen erforderlich.
Wir haben bisher unterstellt, daß pro Relation genau ein Block gepuffert werden kann, was ziemlich unrealistisch ist. Sind insgesamt n
Blöcke für die Pufferung verfügbar, so bilden wir in beiden Relationen jeweils Abschnitte von n/2 Blöcken und behandeln jeweils einen
Abschnitt wie einen Block im obigen Algorithmus.
Verbundberechnung mit Index. Beim einfachen und blockorientierten Iterieren wird die zweite Relation im Prinzip immer wieder
sequentiell nach Verbundpartnern für das aktuell betrachtete Tupel
der ersten Relation durchsucht. Die lineare Suche ist das ineffizienteste Suchverfahren. Sofern für die zweite Relation ein Primär- oder
Sekundärindex für das Verbundattribut (bzw. die Verbundattribute)
vorliegt, ist mit dessen Hilfe eine wesentlich effizientere Suche möglich
(s. Bild 2). U.U. lohnt es sich, einen Index temporär aufzubauen.
r1
A
Index
für
r2
r2
A
Abbildung 2: Verbundberechnung mit Index
Diese Verbundberechnung mit Index ist im sehr häufigen Fall anwendbar, daß der Verbund über einen Fremdschlüssel gebildet wird; der
Fremdschlüssel ist dann in der anderen Relation Primärschlüssel. Ein
c
2002
Udo Kelter
Stand: 30.11.2002
Implementierung relationaler Operationen
14
Beispiel hierfür ist der schon früher betrachtete Verbund lieferungen
1 kunden.
Wie schon früher erwähnt lohnt der Einsatz von Indexen nicht,
wenn das unterstützte Attribut eine schlechte Selektivität hat. Bei
großen, nicht pufferbaren Relationen und geringer Selektivität des Verbundattributs entstehen allerdings immens große Resultate, die mit
hoher Wahrscheinlichkeit die verfügbaren Ressourcen überlasten, so
daß derartige Abfragen ohnehin unrealistisch sind.
Misch-Verbund (Merge Join). Sofern bei einem Verbund r1s
das Attribut A Verbundattribut ist und sowohl r als auch s nach A sortiert gespeichert sind, kann der Verbund unter gewissen Bedingungen
wie beim Misch-Algorithmus in einem einzigen parallelen Durchlauf
durch die beiden Relationen konstruiert werden.
r1
A
r2
A
x
x
x
x
x
Abbildung 3: Misch-Verbund
Hierzu wird in einer Schleife der jeweils nächstgrößere, in beiden
Relationen auftretende Wert des Verbundattributs bestimmt2 . In beiden Relationen bilden die Tupel, bei denen dieser Wert auftritt, jeweils
ein “Abschnitt”. Alle Tupel in den beiden Abschnitten müssen paarweise kombiniert und ausgegeben bzw. weiterverarbeitet werden.
Sofern das Verbundattribut eine hohe Selektivität hat, sind diese
Abschnitte kurz und können wahrscheinlich komplett gepuffert werden. Andernfalls werden diese Abschnitte entsprechend lang - im Extremfall kann die ganze Relation einen einzigen Abschnitt bilden -, d.h.
2
Werte, die nur in einer der Relationen auftreten, müssen nur bei äußeren Verbunden betrachtet werden.
c
2002
Udo Kelter
Stand: 30.11.2002
Implementierung relationaler Operationen
15
wir stehen hier wieder vor dem Problem, einen Abschnitt puffern zu
müssen. Allerdings sind, wie schon oben erwähnt, Verbundattribute
mit geringer Selektivität ohnehin eher unrealistisch.
3-Wege-Verbund. Ein Verbund zwischen drei Relationen r1 1 r2
1 r3 kann im Prinzip auf die Hintereinanderschaltung zweier binärer
Verbunde (entweder (r11r2) 1 r3 oder r1 1 (r21r3) ) zurückgeführt
werden. Anzustreben ist in diesem Fall ein möglichst kleines Zwischenergebnis.
Alternativ kann der 3-stellige Verbund auch direkt, also ohne die
ggf. aufwendige Erzeugung eines Zwischenergebnisses, erzeugt werden.
Als Grundidee verwenden wir die Verbundberechnung mit Index. Wir
durchlaufen die mittlere Relation tupelweise (s. Bild 4) und suchen
jeweils “links” (in r1) und “rechts” (in r3) mit Unterstützung je eines
Index nach Verbundpartnern.
r1
A
r2
A B
r3
B
Abbildung 4: 3-Wege-Verbund
Dieses Verfahren ist besonders vorteilhaft anwendbar, wenn r2 eine
Verbindungstabelle zwischen r1 und r3 ist.
Literatur
[RDBM] Kelter, U.: Lehrmodul “Das relationale Datenbankmodell”;
2002
[AVO] Kelter, U.: Lehrmodul “Abfrageverarbeitung und Optimierung”; 2003
c
2002
Udo Kelter
Stand: 30.11.2002
Implementierung relationaler Operationen
16
Glossar
3-Wege-Verbund: Verfahren zur Berechnung von zwei Verbunden mit 3
Eingaberelationen
einfaches Iterieren: Verfahren zur Verbundberechnung, bei dem die beiden Eingaberelationen in zwei geschachtelten Schleifen durchlaufen
werden
erweiterbares Hashing: Variante des Hashings, bei dem die Hashtabelle
über eine Umsetztabelle indirekt adressiert wird und die einzelnen Felder der Hashtabelle gestreut auf der Platte gespeichert werden können
invertierter Datenbestand: Datenbestand, zu dem ein oder mehrere Sekundärindexe vorhanden sind
Misch-Verbund (merge join): Verfahren zur Verbundberechnung, bei dem
die beiden Eingaberelationen zunächst nach den Verbundattributen
sortiert werden und dann für jeden auftretende Wertekombination der
Verbundattribute eine “lokaler” Verbund berechnet wird
Sekundärindex: Verzeichnis, das zu einzelnen Werten eine Liste von Referenzen auf die Speichereinheiten enthält, in denen dieser Attributwert
auftritt
Selektivität (eines Attributs einer Relation): Zahl der verschiedenen Werte des Attributs in seiner Relation; der entsprechende Bruchteil der
Relation wird im Durchschnitt geliefert, wenn nach einen auftretenden Wert des Attributs selektiert wird
c
2002
Udo Kelter
Stand: 30.11.2002
Index
V(A,r), 9
Verbundberechnung
3-Wege-Verbund, 15, 16
blockorientiertes Iterieren, 12
einfaches Iterieren, 11, 16
Misch-Verbund, 14, 16
mit Index, 13
3-Wege-Verbund, siehe Verbundberechnung
Abfrage
Intervall-∼, 5, 9
Zwischenergebnis, 11, 15
B*-Baum, 5
Blockadreßtabelle, 6
Blockungsfaktor, 9
Hash-Verfahren, 5
erweiterbares, 6, 16
Index, 5
Indexblock, 5
invertierter Datenbestand, 7, 16
Misch-Verbund, siehe Verbundberechnung
nested loop join, 11
Optimierung
Projektion, 11
Selektion, 8
Verbundberechnung, 11
von Elementaroperationen, 3
Primärindex, 5
sr , 8
Schlüssel
Fremdschlüssel, 13
Suchschlüssel, 7
Sekundärindex, 7, 10, 13, 16
Aktualisierung, 7
Selektivität, 9, 16
17
Herunterladen