Fachgebiet Datenbanksysteme Institut für Informationssysteme Fachbereich Informatik Universität Hannover Bachelorarbeit im Studiengang Angewandte Informatik Erweiterung eines relationalen Anfragesimulators um eine regelbasierte Steuerung von physischen Optimierungsregeln Moritz Diehle Matr.Nr. 2003050 16. August 2004 Erstprüfer: Prof. Dr. Udo Lipeck Zweitprüfer: Dr. Hans-Hermann Brüggemann Betreuer: Dipl.-Math. Mazeyar E. Makoui Erklärung Hiermit versichere ich, Moritz Diehle, die vorliegende Bachelorarbeit ohne fremde Hilfe und nur unter Verwendung der von mir aufgeführten Quellen und Hilfsmittel angefertigt zu haben. Hannover, 16. August 2004. Danksagung An dieser Stelle möchte ich mich bei allen bedanken, die mich während dieser Arbeit unterstützt haben. Besonderer Dank geht an Herrn Prof. Dr. Lipeck, der mich durch seine Fragen auf mögliche Schwachpunkte in Implementierung und Argumentation hinwies. Desweiteren möchte ich Herrn Dr. Brüggemann für seinen Einsatz als Koreferent danken. Weiterhin möchte ich meinem Betreuer Dipl.-Math. Mazeyar E. Makoui für seine fortwährende Motivation und Herrn Christoph Echtermeyer für seine konstruktive Kritik danken. Außerdem möchte ich noch meinen Eltern danken, die mir dieses Studium ermöglicht haben. Hannover, 16. August 2004 Zusammenfassung Ziel der Arbeit ist die Erweiterung des vorhandenen regelbasierten Anfragesimulators RELOpt. Schwerpunkt sind hier die regelbasierte Steuerung von physischen Optimierungsstrategien. Außerdem sollen kostenbasierte Aspekte betrachtet und implementiert werden. Hauptbestandteil dieser Arbeit ist die über die grafische Benutzerschnittstelle mögliche Auswahl der neuen Regeln sowie der daraus resultierenden Strategien. Dabei soll die Bildung von Regelgruppen durch Zusammenfassen von Regeln, sowie deren Iteration ermöglicht werden. Ein weiterer Teil dieser Arbeit behandelt die Anbindung von RELOpt an eine OracleDatenbank. Über diese Schnittstelle kann der Nutzer Tabellen und ihre Attribute, sowie deren Metadaten in Richtung RELOpt importieren. Desweiteren kann man über diese Schnittstelle die Anfragepläne von RELOpt mit denen der Oracle-Datenbank vergleichen. Zur Anwendung der obigen Implementierungen sollen Anfragepläne verschiedener Beispielanfragen analysiert, sowie die Oracle-Regelstrategie weitestgehend nachgebildet werden. Inhaltsverzeichnis 1 Einleitung 1.1 Das System RELOpt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Ziel dieser Arbeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 Aufbau dieser Arbeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 2 5 6 2 Physische Optimierung 2.1 Physische Optimierungsregeln . . . . . . . . . . . . . . . . . . . . . . . . 7 7 3 Kostenbasierte Optimierung von Verbundfolgen 3.1 Problemstellung . . . . . . . . . . . . . . . . . . . 3.2 Optimierung mit dynamischer Programmierung . 3.2.1 Optimierung von kartesischen Produkten . 3.2.2 Der Algorithmus im Pseudocode . . . . . . 3.2.3 Erweiterung auf Verbunde . . . . . . . . . 3.2.4 Neue Kostenfunktion . . . . . . . . . . . . 3.2.5 Beispiel mit Verbunden . . . . . . . . . . . 3.2.6 Behandlung von Selektionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 13 14 14 15 17 18 19 19 4 Anbindung an die Oracle-Datenbank 4.1 Importieren von Tabellen . . . . . . . . . . . . . 4.2 Importieren von Statistiken . . . . . . . . . . . 4.3 Import von Anfrageplänen . . . . . . . . . . . . 4.3.1 Der Übersetzer . . . . . . . . . . . . . . 4.3.2 Die Regeln . . . . . . . . . . . . . . . . . 4.4 Anfrageplanerstellung in der Oracle Datenbank 4.5 Implementierung . . . . . . . . . . . . . . . . . 4.5.1 Klassen . . . . . . . . . . . . . . . . . . 4.5.2 Die Regeln . . . . . . . . . . . . . . . . . 4.5.3 Der Übersetzer . . . . . . . . . . . . . . 4.5.4 Die Benutzerschnittstelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 21 23 24 24 24 26 27 27 29 30 32 5 Experimente und Anwendungen 5.1 Vergleich Join-Order mit Minimum-Selektivity 5.1.1 Beispiele in Form von left-deep-trees“ ” 5.1.2 Fazit . . . . . . . . . . . . . . . . . . . 5.2 Operationen der Oracle-Datenbank . . . . . . 5.2.1 Struktur der Oracle-Anfragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 33 33 34 35 35 vii . . . . . viii INHALTSVERZEICHNIS 5.3 5.2.2 Umsetzung der Oracle-Operationen in RELOpt Vergleiche mit der Oracle-Datenbank . . . . . . . . . . 5.3.1 Beispielanfrage ohne Selektion . . . . . . . . . . 5.3.2 Beispielanfrage mit Selektion . . . . . . . . . . 5.3.3 Beispielanfrage mit Kartesischen Produkten . . 5.3.4 Fazit . . . . . . . . . . . . . . . . . . . . . . . . 6 Erweiterungen am Programm RELOpt 6.1 Regeln . . . . . . . . . . . . . . . . . . . . . . 6.2 Regelauswahl . . . . . . . . . . . . . . . . . . 6.3 Zusammenlegung von Relation und Metadaten 6.4 Die Paketstruktur . . . . . . . . . . . . . . . . 6.5 Implementierung . . . . . . . . . . . . . . . . 6.5.1 Vereinheitlichung des Regelsystems . . 6.5.2 Umsetzung der neuen Regelstruktur . . 6.5.3 Anpassung des physischen Optimierers 6.5.4 Die Regelauswahl . . . . . . . . . . . . 6.5.5 Der Join-Order-Algorithmus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 37 37 38 39 42 . . . . . . . . . . 43 43 44 45 46 47 47 48 50 50 51 7 Ausblick 55 Abbildungsverzeichnis 57 Tabellenverzeichnis 59 Literaturverzeichnis 61 Kapitel 1 Einleitung Datenbankanfragen in SQL sind darauf ausgelegt, Daten aus einer Datenbank zu extrahieren. Da man im allgemeinen nur an den Daten interessiert ist, nicht aber an der Art und Weise, wie sie gewonnen werden, liegt die optimale Aufbereitung dieser Daten bei dem verwendeten Datenbanksystem. Der Nutzer legt hier vor allem Wert auf schnelle Antwortzeiten und die Korrektheit der gelieferten Daten. In einem Datenbanksystem wird die vom Nutzer gestellte Anfrage zunächst durch einen Optimierer in einen Anfrageplan umgewandelt. Da sich die Anfragen in den meisten Fällen durch verschiedene, im Ergebnis äquivalente Anfragepläne ausdrücken lassen, ist es Aufgabe des Optimierers einen möglichst günstigen Anfrageplan zu finden. Da der Datenbanknutzer eine schnelle Abarbeitung seiner Anfrage erwartet, kann der Optimierer im Normalfall nie alle möglichen Anfragepläne erstellen und gegeneinander abwägen. Bei der Optimierung ist also die Dauer des Vorgangs von entscheidender Bedeutung. Eine Optimierung, die zwar die günstigste Alternative findet, im Endeffekt aber länger dauert als die erstbeste Variante, ist nicht sinnvoll. Um günstige Anfragepläne zu ermitteln, ist es im allgemeinen sinnvoll, auf statistische Daten über den Datenbankinhalt zuzugreifen. Diese können dann von einem kostenbasierten Optimierer verwendet werden, um mittels verschiedener Heuristiken den Anfrageplan zu verbessern. Die Anfrageoptimierung lässt sich in drei Schritte unterteilen: 1. Algebraische Optimierung In dieser Phase werden verschiedene algebraische Regeln auf die Anfrage angewendet. Ziel ist hier die Minimierung der Antwortzeiten, insbesondere bei Verbundoperationen. Dies geschieht zum Beispiel durch Verschieben von Projektionen und die frühe Anwendung von Selektionen. 1 2 KAPITEL 1. EINLEITUNG 2. Physische Optimierung In dieser Phase werden die einzelnen Teile der Anfrage durch konkrete physische Implementierungen der Algorithmen ersetzt. Zum Beispiel könnte hier ein Verbund durch einen Relationen-Index-Verbund ersetzt werden, wenn ein Index auf die zweite Relation des Verbundes existiert. 3. Kostenbasierte Optimierung In dieser Phase werden mittels Kostenfunktionen Anfragepläne erstellt und verglichen, um den günstigsten zu bestimmen. Diese Arbeit basiert auf dem in der Diplomarbeit [Mak03] entwickelten und in der Bachelorarbeit [War03] erweiterten Programm RELOpt. 1.1 Das System RELOpt Bei dem Programm RELOpt handelt es sich um einen Simulator für relationale Anfrageoptimierung. Es wandelt die vom Benutzer eingegebene Anfrage in drei Schritten in einen Anfrageplan um. Dazu wird im ersten Schritt ein Baum von algebraischen Operationen erzeugt und mit Hilfe algebraischer Optimierungsregeln optimiert. Im zweiten Schritt wird der alge” braische“ Baum in einen Baum aus physischen Operationen transformiert. Eine physische Operation ist die Implementierung einer algebraischen Operation, zum Beispiel der Nested-Loop-Join, oder eine Index-Selektion mit Duplikateneliminierung. Dies geschieht mit Hilfe von physischen Transformationsregeln. Im letzten Schritt wird dann der Baum unter kostenbasierten Gesichtspunkten weiter optimiert. Der Benutzer kann die Ergebnisse der einzelnen Schritte getrennt voneinander als Text und als grafische Darstellung betrachten. Die Regeln für die ersten beiden Schritte sind in Dialogen übersichtlich dargestellt und können vom Benutzer angepasst werden. Die für die physische und kostenbasierte Optimierung notwendigen Metadaten können vom Benutzer eingegeben werden. Es folgt ein kurzes Beispiel der drei Schritte. Relation Kardinalität Attribute n(A,R) P 10 {ID, Name} ID=10, Name=7 S 20 {MatrNr, Semester} MatrNr=20, Semester=6 V 30 {VorlNr, gelesenVon} VorlNr=30, gelesenVon=10 H 40 {MatrNr, VorlNr} MatrNr=20, VorlNr=30 Tabelle 1.1: Beispielrelationen 1.1. DAS SYSTEM RELOPT 3 Relation Index P {ID} S {MatrNr} {VorlNr} V H {MatrNr, VorlNr} Tabelle 1.2: Indexe der Beispielrelationen Der Benutzer möchte in der folgenden Anfrage alle Professoren erhalten, deren Vorlesungen von Studenten des fünften Semesters besucht werden. Die benutzten Relationen sind in Tabelle 1.1 zu finden. Die vorhandenen Indexe der Attribute sind in der Tabelle 1.2 zu finden. In der Spalte Relation der Tabelle 1.1 findet sich der Name der Relation, die Spalte Kardinalität enthält die Anzahl der Tupel in der Relation. Die Spalte Attribute enthält eine Liste der Attribute der Relation. Die Spalte n(A,R) enthält die Anzahl der eindeutigen Tupel pro Attribut. Die Spalte Index der Tabelle 1.2 enthält eine Liste der Attribute, für die ein Index vorhanden ist. Die Anfrage in der Notation von RELOpt: (PROJECTION P.Name (SELECTION S.Semester=’5’ (JOIN P.ID=V.gelesenVon P (JOIN V.VorlNr=H.VorlNr V (JOIN H.MatrNr=S.MatrNr H S))))) Der Relationale Parser erzeugt daraus den in Abbildung 1.1 gezeigten äquivalenten Baum aus algebraischen Operationen.1 πP.Name σS.Semester =’5’ ⋊ ⋉P.ID =V.gelesenVon P ⋊ ⋉V.VorlNr =H.VorlNr V ⋊ ⋉H.MatrNr =S.MatrNr H S Abbildung 1.1: Anfragebaum der Beispielanfrage 1 für eine Erklärung der Symbole siehe [Lip03], [War03] und [Mak03] 4 KAPITEL 1. EINLEITUNG Das Ergebnis des Relationalen Parsers wird an den Algebraischen Optimierer übergeben. Dieser optimiert anhand der ihm gegebenen Regeln den vom Parser erstellten algebraischen Baum. Am Beispiel in Abbildung 1.2 erkennt man, dass die Reihenfolge der Joins verändert wurde. Außerdem wurde die Selektion nach innen verschoben. πP.Name ⋊ ⋉P.ID =V.gelesenVon ⋊ ⋉V.VorlNr =H.VorlNr V ⋊ ⋉H.MatrNr =S.MatrNr σS.Semester =’5’ P H S Abbildung 1.2: algebraischer Baum der Beispielanfrage Der physische Optimierer ersetzt nun die algebraischen Operationen anhand von Regeln durch physische Operationen. In diesem Fall wird zum Beispiel die Projektion durch eine Relationenscan-Projektion mit Duplikateneliminierung ersetzt. Die Selektion wird durch eine Relationen-Selektion ersetzt, da es keinen Index für Semester gibt und S auch nicht nach Semester sortiert ist. Rel/elim πP.Name (20) ⋊ ⋉Rel-Index P.ID =V.gelesenVon (8) ⋊ ⋉Rel-Index V.VorlNr =H.VorlNr (11) ⋊ ⋉Rel-Index H.MatrNr =S.MatrNr (10) Rel σS.Semester =’5’ (1) P V H S Abbildung 1.3: physischer Baum der Beispielanfrage Da es für H.MatrNr einen Index gibt, wird der beteiligte Verbund in einen Rel-IndexVerbund2 umgewandelt. Hier existiert ein Index für das Attribut H.VorlNr. Ebenso wird aus den Verbunden, an denen die Relationen V und P beteiligt sind, jeweils ein RelIndex-Verbund erzeugt. Dies ist möglich, da die für den Verbund benutzten Attribute über einen Index verfügen. Das Ergebnis der Umwandlung ist in Abbildung 1.3 zu sehen. 2 siehe hierzu [Mak03] oder [War03] 1.2. ZIEL DIESER ARBEIT 5 Am Ende wird der physische Baum an den kostenbasierten Optimierer übergeben. Dieser verwendet verschiedene Strategien, wie zum Beispiel das Erstellen von Sortierungen oder Indexen, um mögliche Optimierungen zu finden. Der standardmäßig eingestellte Optimierer kombiniert Sortierungen und Indexe der in den Verbundoperationen vorkommenden Relationen, und ermittelt dann aus den resultierenden Verbunden den Günstigsten. Index/elim πP.Name (1) Tree(P.Name)(12) ⋊ ⋉Hash P.ID =V.gelesenVon (5) Hash(·) Hash(·) ⋊ ⋉Hash V.VorlNr =H.VorlNr (5) P Hash(·) Hash(·) ⋊ ⋉Hash H.MatrNr =S.MatrNr (3) V Hash(·) Hash(·) Rel σS.Semester =’5’ (1) H S Abbildung 1.4: Anfragebaum des Beispiels nach der kostenbasierten Optimierung Die kostenbasierte Optimierung liefert den in Abbildung 1.4 gezeigten Anfragebaum. Alle Verbunde wurden durch kostengünstige Hash-Verbunde ersetzt. Dies ist möglich, da für jedes an einem Hash-Verbund teilnehmende Element ein Hash angelegt wird. Die Projektion wurde durch eine Index-Projektion mit Duplikateneliminierung ersetzt. Dies wird durch eine vorhergehende Erstellung eines Indexbaumes über die Ergebnisrelation ermöglicht. Diese Lösung scheint auf den ersten Blick verwunderlich, da die Erstellung eines Index eine teure Operation ist. Aufgrund der geringen Anzahl von Tupeln in den Basisrelationen ist diese Lösung aber tatsächlich günstiger. Erhöht man die Anzahl der Tupel in den Basisrelationen, liefert RELOpt eine Lösung mit einer Sortierung der Ergebnistupel Sorted/elim und anschließender Projektion (πP.Name ) mit Duplikateneliminierung. 1.2 Ziel dieser Arbeit Ziel der Arbeit ist die Erweiterung des Programms RELOpt. Zum einen soll eine flexible regelbasierte Steuerung der algebraischen und physischen Regeln ermöglicht werden. 6 KAPITEL 1. EINLEITUNG Dies gibt dem Benutzer die Möglichkeit, verschiedene Optimierungsstrategien zu benutzen und zu vergleichen. Weiterhin soll das Programm um einen neuen kostenbasierten Optimierer erweitert werden. Im einzelnen sind zu entwickeln: • Erweiterung der algebraischen und physischen Regelsteuerung RELOpt soll eine flexible regelbasierte Steuerung bekommen, die es dem Benutzer erlaubt, Regelgruppen zu definieren und diese iterativ anzuwenden. Die neue einheitliche Struktur der Regeln soll späteren Erweiterungen zugute kommen. • Anbindung an die Oracle-Datenbank Der Benutzer soll Relationen und ihre Metadaten aus einer Oracle-Datenbank importieren können. Außerdem soll er die Möglichkeit haben, die von RELOpt erzeugten Anfragepläne mit denen des Oracle-Systems zu vergleichen. Zu diesem Zweck muss RELOpt so erweitert werden, dass es vom Benutzer eingegebene Anfragen in äquivalente SQL-Anfragen umwandeln kann. • Implementierung eines neuen kostenbasierten Optimierers RELOpt soll um einen neuen kostenbasierten Optimierer erweitert werden. Der Benutzer hat in der grafischen Oberfläche dann die Möglichkeit, zwischen verschiedenen Optimierern zu wählen. • Anwendungen Es sollen Vergleiche des neu implementierten Optimierers mit dem vorhandenen Optimierer durchgeführt werden. Außerdem sollen die von RELOpt gelieferten Anfragepläne mit denen des Oracle-Systems verglichen werden. 1.3 Aufbau dieser Arbeit Kapitel 2 behandelt physische Regeln. Im Anschluss daran werden in Kapitel 3 die Grundlagen und die Implementierung eines neuen kostenbasierten Optimierers behandelt. Im Kapitel 4 wird die Anbindung an eine Oracle-Datenbank dargestellt. Es finden sich dort Hinweise zur Benutzung und Erläuterungen zu den Implementierungen. Kapitel 5 enthält Experimente und Anwendungen des neuen Algorithmus, sowie Vergleiche zur Optimierungsstrategie von Oracle. Kapitel 6 geht auf die Erweiterung des Programms RELOpt ein. Benutzung der neuen Funktionen und deren Implementierung sind hier dargelegt. In Kapitel 7 wird kurz ein Abriss darüber gegeben, welche Aspekte noch weiter betrachtet werden können. Abschließend findet sich das Literaturverzeichnis, sowie das Tabellenund das Abbildungsverzeichnis. Kapitel 2 Physische Optimierung Dieses Kapitel befasst sich mit den im Programm RELOpt implementierten Regeln und ihrer Umsetzung in ein regelbasiertes System. Durch Analyse der in der Literatur [Mit95],[Mak03] und [War03] behandelten physischen Optimierungen kann man die im folgenden Abschnitt beschriebenen Regeln definieren. Diese Regeln können dann später in einem regelbasierten Optimierer benutzt werden. 2.1 Physische Optimierungsregeln In diesem Abschnitt benutzte Abkürzungen sind: R, S A M ϕ sch(R) attr(ϕ) sort(R) Relationen ein Attribut eine Menge eine Bedingung Menge der Attribute der Relation R Menge der in ϕ vorkommende Attribute einelementige Menge, enthält das sortierte Attribut aus R, falls R sortiert ist. Ist R nicht sortiert, wird die leere Menge zurückgegeben. index(R) Menge aller Attribute aus R, die einen Index besitzen Weiterhin seien folgende Funktionen definiert: ( #(M ) = P0 : für M = ∅ 1 : sonst m∈M attrsch(ϕ, R) = 1 : für #(attr(ϕ) ∩ sch(R)) = 1 0 : sonst 7 8 KAPITEL 2. PHYSISCHE OPTIMIERUNG 1 : für (attr(ϕ) ∩ sort(R)) 6= ∅ 0 : sonst 1 : für (attr(ϕ) ∩ index(R)) 6= ∅ 0 : sonst attrsort(ϕ, R) = attrindex(ϕ, R) = • [Index|Sorted|Nested]DupProjectionRule – IndexDupProjectionRule wandelt eine algebraische Projektion in eine physische Index-Projektion mit Duplikateneliminierung um, wenn ein Index auf das Attribut besteht. A ∈ index(R) Index/elim ⇒ πA (R) := πA (R) – SortedDupProjectionRule verhält sich ähnlich, nur wird hier auf das Vorhandensein einer Sortierung geprüft. A ∈ sort(R) Sort/elim ⇒ πA (R) := πA (R) – NestedDupProjectionRule kann auf alle algebraischen Projektionen angewendet werden. Rel/elim πA (R) := πA (R) • [Merge|IndexIndex|RelIndex|NestedLoop]JoinRule – MergeJoinRule Wandelt einen algebraischen Join in einen physischen Merge-Join um, wenn beide Relationen sortiert vorliegen. attrsch(ϕ, R) ∧ attrsort(ϕ, R) ∧ attrsch(ϕ, S) ∧ attrsort(ϕ, S) ⇒Ro nϕ S := R o nMerge S ϕ – IndexIndexJoinRule Wandelt einen algebraischen Join in einen Index-Index-Join um, wenn für beide Relationen ein Index vorhanden ist. attrsch(ϕ, R) ∧ attrindex(ϕ, R) ∧ attrsch(ϕ, S) ∧ attrindex(ϕ, S) ⇒Ro nϕ S := R o nIndex,Index S ϕ – RelIndexJoinRule Wandelt einen Join in einen Rel-Index-Join um, wenn für eine der beiden Relationen ein Index vorliegt. Fall 1: ¬attrindex(ϕ, R) ∧ attrsch(ϕ, S) ∧ attrindex(ϕ, S) 2.1. PHYSISCHE OPTIMIERUNGSREGELN 9 ⇒Ro nϕ S := R o nRel,Index S ϕ Fall 2: attrsch(ϕ, R) ∧ attrindex(ϕ, R) ∧ ¬attrindex(ϕ, S) ⇒Ro nϕ S := S o nRel,Index R ϕ – NestedLoopJoinRule Diese Regel ist auf alle algebraischen Joins anwendbar. Ro nϕ S := R o nNestedLoop S ϕ • [Merge|IndexIndex|RelIndex|NestedLoop]SemijoinRule – MergeSemijoinRule Wandelt einen algebraischen Semijoin in einen physischen Merge-Semijoin um, wenn beide Relationen sortiert vorliegen. attrsch(ϕ, R) ∧ attrsort(ϕ, R) ∧ attrsch(ϕ, S) ∧ attrsort(ϕ, S) ⇒ R nϕ S := R nMerge S ϕ – IndexIndexSemijoinRule Wandelt einen algebraischen Semijoin in einen Index-Index-Semijoin um, wenn für beide Relationen ein Index vorhanden ist. attrsch(ϕ, R) ∧ attrindex(ϕ, R) ∧ attrsch(ϕ, S) ∧ attrindex(ϕ, S) ⇒ R nϕ S := R nIndex,Index S ϕ – RelIndexSemijoinRule Fall 1: wandelt einen Semijoin in einen Rel-Index-Semijoin um, wenn für die Zweite der beiden Relationen ein Index vorliegt. ¬attrindex(ϕ, R) ∧ attrsch(ϕ, S) ∧ attrindex(ϕ, S) ⇒ R nϕ S := R nRel,Index S ϕ Fall 2: wandelt einen Semijoin in einen Index-Rel-Semijoin um, wenn für die Erste der beiden Relationen ein Index vorliegt. attrsch(ϕ, R) ∧ attrindex(ϕ, R) ∧ ¬attrindex(ϕ, S) ⇒ R nϕ S := R nIndex,Rel S ϕ – NestedLoopSemijoinRule Diese Regel ist auf alle algebraischen Semijoins anwendbar. R nϕ S := R nNestedLoop S ϕ 10 KAPITEL 2. PHYSISCHE OPTIMIERUNG • [Merge|IndexIndex|RelIndex|NestedLoop]AntisemijoinRule – MergeAntisemijoinRule Wandelt einen algebraischen Antisemijoin in einen physischen Merge-Antisemijoin um, wenn beide Relationen sortiert vorliegen. attrsch(ϕ, R) ∧ attrsort(ϕ, R) ∧ attrsch(ϕ, S) ∧ attrsort(ϕ, S) Merge ⇒ R nϕ S := R nϕ S – IndexIndexAntisemijoinRule Wandelt einen algebraischen Antisemijoin in einen Index-Index-Antisemijoin um, wenn für beide Relationen ein Index vorhanden ist. attrsch(ϕ, R) ∧ attrindex(ϕ, R) ∧ attrsch(ϕ, S) ∧ attrindex(ϕ, S) Index,Index ⇒ R nϕ S := R nϕ S – RelIndexAntisemijoinRule Fall 1: wandelt einen Antisemijoin in einen Rel-Index-Antisemijoin um, wenn für die Zweite der beiden Relationen ein Index vorliegt. ¬attrindex(ϕ, R) ∧ attrsch(ϕ, S) ∧ attrindex(ϕ, S) Rel,Index ⇒ R nϕ S := R nϕ S Fall 2: wandelt einen Antisemijoin in einen Index-Rel-Antisemijoin um, wenn für die Erste der beiden Relationen ein Index vorliegt. attrsch(ϕ, R) ∧ attrindex(ϕ, R) ∧ ¬attrindex(ϕ, S) Index,Rel ⇒ R nϕ S := R nϕ S – NestedLoopAntisemijoinRule Diese Regel ist auf alle algebraischen Antisemijoins anwendbar. NestedLoop R nϕ S := R nϕ S • [Merge|IndexIndex|RelIndex|NestedLoop]UnionRule Alle hier vorgestellten physischen Vereinigungen arbeiten mit Duplikateneliminierung. – MergeUnionRule Wandelt eine algebraische Union in eine physische Merge-Union um, wenn beide Relationen sortiert vorliegen. attrsch(ϕ, R) ∧ attrsort(ϕ, R) ∧ attrsch(ϕ, S) ∧ attrsort(ϕ, S) ⇒ R ∪ S := R ∪Merge S 2.1. PHYSISCHE OPTIMIERUNGSREGELN 11 – IndexIndexUnionRule Wandelt eine algebraischen Union in eine Index-Index-Union um, wenn für beide Relationen ein Index vorhanden ist. attrsch(ϕ, R) ∧ attrindex(ϕ, R) ∧ attrsch(ϕ, S) ∧ attrindex(ϕ, S) ⇒ R ∪ S := R ∪Index,Index S – RelIndexUnionRule Wandelt eine Union in eine Rel-Index-Union um, wenn für eine der beiden Relationen ein Index vorliegt. Fall 1: ¬attrindex(ϕ, R) ∧ attrsch(ϕ, S) ∧ attrindex(ϕ, S) ⇒ R ∪ S := R ∪Rel,Index S oder Fall 2: attrsch(ϕ, R) ∧ attrindex(ϕ, R) ∧ ¬attrindex(ϕ, S) ⇒ R ∪ S := S ∪Rel,Index R – NestedLoopUnionRule Diese Regel ist auf alle algebraischen Unions anwendbar. R ∪ S := R ∪NestedLoop S • [Index|Rel]SelectionRule – IndexSelectionRule Wandelt eine vorhandene algebraische Selektion in eine Index-Selektion um, wenn für das Attribut ein Index existiert. (#(attr(ϕ)) = 1) ∧ attrindex(ϕ, R) ⇒ σϕ (R) := σϕIndex (R) – RelSelectionRule Diese Regel kann alle algebraischen Selektionen behandeln. σϕ := σϕRel • ProductRule Wandelt ein Product in einen Join ohne Bedingung um. R × S := R o ntrue S 12 KAPITEL 2. PHYSISCHE OPTIMIERUNG • DifferenceRule Wandelt eine Differenz in einen Antisemijoin mit Bedingung um. R − S := R nϕ BS Die Bedingung ergibt sich wie folgt: ^ ϕ= R.A = B.A, mit T := sch(R) ∩ sch(S) A ∈ T • IntersectionRule Wandelt einen Durchschnitt in einen Semijoin mit Bedingung um. R ∩ S := R nϕ S Die Bedingung ergibt sich wie folgt: ^ ϕ= R.A = S.A, mit T := sch(R) ∩ sch(S) A ∈ T Kapitel 3 Kostenbasierte Optimierung von Verbundfolgen Bei der kostenbasierten Optimierung können unterschiedliche Strategien benutzt werden, um einen Anfrageplan zu verbessern. Der in diesem Kapitel beschriebene Optimierer verbessert die Abfolge von Verbund-Operationen mit Hilfe dynamischer Programmierung und der in [VM96] beschriebenen Algorithmen. Er arbeitet auf dem algebraischen Anfragebaum unter Zuhilfenahme der zu den benutzten Relationen gehörenden Statistiken. Der Algorithmus wurde als Alternative zu dem in [War03] implementierten MinimumSelectivity-Algorithmus gewählt, um eine Möglichkeit zu haben, Lösungen im kompletten Suchraum zu finden, und diese mit den Lösungen aus dem auf left-deep trees“ einge” schränkten Suchraum zu vergleichen. Vergleiche an ausgesuchten Beispielen finden sich im Kapitel 5. 3.1 Problemstellung Enthält eine vom Benutzer gestellte Anfrage mehrere Verbund-Operationen, so ist in den meisten Fällen nicht erkennbar, in welcher Reihenfolge die Verbunde optimal ausgeführt werden. Ein Optimierer muss anhand der ihm vorliegenden statistischen Daten ermitteln, in welcher Ausführungsreihenfolge die Verbunde die geringsten Kosten verursachen. Bei der Suche nach optimalen Anfrageplänen kann der Optimierer in den meisten Fällen aus Zeitgründen nicht alle möglichen Teilbäume untersuchen. Viele Algorithmen schränken daher den Suchraum ein, und betrachten etwa nur left-deep trees“. Der in diesem ” Kapitel erläuterte Algorithmus hat keine derartigen Beschränkungen, und kann so auch unter anderem einen bushy tree“ als optimales Ergebnis liefern. ” 13 14 KAPITEL 3. KOSTENBASIERTE OPTIMIERUNG VON VERBUNDFOLGEN 3.2 Optimierung mit dynamischer Programmierung Im ersten Schritt wird der Algorithmus für kartesische Produkte erläutert, um dann später für Verbund-Operationen erweitert zu werden. Dies ermöglicht einen verständlichen Einblick in die Arbeitsweise des Algorithmus. 3.2.1 Optimierung von kartesischen Produkten Um die Vorgehensweise am Beispiel von V × P × S × H zu erklären, benötigt man zuerst ein einfaches Kostenmodel1 , und die Kardinalitäten der Beispielrelationen. Um das Beispiel so einfach wie möglich zu halten nehmen wir an, dass eine Basisrelation Kosten von 0 verursacht. Weiterhin nehmen wir an, dass sich die Kosten eines kartesischen Produkts aus den einzelnen Kosten der verbundenen Relationen, sowie aus den Kosten der Operation zusammensetzen: cost(R) = 0 cost(R1 × R2 ) = cost(R1 ) + cost(R2 ) + κ(R1 , R2 ) R ist hier eine Basisrelation. R1 und R2 können Basisrelationen oder andere Ausdrücke der Relationenalgebra sein. κ ist die Kostenfunktion für das Produkt der beiden übergebenen Teilausdrücke. In unserem Beispiel ist κ gleich der Kardinalität des Ergebnisses: κ(R1 , R2 ) = |R1 × R2 | Die verwendeten Beispielrelationen haben die in Tabelle 3.1 aufgeführten Kardinalitäten. Relation Kardinalität P 10 20 S V 30 H 40 Tabelle 3.1: Die Basisrelationen Um nun die optimale Ausführungsreihenfolge zu bekommen, benutzt man eine Tabelle mit vier Spalten. Die erste Spalte enthält eine Menge von Relationen. Die zweite Spalte enthält die Kardinalität des kartesischen Produkts der Mengenelemente (bei einelementigen Mengen nur die Kardinalität der enthaltenen Basisrelation). Die dritte Spalte enthält ein Menge mit Relationen, die die geringsten Kosten verursachen, wenn man das Produkt mit ihnen beginnt (bei Basisrelationen die leere Menge). In der vierten Spalte werden die Kosten des kartesischen Produkts eingetragen. Die initialisierte Tabelle des Beispiels findet man unter Tabelle 3.2. 1 siehe hierzu [VM96] 3.2. OPTIMIERUNG MIT DYNAMISCHER PROGRAMMIERUNG Relation Kardinalität Startmenge {H} 40 ∅ {P} 10 ∅ 20 ∅ {S} {V} 30 ∅ Kosten 0 0 0 0 Tabelle 3.2: Tabelle nach der Initialisierung 3.2.2 Der Algorithmus im Pseudocode void init_table(Relation R, Metadata M) { table.add(R, M.getCardinality(R), ∅, 0); } void compute_cardinality(Menge S, Metadata M) { card = 1; for each p ∈ S do { card = card · M.getCardinality(p); } table.add(S, card, ∅, 0); } void optimize(Menge R, Metadata M) { for each r ∈ R do init_table(r, M); for (count=2; count < R.size(); inc(count) { for each S ⊆ R und |S| = count do { compute_cardinality(S, M); find_best_split(S); } } } void find_best_split(Menge S) { best cost = MAX VALUE; for each Slhs , ∅ ⊂ Slhs ⊂ S do{ Srhs = S − Slhs ; cost = table.getCost(Srhs ) + table.getCost(Slhs ) + κ(Slhs , Srhs ); if (cost < best cost) { best cost = cost; table.setLHS(S, Slhs ); } } table.setCost(S, best cost); } 15 16 KAPITEL 3. KOSTENBASIERTE OPTIMIERUNG VON VERBUNDFOLGEN Die Funktion init_table erstellt eine neue Zeile in der Optimierungstabelle. Die Relation R wird dabei zusammen mit ihrer Kardinalität, einer leere Startmenge und Kosten von Null eingetragen. Die Metadaten enthalten die Kardinalitäten der Relationen. Die Tabelle table speichert die Menge der teilnehmenden Relationen, die Kardinalität der Operation, die beste Startmenge und die Kosten der Operation. Sie stellt Funktionen bereit um diese Werte auszulesen oder neu zu setzen. Die Tabelle benutzt die gespeicherte Menge als Primärschlüssel, so dass die anderen Werte über die Menge eindeutig identifiziert werden. Die Funktion compute_cardinality(S) berechnet die Kardinalität der Relationenmenge S wie folgt: Y compute_cardinality(S) = |p| p∈S Die Funktion optimize initialisiert erst die Optimierungstabelle mit den Basisrelationen. Danach werden für jede mögliche Teilmenge S der Menge R der Basisrelationen die Funktionen compute_cardinality und find_best_split aufgerufen. Die Funktion find_best_split sucht in der Tabelle für die übergebene Menge die kostengünstigste Startmenge. Diese trägt sie zusammen mit den Kosten in die Tabelle ein. Für die Berechnungen werden die vorher ermittelten kleineren Teilmengen benutzt, da diese aufgrund der Arbeitsweise des Algorithmus schon in der Tabelle vorhanden sind. MAX VALUE ist die größte Zahl, die in der Variablen best cost gespeichert werden kann. Aufbau der Tabelle Im ersten Durchgang werden die Basisrelationen eingetragen. In jedem weiteren Schritt werden alle möglichen Mengen aus den in der Tabelle gespeicherten Mengen durch Vereinigung gebildet. Diese werden dann jeweils in eine neue Zeile gespeichert und ihre Kardinalität, die beste Startmenge und die Kosten werden berechnet. Das Verfahren endet sobald eine Menge in die Tabelle eingetragen wurde, die der Menge der am Produkt beteiligten Relationen entspricht. Die fertige Tabelle für das Beispiel findet sich unter Tabelle 3.3. Auswertung der Tabelle Die optimale Produktreihenfolge läßt sich bestimmen, indem aus der letzten Tabellenzeile die Obermenge R aus der Spalte Relation und die Startmenge S aus der Spalte Startmenge ausgelesen werden. Nun bildet man das Produkt S × (R − S). 3.2. OPTIMIERUNG MIT DYNAMISCHER PROGRAMMIERUNG Relation {H} {P} {S} {V} {H,P} {H,S} {V,H} {P,S} {P,V} {S,V} {H,P,S} {H,P,V} {H,S,V} {P,S,V} {H,P,S,V} Kardinalität Startmenge 40 ∅ 10 ∅ 20 ∅ 30 ∅ 400 {P } 800 {S} 1200 {V } 200 {S} 300 {V } 600 {V } 8000 {P, S} 12000 {P, V } 24000 {S, V } 6000 {P, S} 240000 {H, P } 17 Kosten 0 0 0 0 400 800 1200 200 300 600 8200 12300 24600 6200 241000 Tabelle 3.3: Tabelle für die Beispielanfrage V × P × S × H Ist die Startmenge S eine zweielementige Menge {R1 , R2 }, so bildet man aus den beiden enthaltenen Relationen das Produkt R1 × R2 und ist mit dem linken Teil der Anfrage fertig. Sollten es mehr als 2 Elemente sein, liest man die Zeile aus der Tabelle, die der Menge entspricht. Man extrahiert wieder Obermenge und Startmenge und fährt dann fort wie oben beschrieben. So baut man die linke Seite des Anfragebaums auf. Für die rechte Seite verfährt man analog, nur startet man hier mit Obermenge minus Startmenge. Im Beispiel würde man also aus der letzten Zeile die Obermenge {H,P,S,V} und die Startmenge {H,P} bekommen. Die Startmenge hat nur zwei Elemente, daher ist die linken Seite des Produkts mit dem Produkt H × P fertig. Die Restmenge ist {H,P,S,V}{H,P}={S,V}. Diese hat auch nur zwei Elemente, daher endet die Abarbeitung hier. Das Endergebnis ist also (H × P ) × (S × V ). 3.2.3 Erweiterung auf Verbunde Die Optimierung von Verbund-Operationen ist bis auf die Bildung der Zwischenergebnisse identisch mit der Optimierung von Produkten. Bei der Bildung der Zwischenergebnisse muss nun die Selektivität der beiden Verbundpartner beachtet werden. Um dieses zu berücksichtigen wird die Tabelle um eine Spalte Selektivität erweitert. In dieser Spalte wird die Selektivität der Verbundoperation gespeichert. 1 1 , , mit R = R1 o nϕ R2 und ϕ ≡ R1 .A = R2 .B sel(ϕ) = min #(A, R1 ) #(B, R2 ) Um die Kardinalität von R = R1 o np R2 zu berechnen, multipliziert man die Kardinalitäten von R1 und R2 mit der Selektivität von p. Da card(R1 ) und card(R2 ) aufgrund 18 KAPITEL 3. KOSTENBASIERTE OPTIMIERUNG VON VERBUNDFOLGEN der Konstruktionsweise der Tabelle schon enthalten sind, muß nur noch die Selektivität neu berechnet werden. Die Selektivität ist das Produkt aller am Verbund beteiligten Selektivitäten. Betrachtet man den Verbund als Graphen mit den Verbundbedingungen als Kanten und den Relationen als Knoten, so gilt: R1 o nϕ R2 mit ϕ = ^ p, P := {p | p spannt R1 und R2 auf} p∈P Damit folgt dann die Kardinalität: card(R) = card(R1 ) · card(R2 ) · Y sel(p), P := {p | p spannt R1 und R2 auf} p∈P Da die Selektivität der Verbundpartner schon in der Tabelle gespeichert ist, muss man nur noch die Gesamtselektivität des neuen Verbundes berechnen. Diese wird dann mit den anderen Daten gemeinsam in der Tabelle gespeichert. 3.2.4 Neue Kostenfunktion In diesem Abschnitt wird eine neue Kostenfunktion eingeführt, da die aus der Literatur entnommene Kostenfunktion (siehe [VM96]) zwar teilweise recht gute Ergebnisse liefert, aber in einigen Fällen auch erheblich schlechtere Lösungen zulässt. Die neue Funktion berücksichtigt nun Lesezugriffe über ganze Seiten, und ist damit identisch mit den in [War03] eingeführten I/O-Kosten. Die Funktion cost() ist unverändert, da sie die Kosten des Endergebnisses repräsentiert. cost(R) ist daher immer noch Null, da die Basisrelation schon vorhanden ist, und nicht erst berechnet werden muss. Die Funktion κ() wurde wie folgt verändert: κ(R1 , R2 ) = page(R1 ) + |R1 | · page(R2 ) Die Funktion page(R) liefert die von der Relation R belegten Seiten. Hier bietet sich an, die Tabelle um eine neue Spalte Seiten zu erweitern. Bei der Initialisierung werden hier die in den Metadaten gespeicherten Werte eingetragen. Alle weiteren Werte lassen sich wie folgt berechnen (siehe auch [War03], Kapitel 4.2): page(R1 op R2 ) = (|R2 | · page(R1 ) + |R1 | · page(R2 )) · sel(R1 op R2 ) , mit op ∈ {×, o n} Die neue Tabelle für das Beispiel findet man unter Tabelle 3.4. 3.2. OPTIMIERUNG MIT DYNAMISCHER PROGRAMMIERUNG Relation {H} {P} {S} {V} {H,P} {H,S} {H,V} {P,S} {P,V} {S,V} {H,P,S} {H,P,V} {H,S,V} {P,S,V} {H,P,S,V} Kardinalität Seiten Startmenge 40 4 ∅ 10 1 ∅ 20 2 ∅ 30 3 ∅ 400 80 {P } 800 160 {S} 1200 240 {V } 200 40 {P } 300 60 {P } 600 120 {S} 8000 2400 {P, S} 12000 3600 {P, V } 24000 7200 {S, V } 6000 1800 {P, S} 240000 96000 {P, S, V } 19 Kosten 0 0 0 0 41 82 123 21 31 62 861 1291 2582 661 26461 Tabelle 3.4: Neue Tabelle für die Beispielanfrage V × P × S × H 3.2.5 Beispiel mit Verbunden In diesem Abschnitt findet sich die Tabelle für folgende kurze Anfrage: V o n (H o n S) Dafür benötigen wir Attribute sowie die Anzahl unterschiedlicher Tupel pro Attribut. Diese finden sich in Tabelle 3.5 Relation Kardinalität Attribute S 20 {A, B} V 30 {C,D} H 40 {A,C} n(A,R) A=20, B=6 C=30, D=10 A=20, C=30 Tabelle 3.5: Erweiterte Basisrelationen Die fertige Optimierungstabelle findet sich unter Tabelle 3.6. 3.2.6 Behandlung von Selektionen Um noch bessere Ergebnisse erzielen zu können, wurde der Optimierer in einem letzten Schritt so erweitert, dass er neben Basisrelationen auch Selektionen mit in seine Berechnungen einbezieht. Selektionen werden wie normale Basisrelationen behandelt. In die Optimierungstabelle wird die Kardinalität des Ergebnisses und die Anzahl der belegten 20 KAPITEL 3. KOSTENBASIERTE OPTIMIERUNG VON VERBUNDFOLGEN Relation Kardinalität Seiten Startmenge {H} 40 4 ∅ {S} 20 2 ∅ 30 3 ∅ {V} {H,S} 40 8 {S} {H,V} 40 8 {V } 600 120 {S} {S,V} {H,S,V} 40 12 {S, V } Kosten Selektivität 0 1 0 1 0 1 82 0,05 123 0,033 62 1 210 0,002 Tabelle 3.6: Tabelle für die Beispielanfrage V o n (H o n S) Seiten eingetragen. Um Selektionen in der Tabelle von Basisrelationen unterscheiden zu können, bekommen sie als Präfix das Zeichen σ gefolgt von dem Namen der Relation, auf die sich die Selektion bezieht. Während der Tabelleninitialisierung muss darauf geachtet werden, dass alle vorkommenden Selektionen unter dem Namen in einer neuen Datenstruktur gespeichert werden, mit dem sie in die Tabelle eingetragen werden. Dies ist nötig, da in der Tabelle die Bedingungen nicht mit gespeichert werden. Nach der Optimierung kann man dann die Selektionen mit ihren Bedingungen aus dieser Datenstruktur auslesen und in den neuen Anfragebaum einfügen. Beispiel mit Selektion Das Beispiel aus Kapitel 1 erzeugt die Tabelle 3.7. Hier sieht man, dass die Selektion auf S in der Tabelle als σS aufgeführt wird und so in die Berechnung eingeht. Relation {H} {P} {V} {σS} {H,P} {H,V} {H,σS} {P,V} {P,σS} {V,σS} {H,P,V} {H,P,σS} {H,V,σS} {P,V,σS} {H,P,V,σS} Kardinalität Seiten Startmenge 40 4 ∅ 10 1 ∅ 30 3 ∅ 3 1 ∅ 400 80 {P } 40 8 {V } 6 3 {σS} 30 6 {P } 30 13 {σS} 90 39 {σS} 40 12 {P, V } 60 36 {H, σS} 6 4 {H, σS} 90 48 {σS} 6 5 {H, V, σS} Kosten Selektivität 0 1 0 1 0 1 0 1 41 1 123 0,033 13 0,05 31 0,1 4 1 10 1 157 0,003 22 0,05 34 0,002 50 0,1 44 0,0002 Tabelle 3.7: Optimierungstabelle für die Beispielanfrage aus Kapitel 1 Kapitel 4 Anbindung an die Oracle-Datenbank In diesem Kapitel wird die Anbindung von RELOpt an die Datenbank Oracle 9i/10g beschrieben. Über diese Schnittstelle soll dem Benutzer die Möglichkeit gegeben werden, Relationen und ihre Attribute, sowie die entsprechenden Statistiken aus der Datenbank zu übernehmen. Dies erleichtert die Benutzung, da man nicht erst alle Relationen per Hand eingeben muss. RELOpt wurde daher so erweitert, dass es diese Metadaten aus den über JDBC zur Verfügung gestellten Metadaten, sowie direkt aus den in der Datenbank gespeicherten Metadatenrelationen auslesen kann. 4.1 Importieren von Tabellen Abbildung 4.1: Die Knöpfe im Hauptfenster von RELOpt Die Importfunktion für Tabellen und ihre Attribute ist im Hauptfenster von RELOpt unter dem Knopf Metadaten zu finden (siehe Abb. 4.1). Dort wurde ein neuer Knopf Tabellen aus Datenbank übernehmen hinzugefügt (Abb. 4.2). 21 22 KAPITEL 4. ANBINDUNG AN DIE ORACLE-DATENBANK Abbildung 4.2: Dialog für die Bearbeitung von Tabellen Wird der Knopf Tabellen aus Datenbank übernehmen gedrückt, werden die Tabellen aus dem Benutzerschema des an der Datenbank angemeldeten Benutzer ausgelesen und in der Auswahltabelle (Abb. 4.4) dargestellt. Sollte noch keine Verbindung zur Datenbank bestanden haben, wird vorher ein Verbindungsdialog angezeigt (Abb. 4.3) und versucht mit den eingegebenen Daten eine Verbindung aufzubauen. Abbildung 4.3: Dialog für den Datenbanklogin Der Nutzer kann nun in der Auswahltabelle die gewünschten Tabellen markieren und per Knopfdruck auf Tabellen hinzufügen importieren. Soll eine Tabelle aus einem anderen Schema übernommen werden, so kann man dieses in das Eingabefeld Schema eingeben. Nach einem Klick auf Schema laden erscheinen dann die Tabellen des ausgewählten Schemas in der Auswahltabelle. Die Eingabe darf die Oracle Wildcards _ und % enthalten. Sollten mehrere Schemas auf diese Eingabe passen, so werden alle Tabelle aus allen passenden Schemas geladen. 4.2. IMPORTIEREN VON STATISTIKEN 23 Abbildung 4.4: Dialog für den Import von Tabellen 4.2 Importieren von Statistiken Die statistischen Daten der importierten Relationen werden automatisch mit eingelesen. Die Kardinalitäten werden aus den von der JDBC-Schnittstelle gelieferten Metadaten gewonnen, ebenso mögliche Indexe. Aufgrund des Rechtemanagements kann beim Import von Fremdtabellen aus anderen Schemata nicht immer auf die durch die JDBCSchnittstelle gelieferten Metadaten zurückgegriffen werden. Daher werden in so einem Fall die Metadaten nicht automatisch übernommen, sondern müssen vom Benutzer eingetragen werden. Hierbei erfolgt eine Meldung wenn beim Import Nullwerte eingelesen wurden. Die Klasse DBManager stellt sowohl die Metadaten der JDBC-Schnittstelle zur Verfügung als auch Daten die durch direkte Anfragen an die Datenbank gewonnen wurden. Die angesprochenen Relationen sind nachfolgend aufgezählt. • ALL_TABLES Aus dieser Relation wird die Seiten- und Tupelkardinalität ausgelesen. • ALL_TAB_COLUMNS Aus dieser Relation wird die Anzahl der eindeutigen Tupel #(A, R) ausgelesen. • ALL_INDEXES Aus dieser Relation werden die Indexe gewonnen, sowie die zugehörigen Kardinalitäten. • ALL_IND_COLUMNS Aus dieser Relation wird die Zuordnung der Indexe zu den einzelnen Spalten ausgelesen. 24 KAPITEL 4. ANBINDUNG AN DIE ORACLE-DATENBANK • PLAN_TABLE In dieser Tabelle speichert das Oracle-System die Anfragepläne, die durch die Anweisung EXPLAIN PLAN FOR <SQL ANFRAGE> angefordert werden. 4.3 Import von Anfrageplänen Um eine Anfrage durch das Oracle-System bewerten zu lassen wird die vom Benutzer erstellte Anfrage durch einen Übersetzer in ein SQL-Statement umgewandelt. Die vom Übersetzer gelieferte SQL-Anfrage wird über die JDBC-Schnittstelle an die Datenbank übergeben. Der dort erstellte Anfrageplan wird dann zurückgegeben und in einem Anzeigefenster dargestellt. Eine Erweiterungsmöglichkeit wäre hier die Visualisierung des von der Datenbank gelieferten Plans (Siehe Kap. 7). 4.3.1 Der Übersetzer Der Übersetzer hat die Aufgabe, aus dem von RELOpt gelieferten Anfrageplan eine für die Oracle-Datenbank verständliche SQL-Anfrage zu generieren. Hierfür durchläuft er die Anfrage und wendet auf die einzelnen Teile verschiendene Regeln an. 4.3.2 Die Regeln Insgesamt gibt es 10 Regel, die die Bearbeitung der Anfrage übernehmen. Die hier benutzten Regeln für abgeleiteten Operationen stammen aus [Lip03]: • JoinSQLRule Diese Regel formt einen Join R o nϕ S in folgenden SQL Ausdruck um: SELECT * FROM R ALIAS JOIN S ALIAS ON (ϕ̄) Hierbei wurde ϕ in ϕ̄ umgewandelt, indem die entsprechenden Relationen durch die zugehörigen Aliase ersetzt wurden. • SemijoinSQLRule Da für Semijoins folgendes gilt: R nϕ S = R o nϕ πAttribute(R) (S) folgt für die Anfrage in SQL: SELECT R.* FROM R JOIN S ON (ϕ) 4.3. IMPORT VON ANFRAGEPLÄNEN 25 Bei dieser Anfrage kann das Oracle-System aber nicht erkennen, dass es sich um einen Semijoin handelt. Daher wird der Semijoin in folgende Anfrage übersetzt, welche korrekt erkannt wird: SELECT * FROM R ALIAS WHERE EXISTS (SELECT * FROM S ALIAS WHERE (ϕ̄)) Hierbei wurde ϕ in ϕ̄ umgewandelt, indem die entsprechenden Relationen durch die zugehörigen Aliase ersetzt wurden. • AntisemijoinSQLRule Diese Regel benutzt folgenden Sachverhalt, um einen Antisemijoin in SQL darzustellen: R nϕ S = R − R o nϕ πAttribute(R) (S) Dies kann in SQL wie folgt realisiert werden: (SELECT * FROM R) MINUS (SELECT R.* FROM R JOIN S ON (ϕ)) Bei dieser Anfrage kann das Oracle-System aber nicht erkennen, dass es sich um einen Antisemijoin handelt. Daher wird der Antisemijoin in folgende Anfrage übersetzt, welche korrekt erkannt wird: SELECT * FROM R ALIAS WHERE NOT EXISTS (SELECT * FROM S ALIAS WHERE (ϕ̄)) Hierbei wurde ϕ in ϕ̄ umgewandelt, indem die entsprechenden Relationen durch die zugehörigen Aliase ersetzt wurden. • DifferenceSQLRule Diese Regel formt die Differenz R − S in folgendes SQL Statement um: (SELECT * FROM R) MINUS (SELECT * FROM S) • IntersectionSQLRule Diese Regel formt den Durchschnitt R ∩ S in folgendes SQL Statement um: (SELECT * FROM R) INTERSECT (SELECT * FROM S) • UnionSQLRule Diese Regel formt die Vereinigung R ∪ S in folgendes SQL Statement um: (SELECT * FROM R) UNION (SELECT * FROM S) 26 KAPITEL 4. ANBINDUNG AN DIE ORACLE-DATENBANK • ProductSQLRule Diese Regel formt das Produkt R × S in folgendes SQL Statement um: SELECT * FROM R CROSS JOIN S • ProjectionSQLRule Diese Regel formt die Projektion πĀ (R) in folgendes SQL Statement um: SELECT Ā FROM R • SelectionSQLRule Diese Regel formt die Selektion σϕ (R) in folgendes SQL Statement um: SELECT * FROM R WHERE (ϕ) • TableSQLRule Diese Regel fügt dem SQLStatement den Namen der Tabelle als neue Relation hinzu. 4.4 Anfrageplanerstellung in der Oracle Datenbank Zuerst wird in der Oracle Datenbank geprüft, ob eine Relation PLAN TABLE existiert. In dieser Relation speichert der Oracle-Optimierer den von ihm erstellten Anfrageplan. Ist diese Relation vorhanden, so wird sie geleert. Sollte dies nicht der Fall sein, wird diese angelegt. PLAN_TABLE_OUTPUT -----------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost | -----------------------------------------------------------------------| 0 | SELECT STATEMENT | | 51 | 1734 | 1 | | 1 | NESTED LOOPS | | 51 | 1734 | 1 | | 2 | INDEX FULL SCAN | PK_ADMIN_PR_VP | 56 | 1008 | 1 | |* 3 | INDEX UNIQUE SCAN | PK_PRES | 1 | 16 | | -----------------------------------------------------------------------Predicate Information (identified by operation id): --------------------------------------------------3 - access("ADMIN_PR_VP"."VICE_PRES_NAME"="PRESIDENT"."PRES_NAME") Note: cpu costing is off Abbildung 4.5: Oracle Anfrageplan PLAN TABLE wird standardmäßig vom SQL Befehl EXPLAIN PLAN FOR benutzt, um einen Anfrageplan abzuspeichern. Nachdem der Benutzer die Anfrage abgeschickt hat, 4.5. IMPLEMENTIERUNG 27 wird das Ergebnis mit folgendem SQL Befehl ausgelesen und auf der rechten Seite des Dialogs dargestellt. SELECT * FROM TABLE ( DBMS_XPLAN.display() ); DBMS_XPLAN wird von der Oracle Datenbank zur Verfügung gestellt, um Anfragepläne übersichtlich als Textausgabe darzustellen. Das Paket hat nur eine einzige Prozedur namens display(). Das Beispiel aus Kapitel 1 ist in Abbildung 4.5 zu sehen. Man sieht, dass der Oracle-Optimierer die Tupel mit Index Zugriffen auswählt, und dann mit einem Nested-Loop-Verbund zusammenführt. 4.5 Implementierung In diesem Abschnitt wird die Implementierung der Importschnittstelle und die Anwendung der neuen Klassen beschrieben. Die Klassen verwenden für die Datenbankzugriffe JDBC, welches über das Paket java.sql benutzt wird. Die für die Implementierung zu Rate gezogenen Oracle-Dokumentationen finden sich unter [ORA]. 4.5.1 Klassen Um die oben skizzierten Funktionen in RELOpt bereitzustellen, wurde ein neues Paket sopt.db.oracle angelegt. Dieses enthält die nachfolgenden Klassen. • DBManager Diese Klasse verwaltet die Verbindung zur Datenbank. Sie stellt eine Methode bereit, die die Verbindung zur Datenbank liefert. Sollte die Verbindung noch nicht bestehen, wird ein JLoginDialog geöffnet. Mit den vom Benutzer gelieferten Logindaten wird dann versucht, eine Verbindung zur Datenbank herzustellen. Desweiteren stellt sie Methoden zum Schließen der Verbindung und zur Abfrage der Metadaten bereit. Auch die Anfragepläne werden von dieser Klasse aus der Datenbank gelesen. Für Metadaten, die nicht aus den von JDBC gelieferten Daten gewonnen werden können, werden PreparedStatement bereitgestellt. Diese Anfragen werden zur Laufzeit generiert, sobald sie das erste Mal benutzt werden. – openConnection Stellt die Verbindung zur Datenbank her. – getConnection Liefert ein Objekt vom Typ Connection. 28 KAPITEL 4. ANBINDUNG AN DIE ORACLE-DATENBANK – closeConnection Schliesst die Verbindung, wenn sie noch offen ist. – getMetaData Liefert die Datenbankmetadaten. – sendStatement Sendet die übergebene Anfrage an die Datenbank. – sendQuery(String statement Sendet die übergebene Anfrage an die Datenbank und liefert das Ergebnis zurück. – preparePlanTable Schaut nach, ob die Relation PLAN_TABLE existiert, wenn nicht wird diese angelegt. – getPlan Fragt die Relation PLAN_TABLE ab und liefert das Ergebnis. – getTableInfo Liefert Tupel- und Seiten-Kardinalitäten der übergebenen Relation. – getNumDistinct Liefert die Spaltennamen und die Anzahl der einzigartigen Tupel in der jeweiligen Spalte. – getIndexes Liefert alle Spalten, die mit einem Index versehen sind. – isClosed Liefert wahr, wenn die Verbindung getrennt ist. • SQLStatement Diese Klasse repräsentiert eine SQL Anfrage. Sie stellt Methoden zum Hinzufügen vom Selektionsbedingungen, Relationen und Projektionsbedingungen zur Verfügung. Ihre toString() Methode liefert eine Anfrage der Form EXPLAIN PLAN FOR SELECT..., die direkt an die Datenbank geschickt werden kann. – addAttribute Fügt ein Attribut hinzu. – addRelation Fügt eine Relation hinzu. – addCondition Fügt eine Bedingung hinzu. – toString Liefert eine Stringdarstellung der SQL-Anfrage. 4.5. IMPLEMENTIERUNG 29 • StatementBuilder Diese Klasse erzeugt aus einem algebraischen Baum eine äquivalente SQL Anfrage. Diese wird benötigt um die Anfrage des Benutzers durch das Oracle System bewerten zu lassen. Der StatementBuilder erwartet als Eingabe einen AlgebraicTree. Diesen durchläuft er dann von oben nach unten (TopDown) und liefert am Ende ein Objekt vom Typ SQLStatement (s.o.), dass die Anfrage in SQL repräsentiert. – createStatement Erstellt ein SQL Statement aus dem übergebenen AlgebraicTree oder der übergebenen Relation. – conditionToSQL Liefert die übergebene Bedingung vom Typ Condition als String. – createCondition Fügt dem übergebenen SQLStatement eine Stringdarstellung der übergebenen Condition hinzu. Das Paket dbs.sopt.gui wurde um folgende Klassen erweitert, welche die grafische Benutzerschnittstelle der Anbindung zur Verfügung stellen. • DBImport DBImport fordert über den DBManager die Metadaten der Datenbank an und stellt dem Benutzer die gefundenen Relationen mit ihren Attributen zum Importieren in RELOpt zur Verfügung. Für alle importierten Relationen werden, wenn vorhanden, die Kardinalitäten und weitere Metadaten ausgelesen und in die von RELOpt gespeicherten Daten integriert. • SendSQLToDB Diese Klasse ist eine Erweiterung von JDialog. Der Dialog enthält in der oberen Hälfte die vom StatementBuilder erstellte Anfrage. Darunter befinden sich links die Darstellung des Anfrageplans, wie RELOpt ihn erstellt hat, und auf der rechten Seite wird der Anfrageplan der Oracle Datenbank dargestellt (siehe Abb. 4.9). Der Oracle Anfrageplan steht zur Verfügung, sobald der Benutzer auf Abschicken geklickt hat. Der Dialog schickt dann die Anfrage zur Datenbank und liest den Anfrageplan aus der Tabelle PLAN_TABLE. 4.5.2 Die Regeln Die Oberklasse aller Übersetzerregeln ist die abstrakte Klasse SQLRule (siehe Abbildung 4.6). Sie definiert 2 Methoden die von den Subklassen überschrieben werden müssen. Die Auslagerung der Übersetzerregeln in eigene Klassen wurde in Hinblick auf spätere Erweiterungen des Sprachumfangs gewählt. So können neue Sprachkonstrukte durch einfaches Erstellen einer passenden Regel und eines Eintrags in der Regel-Hash-Map integriert werden. 30 KAPITEL 4. ANBINDUNG AN DIE ORACLE-DATENBANK • handlesClass Diese Methode liefert ein Objekt vom Typ Class zurück. Es repräsentiert die Art von Klasse, die diese Regel behandeln kann. • create Diese Methode erwartet als Parameter eine Relation und ein SQLStatement. Sie liefert das SQLStatement zurück, erweitert um die SQL-Darstellung der Relation. SQLRule handleClass create Product SQLRule Join SQLRule Intersection SQLRule Semijoin SQLRule Union SQLRule Antisemijoin SQLRule Difference SQLRule Projection SQLRule Table SQLRule Selection SQLRule Abbildung 4.6: Ausschnitt aus dem Paket sopt.sqlp.rules 4.5.3 Der Übersetzer Der Übersetzer besteht aus der Hauptklasse StatementBuilder und den in Abschnitt 4.3.2 definierten Regeln. Der Übersetzer erwartet als Eingabe einen Anfragebaum. Dieser wird dann rekursiv durch die Regeln durchlaufen. Als Ergebnis liefert der Übersetzer die SQL-Anfrage als Text. Der Aufruf des Übersetzer geschieht durch die statische Methode createStatement. Diese erwartet als Eingabe einen AlgebraicTree und liefert einen String zurück, der die Anfrage in SQL darstellt. Funktionsweise Der Übersetzer benutzt für die Umwandlung der im AlgebraicTree gespeicherten Objekte vom Typ Relation (In RELOpt haben alls Operationen Relation als Superklasse) eine Reihe von Regeln, die dynamisch zur Laufzeit ausgewählt werden. 4.5. IMPLEMENTIERUNG 31 Um ein Objekt zu übersetzen, wird zuerst in einer HashMap nachgeschaut, welche Regel für diese Art von Objekten zuständig ist. Dabei wird die Klasse des Objekts als Schlüssel benutzt. Danach wird über die in Java eingebauten Reflektionsmethoden die statische Methode create der Regel aufgerufen. Die Regel extrahiert die Operation, die Teilbäume, auf die die Operation angewendet wird, und gegebenenfalls eine Bedingung. Mit diesen Informationen wird dann das der Regel übergebene SQLStatement erweitert. Danach wird auf jeden Teilbaum erneut der StatementBuilder aufgerufen. Handelt es sich bei der Operation um Join, Semijoin oder Antisemijoin, so werden Aliase für die Teilbäume eingeführt. Der Alias setzt sich aus dem Namen der Wurzel des Teilbaumes sowie des Hashwert der Wurzel zusammen. In der Bedingung werden dann alle Relationennamen durch den entsprechenden Alias ersetzt. Der Übersetzer am Beispiel Der Übersetzer liefert für den in Abbildung 4.7 gezeigten Anfragebaum das in Abbildung 4.8 gezeigte SQL-Statement. πP.N ame, S.Semester ⋊ ⋉P.ID=V.gelesenV on P ⋊ ⋉V.V orlN r=H.V orlN r V ⋊ ⋉H.MatrN r=S.MatrN r H S Abbildung 4.7: Beispielanfragebaum für den SQL-Übersetzer SELECT Name, Semester FROM P P10592665 JOIN (SELECT * FROM V V1685884 JOIN (SELECT * FROM H H6839856 JOIN S S16766291 ON (H6839856.MatrNr=S16766291.MatrNr) ) JOIN14722034 ON (V1685884.VorlNr=JOIN14722034.VorlNr) ) JOIN7893316 ON (P10592665.ID=JOIN7893316.gelesenVon) Abbildung 4.8: Beispielanfrage in SQL 32 4.5.4 KAPITEL 4. ANBINDUNG AN DIE ORACLE-DATENBANK Die Benutzerschnittstelle Die Klasse des Vergleichsfensters ist SendSQLToDB. Ein Bild des Fensters ist unter Abbildung 4.9 zu finden. Im oberen Teil des Fensters kann der Benutzer seine Anfrage sehen, die an die Datenbank geschickt wird. Auf der unteren linken Seite findet der User den von RELOpt erstellten Anfrageplan, auf der unteren rechten Seite die Version des verwendeten Oracle-Systems. Die Erstellung der SQL-Statements wird durch die in Kapitel 4.5.1 beschriebene Klasse StatementBuilder realisiert. Die Ausgabe des StatementBuilders wird in der oberen Hälfte des SendSQLToDB Dialogs dargestellt. Abbildung 4.9: Dialog für den Anfrageplan Vergleich Kapitel 5 Experimente und Anwendungen In diesem Kapitel finden sich Vergleiche zwischen dem in [War03] implementierten Minimum-Selektivity-Algorithmus und dem in dieser Arbeit behandelten Join-OrderAlgorithmus. Weiterhin werden hier beispielhaft Unterschiede und Gemeinsamkeiten zwischen RELOpts Optimierung und der Optimierung einer Orcale-Datenbank aufgeführt. 5.1 Vergleich Join-Order mit Minimum-Selektivity Da der Join-Order-Algorithmus (im folgenden kurz JOA) Lösungen im kompletten Suchraum findet, ist es interessant, diese mit den vom Minimum-Selektivity-Algorithmus (im folgenden kurz MSA) gefundenen Lösungen zu vergleichen. Besonders interessant sind hier Lösungen des JOA, die nicht im Suchraum des MSA liegen. Zum Beispiel Anfragepläne in Form von bushy-trees“ oder right-deep-trees“. ” ” 5.1.1 Beispiele in Form von left-deep-trees“ ” Für eine Vielzahl von Anfragen liefern beide Algorithmen identische Lösungen. Als Beispiel dieser Gruppe von Anfragen dient folgende aus Kapitel 1 bekannte Anfrage: (PROJECTION P.Name (SELECTION S.Semester=’5’ (JOIN P.ID=V.gelesenVon P (JOIN V.VorlNr=H.VorlNr V (JOIN H.MatrNr=S.MatrNr H S))))) 33 34 KAPITEL 5. EXPERIMENTE UND ANWENDUNGEN Sowohl der JOA als auch der MSA liefern den in Abbildung 5.1 gezeigten Anfragebaum. πP.Name σS.Semester =’5’ ⋊ ⋉H.MatrNr =S.MatrNr S ⋊ ⋉V.VorlNr =H.VorlNr ⋊ ⋉P.ID =V.gelesenVon P H V Abbildung 5.1: Anfragebaum der Beispielanfrage (JOA/MSA) Führt man vor der Optimierung die entsprechenden Regeln aus, um die Selektion nach unten in den Anfragebaum zu schieben, ergibt sich die Lösung in Abbildung 5.2, wieder identisch für beide Optimierer. πP.Name ⋊ ⋉P.ID =V.gelesenVon ⋊ ⋉V.VorlNr =H.VorlNr ⋊ ⋉H.MatrNr =S.MatrNr σS.Semester =’5’ P V H S Abbildung 5.2: Anfragebaum der Beispielanfrage mit verschobener Selektion 5.1.2 Fazit Bei allen getesteten Anfragen1 lieferten beide Optimierer identische Ergebnisse. Für keine der durch den JOA optimierten Anfragen wurde ein bushy-tree“ oder right-deep” ” tree“ geliefert. Dies lässt darauf schliessen, dass die beim Minimum-Selektivity getroffene Einschränkung auf das Gebiet der left-deep-trees“ gerechtfertigt ist. ” 1 hier größtenteils nicht dargestellt 5.2. OPERATIONEN DER ORACLE-DATENBANK 5.2 35 Operationen der Oracle-Datenbank Um die von der Oracle-Datenbank gelieferten Anfragepläne mit denen von RELOpt vergleichen zu können, müssen zuerst für die von der Oracle-Datenbank benutzten Operationen äquvalente Operationen in RELOpt aufgeführt werden. 5.2.1 Struktur der Oracle-Anfragen Das Wurzelelement des Anfragebaums, der aus der Oracle-Datenbank über die Relation PLAN_TABLE ausgelesen werden kann, ist immer vom Typ SELECT STATEMENT. Alle weiteren Elemente des Anfragebaums sind beliebige Operationen. Diese können mehrere Kindelemente und Optionen haben. Das Beispiel aus Kapitel 1 hat den in Abbildung 5.3 dargestellten Anfragebaum. Die Abkürzung T. steht für TABLE. SELECT STATEMENT NESTED LOOPS NESTED LOOPS NESTED LOOPS T. ACCESS BY INDEX ROWID INDEX UNIQUE SCAN INDEX FULL SCAN INDEX RANGE SCAN P ID PK H VORLNR MATRNR PK V VORLNR PK T. ACCESS FULL S T. ACCESS BY INDEX ROWID Abbildung 5.3: Anfragebaum des Beispiels aus Kapitel 1 5.2.2 Umsetzung der Oracle-Operationen in RELOpt In der Tabelle 5.1 finden sich die von Oracle benutzten Operationen und ihre äquivalenten Umsetzungen in RELOpt, wenn vorhanden. Die drei Operationen NESTED LOOPS, MERGE JOIN und HASH JOIN können die Option OUTER haben. Da RELOpt keine Outer-Joins unterstützt, können Operationen mit dieser Option nicht in RELOpt dargestellt werden. Weiterhin können die Joins als CARTESIAN (z.B. MERGE JOIN CARTESIAN) auftreten. Diese lassen sich in RELOpt durch den entsprechenden Verbund mit der Bedingung TRUE darstellen. Die Bedingung TRUE liefert immer wahr. 36 KAPITEL 5. EXPERIMENTE UND ANWENDUNGEN In der Tabelle steht * für einen Wildcard, nicht unterstützt bedeutet, das diese Funktion in RELOpt nicht darstellbar ist. INDEX bedeutet, dass die Tupel über einen Indexzugriff geholt werden, TABLE ACCESS steht für den direkten Tupelzugriff. Die Spalte Operation enthält die vom Oracle-Sytem benutzten Operationen. In den beiden Spalten 1. Kindelement und 2. Kindelement werden die im Anfragebaum möglichen Kindelemente aufgeführt. Neben den in der Tabelle aufgeführten Operationen TABLE ACCESS und INDEX sind noch verschiedene Sortierungen SORT möglich, diese als Kindelemente mit aufzuführen würde aber den Rahmen der Tabelle sprengen. In der Spalte Darstellung in RELOpt werden die Java-Klassen aufgeführt, mit denen man die Oracle-Operation möglichst äquivalent in RELOpt darstellen kann. Operation 1. Kindelement 2. Kindelement Darstellung in RELOpt NESTED LOOPS TABLE ACCESS TABLE ACCESS NestedLoopJoin TABLE ACCESS INDEX RelIndexJoin INDEX TABLE ACCESS RelIndexJoin INDEX INDEX IndexIndexJoin MERGE JOIN TABLE ACCESS TABLE ACCESS MergeJoin TABLE ACCESS INDEX nicht unterstützt INDEX TABLE ACCESS nicht unterstützt INDEX INDEX nicht unterstützt HASH JOIN TABLE ACCESS TABLE ACCESS HashJoin TABLE ACCESS INDEX nicht unterstützt INDEX TABLE ACCESS nicht unterstützt INDEX INDEX nicht unterstützt UNION TABLE ACCESS TABLE ACCESS NestedLoopUnion TABLE ACCESS INDEX RelIndexUnion INDEX TABLE ACCESS RelIndexUnion INDEX INDEX IndexIndexUnion MINUS TABLE ACCESS TABLE ACCESS NestedLoopAntisemijoin TABLE ACCESS INDEX RelIndexAntisemijoin INDEX TABLE ACCESS IndexRelAntisemijoin INDEX INDEX IndexIndexAntisemijoin INTERSECTION TABLE ACCESS TABLE ACCESS NestedLoopSemijoin TABLE ACCESS INDEX RelIndexSemijoin INDEX TABLE ACCESS IndexRelSemijoin INDEX INDEX IndexIndexSemijoin SORT * AttrSort Tabelle 5.1: Oracle-Operationen und ihre Umsetzung in RELOpt 5.3. VERGLEICHE MIT DER ORACLE-DATENBANK 5.3 5.3.1 37 Vergleiche mit der Oracle-Datenbank Beispielanfrage ohne Selektion Das Ergebnis der Optimierung der aus Kapitel 1 und 4.5.3 bekannten Beispielanfrage (siehe Abbildung 1.1) nach der Optimierung durch RELOpt ist in Abbildung 5.4 zu finden. Bei der Anfrage wurde die Selektion weggelassen. In Abbildung 5.5 findet sich der Anfragebaum nach der Optimierung durch das Oracle-System. Im Oracle-System wurden vorher die Statistiken der benutzten Beispielrelationen mit den entsprechenden Systemfunktionen gesammelt. Index/elim S.Semester (3) πP.Name Tree(P.Name)(33) ⋊ ⋉Hash H.MatrN r=S.MatrN r (9) Hash(·) Hash(·) ⋊ ⋉Hash V.V orlN r=H.V orlN r (6) S Hash(·) Hash(·) ⋊ ⋉Hash P.ID=V.gelesenV on (3) H Hash(·) Hash(·) V P Abbildung 5.4: Beispielanfrage durch RELOpt optimiert In den beiden Anfragebäumen kann man feststellen, dass die grundlegende Struktur und die Reihenfolge der Verbunde identisch sind. Auch die Art der Verbunde ist in beiden Anfragebäumen gleich. ein Unterschied ist der Rel-Index-Hash-Verbund mit der Relation H. Die Oracle-Datenbank greift hier auf den Index H VORLNR MATRNR PK zu. Da ein Rel-Index-Hash-Verbund in RELOpt nicht implementiert ist, wird in der Lösung von RELOpt ein normaler Rel-Rel-Hash-Verbund benutzt. Ein weiterer Unterschied könnte das Wurzelelement der beiden Anfragebäume sein, da aus der Oracle-Datenbank keinerlei Informationen über die Art der verwendeten Projektion zu bekommen sind. RELOpt bildet hier einen sortierten Indexbaum über die Er- 38 KAPITEL 5. EXPERIMENTE UND ANWENDUNGEN πP.NameS.Semester (10) ⋊ ⋉Hash H.MatrN r=S.MatrN r (10) ⋊ ⋉Hash V.V orlN r=H.V orlN r (7) ⋊ ⋉Hash P.ID=V.gelesenV on (5) TABLE ACCESS FULL INDEX FULL SCAN TABLE ACCESS FULL TABLE ACCESS FULL P V S H VORLNR MATRNR PK Abbildung 5.5: Beispielanfrage durch Oracle optimiert gebnisrelation und führt dann eine Index-Projektion mit Duplikateneliminierung durch. Aus dem PLAN_TABLE lassen sich keine Informationen über die Verwendung von Pipelines extrahieren. Die Form des Oracle-Anfragebaumes lässt aber auf deren Verwendung schliessen. 5.3.2 Beispielanfrage mit Selektion Fügt man der Anfrage eine Selektion hinzu, unterscheiden sich die beiden Anfragepläne erheblich in den verwendeten Verbunden. Als Beispiel dient wieder die aus Kapitel 1 bekannte Anfrage. Diese unterscheidet sich von der vorhergehenden nur durch die Selektion S.Semester = 5, die im ersten Beispiel weggelassen wurde. In der von RELOpt gelieferten Lösung in Abbildung 5.6 sieht man deutlich, dass die Selektion sehr früh ausgeführt wird und sich damit die Reihenfolge der Verbunde verändert hat. Die von Oracle gelieferte Lösung (siehe Abbildung 5.7) besitzt nun ebenfalls eine komplett andere Verbundreihenfolge. Zuerst wird die Selektion auf der Relation S durchgeführt, danach wird das Ergebnis daraus mit einem Rel-Index-Join mit der Relation H zusammengeführt. Als nächstes Folgt ein Rel-Index-Verbund mit der Relation V. Als letzter Verbund findet ein Rel-Index-Verbund mit der Relation P statt. Die beiden Anfragebäume sind von der Struktur her gleich, Hauptunterschied ist hier die Verwendung von Hash-Verbunden in RELOpt im Gegensatz zu Rel-Index-Verbunden in der Lösung des Oracle-Systems. 5.3. VERGLEICHE MIT DER ORACLE-DATENBANK Index/elim πP.Name 39 (1) Tree(P.Name)(5) ⋊ ⋉Hash P.ID=V.gelesenVon (5) Hash(·) ⋊ ⋉Hash V.VorlNr=H.VorlNr (5) Hash(·) Hash(·) ⋊ ⋉Hash H.MatrNr=S.MatrNr (3) V Hash(·) Hash(·) Rel σS.Semester =’5’ (1) H Hash(·) P S Abbildung 5.6: Beispielanfrage mit Selektion durch RELOpt optimiert πP.Name (5) ⋊ ⋉Rel-Index P.ID=V.gelesenVon (5) ⋊ ⋉Rel-Index V.VorlNr=H.VorlNr (4) ⋊ ⋉Rel-Index H.MatrNr=S.MatrNr (3) Rel σS.Semester =’5’ (2) P ID PK V VORLNR PK H VORLNR MATRNR PK S Abbildung 5.7: Beispielanfrage mit Selektion durch Oracle optimiert 5.3.3 Beispielanfrage mit Kartesischen Produkten Formt man die Beispielanfrage so um, dass sie Selektionen und kartesische Produkte statt Verbunde benutzt, liefert RELOpt die gleiche Lösung wie vorher (Abbildung 5.6). 40 KAPITEL 5. EXPERIMENTE UND ANWENDUNGEN Die Lösung des Oracle-Systems ist auch in diesem Fall unverändert (Abbildung 5.7). Die interne Behandlung von Selektionen und kartesischen Produkten ist also in beiden Systemen vergleichbar. Die benutzte Anfrage: (PROJECTION P.Name (SELECTION (AND S.Semester=’5’ P.ID=V.gelesenVon V.VorlNr=H.VorlNr H.MatrNr=S.MatrNr) (PRODUCT P (PRODUCT V (PRODUCT H S))))) Stellt man nachfolgende Anfrage, so kann man einen deutlichen Unterschied zwischen dem Oracle-Optimierer und RELOpt feststellen. Die Anfrage soll die Semester der Studenten liefern, die bei Professor ’D’ eine Vorlesung belegt haben. (PROJECTION S.Semester (SELECTION P.Name=’D’ (JOIN P.ID=V.gelesenVon P (JOIN V.VorlNr=H.VorlNr V (JOIN H.MatrNr=S.MatrNr H S))))) Index/elim πS.Semester (1) Tree(S.Semester )(20) ⋊ ⋉Rel-Index H.MatrNr=S.MatrNr (7) ⋊ ⋉Hash V.VorlNr=H.VorlNr (6) Hash(·) Hash(·) N.-Loop ⋊ ⋉P.ID=V.gelesenVon (2) Rel σP.Name=’D’ (1) Hash(·) S H V P Abbildung 5.8: weitere Beispielanfrage durch RELOpt optimiert 5.3. VERGLEICHE MIT DER ORACLE-DATENBANK 41 RELOpt liefert für diese Anfrage die Lösung in Abbildung 5.8. Diese unterscheidet sich komplett von der Lösung des Oracle-Systems in Abbildung 5.9. Ändert man die Anfrage leicht, indem man ein NOT vor die Selektionsbedingung setzt, liefert RELOpt immer noch die gleiche Lösung. Die Lösung des Oracle-Systems ist in Abbildung 5.10 zu finden. Diese ist wieder der von RELOpt gelieferten Lösung weitestgehend identisch. πP.Name (7) ⋊ ⋉Rel-Index H.MatrNr=S.MatrNr (7) ⋊ ⋉Hash (P.ID=V.gelesenVon)∧(V.VorlNr=H.VorlNr) (6) Merge ⋊ ⋉true (3) Rel σP.Name=’D’ (2) P S MATRNR PK V Sort(·) H VORLNR MATRNR PK Abbildung 5.9: weitere Beispielanfrage durch Oracle optimiert πS.Semester (10) ⋊ ⋉Hash H.MatrNr=S.MatrNr (10) ⋊ ⋉Hash V.VorlNr=H.VorlNr (7) ⋊ ⋉Hash P.ID=V.gelesenVon (5) Rel σP.Name=’D’ (2) H VORLNR MATRNR PK Hash(·) S V P Abbildung 5.10: die Beispielanfrage mit NOT durch Oracle optimiert 42 5.3.4 KAPITEL 5. EXPERIMENTE UND ANWENDUNGEN Fazit Bei den getesteten Anfragen sind sich die Lösungen von RELOpt und die des OracleSystems sehr ähnlich. Bei dem letzten Beispiel allerdings sieht man eine Eigenschaft des Oracle-Optimierers, bei einelementigen Ergebnismengen aus einer Selektion eine komplett andere Lösung zu liefern. Im Beispiel liefert die Selektion nur ein einziges Tupel. Das nachfolgende kartesische Produkt mit der größten Relation H ist daher sehr kostengünstig zu berechnen. Danach folgt ein Hash-Verbund mit zwei Bedingungen. Verbunde mit mehreren Bedingungen sind in RELOpts Optimierungsstrategie nicht vorgesehen. Hier sollte noch genauer untersucht werden, wieviel Kosten wirklich durch diese Art der Optimierung gespart werden können. Kapitel 6 Erweiterungen am Programm RELOpt In diesem Kapitel folgen detaillierte Beschreibungen der durchgeführten Änderungen und Erweiterungen am Programm RELOpt. Um den kompletten Entwicklungsgang des Programms zu betrachten, sollten auch die vorhergehenden Arbeiten von [Mak03] und [War03] beachtet werden. Zuerst folgt ein kurzer Abriss über die durchgeführten Arbeiten, danach dann die Implementierung. 6.1 Regeln Die in Kapitel 2 definierten Regeln wurden umgesetzt. Hierzu wurde ein vereinheitlichtes Regelsystem eingeführt, damit sowohl algebraische als auch physische Regeln eine gemeinsame Schnittstelle haben. Dies vereinfacht die Handhabung der Regeln. Denkbar wären dann auch gemischte Abarbeitung algebraischer und physischer Regeln. Weiterhin wurde eine Gruppierungsschnittstelle definiert. Diese ermöglicht es, Regeln in Gruppen zusammenzufassen. Der algebraische und der physische Optimierer wurden so erweitert, dass sie die neuen Regelstrukturen unterstützen. Eine Regelgruppe kann Regeln und weitere Regelgruppen enthalten. Beide Optimierer unterstützen nun auch iterative Regelbearbeitung. Hierbei werden Regeln in Gruppen zusammengefasst, und diese Regelgruppe wird dann vom Optimierer so lange angewendet, bis sich keine Änderungen mehr im Anfragebaum ergeben. Zum Beispiel: (Gruppe A (Gruppe B)* Gruppe C)* Hier wird zuerst Gruppe A bearbeitet, danach solange Gruppe B, bis keine Veränderung mehr eintritt, und danach Gruppe C. Anschließend beginnt die Abarbeitung wieder von vorn, solange wie sich noch etwas im Anfragebaum ändert. 43 44 6.2 KAPITEL 6. ERWEITERUNGEN AM PROGRAMM RELOPT Regelauswahl In einem ersten Schritt wurden die beiden unterschiedlichen Regelauswahlfenster jeweils durch ein neues ersetzt. Das neue Fenster ist so konzipiert, dass es sowohl die algebraischen als auch die physischen Regeln verwalten kann. Dies wurde durch die in Abschnitt 6.1 erwähnte Schnittstelle möglich. Die Schnittstelle wird zu einem späteren Zeitpunkt definiert. Auch die Gruppierungsfunktion wurde umgesetzt. Regelgruppen lassen sich nun über die grafische Benutzerschnittstelle anlegen und löschen. Das neue Fenster findet sich unter Abbildung 6.1. In diesem Fenster sieht man übersichtlich alle Regeln des jeweiligen Optimierers aufgelistet. Regelgruppen sind wie in einem Dateisystem angeordnet. Die Inhalte einer Regelgruppe können per Doppelklick ein- und ausgeblendet werden. In der rechten Spalte befindet sich ein Auswahlknopf. Dieser dient dazu, die Iteration für das jeweilige Element zu aktivieren, bzw. zu deaktivieren. Abbildung 6.1: Dialog für die Verwaltung physischer Regeln und Gruppen Ein Klick auf den Knopf Gruppe hinzufügen öffnet einen neuen Dialog (siehe Abbildung 6.2). In diesem Dialog kann man den Gruppennamen festlegen. Ein Klick auf OK legt die neue Gruppe an. Abbrechen schließt den Dialog, ohne eine neue Gruppe anzulegen. In der Tabelle kann man durch Doppelklick auf die Beschreibung in einen Editiermodus gelangen, um die Beschreibung zu ändern. Man kann eine beliebige Anzahl Regeln in der neuen Gruppe erstellen, oder Regeln aus anderen Gruppen in die neue Gruppe verschieben. Die anderen Knöpfe haben die in [War03] eingeführten Funktionen. 6.3. ZUSAMMENLEGUNG VON RELATION UND METADATEN 45 Abbildung 6.2: Dialog für das Anlegen von neuen Gruppen 6.3 Zusammenlegung von Relation und Metadaten Die in den vorhergehenden Versionen getrennte Bearbeitung von Relationen und Me” tadaten“ wurde in dieser Version aufgehoben, da die Beschreibung der Relationen auch zu den Metadaten zählt. Der Knopf Relationen wurde entfernt. Unter dem Knopf Metadaten (siehe Abbildung 4.1) finden sich nun beide Dialog-Tabellen (siehe Abb. 6.3). Die Statistischen Daten können nun direkt in der Tabelle geändert werden, ohne den Umweg über den Ändern-Dialog. Dieser wird noch für das Setzen und Löschen von Indexen und Sortierungen benötigt. Außerdem wird er für die Änderung der Anzahl der eindeutigen Tupel benötigt. Abbildung 6.3: Der neue Metadaten-Dialog 46 KAPITEL 6. ERWEITERUNGEN AM PROGRAMM RELOPT 6.4 Die Paketstruktur Es folgt ein kurzer Überblick über die Struktur des Programms (siehe Abbildung 6.4). de.unihannover.dbs.sopt gui test struc sun rules search tree alg phys sqlp db.oracle rules rules rules Abbildung 6.4: Die Paketstruktur von RELOpt Das Paket gui enthält alle Klassen (d.h. Dialoge und Masken) der grafischen Benutzerschnittstelle. Im Paket db.oracle findet man die Anbindung an die Oracle Datenbank. Im Paket test liegt die Hauptklasse zum Ausführen des Programms. Das Paket sqlp enthält den Anfrageübersetzer. Das Paket tree enthält die Implementierung zur Visualisierung der einzelnen Schritte als Baumdiagramme. Alle für die Optimierung benötigten Klassen finden sich im Paket struc. In rules liegen Superklassen und Interfaces für die Anordnung und Speicherung der Regeln in der neuen Baumstruktur. Die Klassen zur algebraischen Optimierung sind in alg zu finden. Die Klassen für die physische Optimierung befinden sich in phys. In search findet man Algorithmen für die kostenbasierte Optimierung. 6.5. IMPLEMENTIERUNG 6.5 6.5.1 47 Implementierung Vereinheitlichung des Regelsystems Im Hinblick auf spätere Erweiterbarkeit wurde das gesamte Regelsystem vereinheitlicht. Alle algebraischen und physischen Regeln haben nun eine gemeinsame Oberklasse AbstractRule. Diese befindet sich im Paket sopt.struc.rules. <<interface>> RuleNode DIRECTION_LEFT_TO_RIGHT DIRECTION_RIGHT_TO_LEFT +getName() +getDirection() +getDescription() +isBidirectional() +setDirection(boolean) +toString() SortedDup Projection Rule IndexDup Projection Rule AbstractRule physRule +applyRule(Relation) NestedDup Projection Rule Merge Join Rule IndexIndex Join Rule RelIndex Join Rule NestedLoop Join Rule Merge Semijoin Rule IndexIndex Semijoin Rule RelIndex Semijoin Rule NestedLoop Semijoin Rule Merge Antisemijoin Rule Merge Union Rule Rel Selection Rule Product Rule RelIndex Antisemijoin Rule IndexIndex Union Rule IndexIndex Antisemijoin Rule RelIndex Union Rule NestedLoop Antisemijoin Rule NestedLoop Union Rule Index Selection Rule Intersection Rule Difference Rule Abbildung 6.5: Klassendiagramm de.unihannover.dbs.sopt.phys.rules 48 KAPITEL 6. ERWEITERUNGEN AM PROGRAMM RELOPT Die aus dem statischen Optimierer1 extrahierten physischen Regeln (siehe Kapitel 2) sind in dem neuen Packet struc.phys.rules zu finden (siehe Abbildung 6.5). Die Regeln ProductRule, DifferenceRule und IntersectionRule unterscheiden sich von den anderen Regeln, da sie den physischen Optimierer in der alten Implementierung rekursiv aufrufen. Dies wurde so gelöst, das die Regeln die zu optimierende Relation aufbauen, und dann mit einer Nachricht an den laufenden Optimierer senden. Dieser kann dann die Nachricht empfangen, die neue Relation daraus extrahieren und neu bearbeiten. 6.5.2 Umsetzung der neuen Regelstruktur Um die Organisation der Regeln in Gruppen möglichst effizient durchzuführen, wurde von der bisher verwendeten Speicherung in Listen abgewichen. Die Regeln werden nun in einer baumähnlichen Struktur gespeichert, die im folgenden beschrieben wird: • RuleNode Diese Klasse ist ein Interface. Alle Knoten im neuen Regelbaum müssen dieses implementieren. Es stellt Methoden zur Identifizierung der Regel (z.B. Name und Beschreibung) zur Verfügung. – getName Liefert den Namen des Knotens – getDirection Liefert die Richtung des Regelknotens. – getDescription Liefert die Beschreibung de Knotens. – isBidirektional Liefert wahr, wenn die Regel Bidirektional ist. – setDirection Setzt die Ausführungsrichtung der Regel. – toString Liefert eine Stringdarstellung der Regel. • RuleGroupNode Diese Klasse repräsentiert innere Knoten, also die Regelgruppen. Diese können vom Benutzer angelegt werden. Sie enthalten einen Namen, dazu noch Regeln und/oder weitere Gruppen. Sie stellt Methoden zum Zugriff auf die enthaltenen Regeln und Gruppen zur Verfügung. Sie implementiert das Interface RuleNode. 1 siehe [Mak03] und [War03] 6.5. IMPLEMENTIERUNG 49 – getChildren Liefert die in der Gruppe enthaltenen Regeln/Gruppen. – add Fügt eine Regel oder Gruppe hinzu. – size Liefert die Anzahl der Regeln. (Sind z.B. 10 Regeln in 3 Gruppen liefert size() 10, nicht 13) – isEmpty Liefert wahr wenn der Knoten keine Kinder hat. – setTo Setzt diesen Knoten gleich dem übergebenen. Beide zeigen dann auf den selben Baum. Name und Beschreibung sind identisch. – setName Setzt den Namen der Gruppe. – setDescription Setzt die Beschreibung der Gruppe. – isIterative Liefert wahr, wenn die Gruppe iterativ ist. – setRecursive Setzt ob die Gruppe rekursiv ist. • AbstractRule Diese Klasse ist die neue Oberklasse aller algebraischen und physischen Regeln. Sie enthält Methoden zum Setzen und Auslesen der Ausführungsrichtung der Regel. Außerdem noch Methoden, die den Namen und die Beschreibung der Regel liefern. Klassen, die AbstractRule implementieren, müssen einen String DESCRIPTION als globale Variable haben, da dieser von der Methode getDescription mit Hilfe von Java-Reflection ausgelesen wird. Die Klasse implementiert das Interface RuleNode. • RuleFactory Diese Klasse stellt eine Methode zum Instanziieren von Regeln zur Verfügung. Man übergibt ihr den Namen der Regel und bekommt eine neue Instanz dieser Regel geliefert. Sie wird von den Auswahldialogen benutzt, um neue Regeln einzufügen. – constructRule Liefert die zum übergebenen String passende Regel. Ein Aufruf mit ARule“ ” würde also eine Instanz der Klasse ARule liefern. Im folgenden Klassendiagramm (Abbildung 6.6) ist die wichtigste Neuerung die Klasse AbstractRule und das Interface RuleNode. Beide sind Teil der eingeführten Vereinheitlichung der Regelstruktur.(siehe 6.5.1) 50 KAPITEL 6. ERWEITERUNGEN AM PROGRAMM RELOPT <<interface>> Rule <<interface>> MetadataBasedRule +optimize(AlgebraicTree) AlgRule +optimizeBottomUp(Relation) +optimizeTopDown(Relation) +optimize(Relation) +optimizw(Relation,boolean) ARule ... ERule FRule +setMetadata(Metadata) <<interface>> RuleNode DIRECTION_LEFT_TO_RIGHT DIRECTION_RIGHT_TO_LEFT +getName() +getDirection() +getDescription() +isBidirectional() +setDirection(boolean) +toString() AbstractRule GRule HRule IRule ... ZRule Abbildung 6.6: Klassendiagramm de.unihannover.dbs.sopt.alg.rules 6.5.3 Anpassung des physischen Optimierers Um aus dem vorhandenen starren physischen Optimierer2 einen flexiblen regelbasierten Optimierer zu machen, benötigt man eine gemeinsame Schnittstelle (siehe Kap. 6.5.2) der neuen Regeln. Der Optimierer wurde nun so erweitert, das er durch die neue Datenstruktur laufen kann. Sollte er dabei auf iterative Regeln oder Gruppen stoßen, so wendet er diese so lange an, bis keine Änderungen mehr im Anfragebaum auftreten. 6.5.4 Die Regelauswahl Die Benutzerschnittstelle wurde um eine regelbasierte Auswahl bei der physischen Optimierung ergänzt. Dort kann der Benutzer die unter Abschnitt 2 zu findenden Regeln in einer Tabelle anordnen, laden und speichern. Hierzu wurde die schon in [War03] eingeführte regelbasierte Auswahl des Algebraischen Optimierers refaktorisiert und an die neue Regelstruktur angepasst(siehe 6.5.2). 2 die Klasse AttrTransformer 6.5. IMPLEMENTIERUNG 51 Die Auswahldialoge für algebraische und physische Regeln wurden von JTable auf JTreeTable umgestellt. Durch die Verwendung einer Tabelle, die die Daten aus einer Baumstruktur darstellt, kann man die Regeln in Gruppen unterteilen, Gruppen von Regelgruppen bilden und diese übersichtlich darstellen. Diese Funktionalität wurde im Hinblick auf die spätere Zentralisierung der Regelauswahl (siehe Kap. 7) bereits jetzt eingeführt. Die vorher verwendeten Listen zur Verwaltung der Regeln wurden durch eine Baumstruktur ersetzt, diese wird in Abschnitt 6.5.2 erläutert. 6.5.5 Der Join-Order-Algorithmus Die Implementierung des Join-Order-Algorithmus aus Kapitel 3 besteht aus drei Klassen: • JOTableEntry Diese Klasse repräsentiert eine Zeile der Optimierungstabelle. Sie enthält die folgenden Methoden: – getCardinality Liefert die Kardinalität des Eintrags. – getProductCardinality Liefert die Kardinalität des Eintrags ohne Berücksichtigung der Selektivität. – setCardinality Setzt die Kardinalität des Eintrags. – getPages Liefert die Anzahl der belegten Seiten. – getProductPages Liefert die Anzahl der belegten Seiten ohne Berücksichtigung der Selektivität. – setPages Setzt die Anzahl der belegten Seiten. – getCost Liefert die Kosten. – setCost Setzt die Kosten. – getLHS Liefert die Startmenge. – setLHS Setzt die Startmenge. – getSet Liefert die Menge der beteiligten Relationen. 52 KAPITEL 6. ERWEITERUNGEN AM PROGRAMM RELOPT – setSet Setzt die Menge der beteiligten Relationen. – addToSet Fügt die übergebene Relation der Menge hinzu. – addToLHS Fügt die übergebene Relation der Startmenge hinzu. – getFanSel Liefert die Selektivität. – setFanSel Setzt die Selektivität. – toString Liefert eine Darstellung des Eintrags als String. – equals Liefert wahr, wenn der übergebene Tabelleneintrag identisch zu diesem ist. – clone Liefert eine exakte Kopie des Eintrags. – compareTo Liefert das Ergebnis des Vergleichs der beiden Stringrepräsentationen, wenn die Menge der Relationen gleich lang ist. Sollte die Menge der Relationen verschieden sein, so wird die Anzahl der Elemente in der ersten Menge minus der Anzahl der Elemente in der zweiten Menge zurückgegeben. So ist garantiert, das Einträge mit kurzen Mengen vor Einträgen mit langen Mengen kommen, und Einträge mit gleichlangen Mengen alphabetisch sortiert sind. • JOTable Diese Klasse repräsentiert die Optimierungstabelle. Sie implementiert TableModel, sowie die folgende Methoden: – add Fügt einen neuen Tabelleneintrag hinzu. Sollte der übergebene Eintrag schon vorhanden sein, so wird er nicht eingefügt. – get Liefert den Eintrag, der in der übergebenen Zeile steht. – getLeastCostItemForSet Liefert die Startmenge für die übergebene Menge. – getItemForSet Liefert den Eintrag, dessen Relationenmenge identisch mit der übergebenen Menge ist. – getItemForArray Liefert den Eintrag, dessen Inhalt der Relationenmenge identisch mit dem Inhalt des übergebenen Arrays ist. 6.5. IMPLEMENTIERUNG 53 • JORule Diese Klasse repräsentiert die Join-Order-Optimierung als algebraische Optimierungsregel. Sie erweitert AlgRule und implementiert MetadataBasedRule3 . Weiterhin hat sie folgende Methoden: – optimize Optimiert den übergebenen AlgebraicTree. Zuerst wird der Anfang des Teilbaums gesucht, der die Verbunde enthält. Dieser wird mit Hilfe des JoinOrder-Algorithmus optimiert. Das optimierte Ergebnis wird anstelle des alten Teilbaums in den Anfragebaum eingefügt. – setMetadata Setzt die Metadaten auf die übergebenen Metadaten. – getTable Liefert die Optimierungstabelle. – getResult Liefert das Ergebnis als String. 3 siehe [War03] 54 KAPITEL 6. ERWEITERUNGEN AM PROGRAMM RELOPT Kapitel 7 Ausblick • Erweiterung des Sprachumfangs Da die in RELOpt implementierten Konstrukte noch nicht die komplette Relationenalgebra abdecken, wären hier einige Ergänzungen notwendig. Als Beispiel sei hier der Outer-Join genannt. Auch eine Unterstützung der erweiterten Relationenalgebra, wie zum Beispiel Aggregation und Gruppierung, wäre sinnvoll. • Einlesen des Oracle-Anfrageplans Die Schnittstelle zum Oracle-System sollte so erweitert werden, dass die von Oracle gelieferten Ergebnisse in die von RELOpt verwendete Baumstruktur eingelesen werden. Dies würde auch die Visualisierung der gelieferten Anfragepläne ermöglichen. • Erweiterung des Join-Order-Algorithmus Der Join-Order-Algorithmus sollte so erweitert werden, dass Pipeline-günstige Bäume als Ergebnis geliefert werden, wenn die erwarteten Gesamtkosten mit Pipelines geringer sind als die Lösung ohne Pipelinebetrachtung. Da Pipelines Teil der physischen Optimierung sind, würde sich hier eine Erweiterung von RELOpt um parallele Betrachtung alternativer Lösungen anbieten. Der Join-Order-Algorithmus würde dann einmal die berechnete optimale“ Lösung lie” fern, parallel dazu aber auch eine Lösung, die eine möglichst lange Pipeline erlaubt. In den nachfolgenden Schritten wäre ein direkter Vergleich der beiden Lösungen möglich, um am Ende die optimale auszuwählen. • Späte Duplikateneliminierung Da zum jetzigen Zeitpunkt alle Projektionen mit Duplikateneliminierung implementiert sind, wäre hier eine Erweiterung von RELOpt um physische Regeln für Projektionen ohne Duplikateneliminierung sinnvoll. Der Optimierer hätte dann die Möglichkeit, kostspielige Duplikateneliminierung erst beim Endergebnis durchzuführen. 55 56 KAPITEL 7. AUSBLICK • Anpassung der Regeln an iterative Abarbeitung Um die in dieser Arbeit eingeführte iterative Abarbeitung von Regelgruppen komplett nutzen zu können, müssten alle Regeln so angepasst werden, dass sie nicht mehr selbsttätig durch den Anfragebaum laufen, sondern nur noch den übergebenen Teilbaum optimieren und sich dann beenden. Das Durchlaufen des Anfragebaums wird nun Aufgabe des Optimierers. Durch diese Änderung ist eine bessere Kontrolle gegeben, wann und wo welche Regeln in welcher Reihenfolge ausgeführt werden. • Manuelle Ersetzung von Operationen Um die Arbeit mit RELOpt zu verbessern, sollte ein Experimentierbereich implementiert werden, in dem der Benutzer mit der vom RELOpt gelieferten Anfrage verschiedene Operationen testen kann. Hier sollte es möglich sein, die einzelnen Operationen durch andere ersetzen zu können (zum Beispiel einen Merge-Verbund durch einen Nested-Loop-Verbund) und neue Operationen in den Anfragebaum einfügen zu können (zum Beispiel Sortierungen). Außerdem sollte der Benutzer die Möglichkeit haben, Operationen im Anfragebaum zu verschieben. In der Kostenanzeige sollten immer die aktuellen Kosten angezeigt werden, so dass man direkt die Auswirkungen sehen kann. Abbildungsverzeichnis 1.1 Anfragebaum der Beispielanfrage . . . . . . . . . . . . . . . . . . . . . . 3 1.2 algebraischer Baum der Beispielanfrage . . . . . . . . . . . . . . . . . . . 4 1.3 physischer Baum der Beispielanfrage . . . . . . . . . . . . . . . . . . . . 4 1.4 Anfragebaum des Beispiels nach der kostenbasierten Optimierung . . . . 5 4.1 Die Knöpfe im Hauptfenster von RELOpt . . . . . . . . . . . . . . . . . 21 4.2 Dialog für die Bearbeitung von Tabellen . . . . . . . . . . . . . . . . . . 22 4.3 Dialog für den Datenbanklogin . . . . . . . . . . . . . . . . . . . . . . . . 22 4.4 Dialog für den Import von Tabellen . . . . . . . . . . . . . . . . . . . . . 23 4.5 Oracle Anfrageplan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 4.6 Ausschnitt aus dem Paket sopt.sqlp.rules . . . . . . . . . . . . . . . . . . 30 4.7 Beispielanfragebaum für den SQL-Übersetzer . . . . . . . . . . . . . . . . 31 4.8 Beispielanfrage in SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 4.9 Dialog für den Anfrageplan Vergleich . . . . . . . . . . . . . . . . . . . . 32 5.1 Anfragebaum der Beispielanfrage (JOA/MSA) . . . . . . . . . . . . . . . 34 5.2 Anfragebaum der Beispielanfrage mit verschobener Selektion . . . . . . . 34 5.3 Anfragebaum des Beispiels aus Kapitel 1 . . . . . . . . . . . . . . . . . . 35 5.4 Beispielanfrage durch RELOpt optimiert . . . . . . . . . . . . . . . . . . 37 57 58 ABBILDUNGSVERZEICHNIS 5.5 Beispielanfrage durch Oracle optimiert . . . . . . . . . . . . . . . . . . . 38 5.6 Beispielanfrage mit Selektion durch RELOpt optimiert . . . . . . . . . . 39 5.7 Beispielanfrage mit Selektion durch Oracle optimiert . . . . . . . . . . . 39 5.8 weitere Beispielanfrage durch RELOpt optimiert . . . . . . . . . . . . . . 40 5.9 weitere Beispielanfrage durch Oracle optimiert . . . . . . . . . . . . . . . 41 5.10 die Beispielanfrage mit NOT durch Oracle optimiert . . . . . . . . . . . . 41 6.1 Dialog für die Verwaltung physischer Regeln und Gruppen . . . . . . . . 44 6.2 Dialog für das Anlegen von neuen Gruppen . . . . . . . . . . . . . . . . . 45 6.3 Der neue Metadaten-Dialog . . . . . . . . . . . . . . . . . . . . . . . . . 45 6.4 Die Paketstruktur von RELOpt . . . . . . . . . . . . . . . . . . . . . . . 46 6.5 Klassendiagramm de.unihannover.dbs.sopt.phys.rules . . . . . . . . . . . 47 6.6 Klassendiagramm de.unihannover.dbs.sopt.alg.rules . . . . . . . . . . . . 50 Tabellenverzeichnis 1.1 Beispielrelationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.2 Indexe der Beispielrelationen . . . . . . . . . . . . . . . . . . . . . . . . . 3 3.1 Die Basisrelationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 3.2 Tabelle nach der Initialisierung . . . . . . . . . . . . . . . . . . . . . . . 15 3.3 Tabelle für die Beispielanfrage V × P × S × H . . . . . . . . . . . . . . . 17 3.4 Neue Tabelle für die Beispielanfrage V × P × S × H . . . . . . . . . . . 19 3.5 Erweiterte Basisrelationen . . . . . . . . . . . . . . . . . . . . . . . . . . 19 3.6 Tabelle für die Beispielanfrage V o n (H o n S) . . . . . . . . . . . . . . . . 20 3.7 Optimierungstabelle für die Beispielanfrage aus Kapitel 1 . . . . . . . . . 20 5.1 Oracle-Operationen und ihre Umsetzung in RELOpt . . . . . . . . . . . 36 59 60 TABELLENVERZEICHNIS Literaturverzeichnis [Lip03] U. Lipeck. Vorlesungsskript Datenbanksysteme I, Wintersemester 2003/2004. 2003. URL:http://www.dbs.uni-hannover.de/lehre/dbs0304/. [Mak03] M. E. Makoui: Heuristische Anfrageoptimierungen in Relationalen Datenbanken. Diplomarbeit, Institut für Informationssysteme, Universität Hannover, 2003. [Mit95] B. Mitschang: Anfrageverarbeitung in Datenbanksystemen. Vieweg, Braunschweig/Wiesbaden, 1995. [ORA] Oracle Database 10g Release 1 (10.1) Documentation. Oracle Corporation. URL:http://www.oracle.com/technology/documentation/database10g.html. [VM96] B. Vance, D. Maier: Rapid Bushy Join-order Optimization with Cartesian Products. In H. V. Jagadish, I. S. Mumick (eds.), Proceedings of the 1996 ACM SIGMOD International Conference on Management of Data, Montreal, Quebec, Canada, June 4-6, 1996, ACM Press, 1996, 35–46. [War03] H. Warneke: Erweiterung eines Simulators für relationale Anfrageoptimierungen. Bachelorarbeit, Institut für Informationssysteme, Universität Hannover, 2003. 61