Hauptseminar Datenbanksysteme: Datenbanken und XML Thema: Efficiently Publishing Relational Data as XML Documents Seminar-Vortrag am 18.12.2001 von Dennis Säring Inhalt 1. Einführung und Motivation 2. Wiederholung ( XML ) 3. Ein Beispiel kurz erläutert mit Quellcode belegt 4. Ausführliche Vorstellung der Alternativen 5. Beurteilung der Effizienz aller Alternativen 6. Abschließender Kommentar und Ansätze für die Zukunft 7. Referenzen 1. Einführung und Motivation Das Ablegen großer Datenmengen in relationale Datenbanken und die zunehmende Verwendung von XML zur Veröffentlichung dieser Daten im WWW fordern Methoden die Tabellen effizient zu strukturieren und in Tag-Form zu bringen. Im folgenden Dokument erläutere ich verschiedene Ansätze und deren Vor- und Nachteile bezüglich der Effizenz. Im Wesentlichen sind dabei zwei Hauptvoraussetzungen zu erfüllen: 1. Eine Sprache, die die Umsetzung ( Strukturierung und Tagging ) von rel. Daten in XMLDokumente spezifiziert. Hierbei wird das bestehende SQL-System durch skalare Funktionen erweitert, um das aufwendige Entwickeln einer komplett neuen Sprache zu umgehen. Es ist außerdem möglich Standart-APIs wie ODBC zu verwenden um XML-Dokumente zu erhalten. Dies erlaubt bei bestehenden Tools und Anwendungen eine einfache Integration von relationalen Systemen und XML. Eine Kombination aus SQL und XML Anfragesprachen ist ebenso möglich. 2. Eine Implementation, die diese Umsetzung möglichst effizient vollzieht. Die relationalen Tabellen sind flach organisiert. Im Gegensatz dazu sind XMLDokumente hierachisch-, graphen- und tagged-strukturiert. Implementationen unterscheiden sich in Ort und Zeit ihrer Ausführung 2. Wiederholung ( XML ) XML ist ein hierachisches Format zur Veröffentlichung von Daten im WWW, bestehend aus verschachtelten Elementen. Jedem Element wird eine Markierung ( Tag ) zugeordnet. Desweiteren können Elemente Attribute und Subelemente enthalten. In XML können Elemente geordnet werden. <customer id=“C1“> <name> John Doe </name> <accounts> <account id=”A1”> 1894654 </account> <account id=”A2”> 3849342 </account> </accounts> <porders> <porder id=”P01” acct=”A2”> // first purchase order <date> 1 Jan 2000 </date> <items> <item id=”I1”> shoes </item> <item id=”I2”> bungee ropes </items> </items> <payments> <payment id=”P1” due Jan 15 </payment> <payment id=”P2” due Jan 20 </payment> <payment id=”P3” due Feb 15 </payment> </payments> </porders> <porder id=”P02” acct=”A1”> // second purchase order … </porder> </customer> Customer ( id integer, name varchar(20) ) Account ( id varchar(20), custId integer, acctnum integer ) PurchOrder ( id custId acctId date Item ( id integer, poId integer, desc varchar(10) ) integer, integer, varchar(20), varchar(10) ) Payment ( id integer, poId integer, desc varchar(10) ) Abb. 1 Abb. 2 3. Auf SQL basierende Sprache zur Veröffentlichung rel.Daten in XML Wie bereits erwähnt, ist die Ausarbeitung einer Sprache zur Spezifikation der XMLKonvertierung von relationalen Daten wesentlich. Man hat nun die Möglichkeit eine neue Sprache speziell für dieses Problem zu erstellen oder wie es in dieser Untersuchung favourisiert wird, die bestehenden Ressourcen zu nutzen und zu erweitern. Dazu werden geschachtelte SQL-Strukturen zum nested-structuring und SQL-Funktionen zur Konstruktion von XML Elementen verwendet. Betrachten wir nun das relationale Schema „Customer“ ( Abb.2 ) Zu beachten sind die verschiedenen Tables ( Customer, Account, PurchaseOrder, Item, Payment ), deren IDs, deren zugeordneten Attribute und ihre Fremdschlüsselrelationen. Select cust.name CUST(cust.id, cust.name, (Select XMLAGG(ACCT(acct.id,acct.acctnum)) From Account acct Where acct.custId = cust.id), (Select XMLAGG(PORDER(porder.id,porder.acct,porder.date, (Select XMLAGG(ITEM(item.id,item.desc)) From Item item Where item.poId = porder.id), (Select XMLAGG(PAYMENT(pay.id,pay.desc)) From Payment pay Where pay.poId = porder.id))) group order by porder.date From PurchOrder porder Where porder.custId = cust.id)) From Customer cust Abb. 3 create function CUST (custId : integer, custName : varchar(20), acctList : XML, porderList : XML ) returns xml language xml return <customer id={custId }> <name> {custName} </name> <accounts> {acctList} </accounts> <porders > {porderList} </porders > </customer> Abb.4 Eine Möglichkeit der Konvertierung wird in Abb. 3 dargestellt. Innerhalb einer SQL Anfrage werden sowohl SQL- als auch XML-Daten erstellt. Das Ergebnistupel setzt sich zusammen aus dem CustomerName zusammen mit seiner XML-Representation. Die gesamte Query besteht aus Sub-Queries, die alle weiteren Tables und deren XMLDarstellung generieren. Die XML-Elemente werden mit Hilfe des XML-Konstruktors erstellt. Einen Beispiel-Konstruktor für den Customer sieht man in Abb. 4. Ihm wird der CustomerName, AccountInf. ( in XML-Form ) und PurchaseOrderInf. ( in XML-Form ) übergeben. Das Ergebnis ist das Customer-XML-Element. Der Konstruktor ist eine skalare Funktion, die ein XML-Fragment mit den übergebenen Parametern zurück gibt. Alle anderen Tables ( Account, PurchaseOrder, Payment, Item ) werden ähnlich in XML konvertiert. XMLAGG fügt die Elemente zu einem vollständigen XML-Dokument zusammen. Um die XML-Fragmente in der richtigen Reihenfolge geordnet zusammen zu setzen, muß XMLAGG bereits geordnete Werte ( Inputs ) erhalten. 4. Alternativen von Implementationen Relationale Datenbanken unterscheiden sich von XML-Dokumenten durch die Struktur und die Tags. Somit ergeben sich zwei wesentliche Aufgaben: § Strukturierung der Daten; Konvertierung in ein geschachteltes hierachisches System § Eintragung von Tags; Einfügen von Textuellen Fragmenten Um die verschiedenen Alternativen möglichst klar voneinander abzugrenzen, unterteilt man die Ansätze nach den zeitlichen Gesichtspunkten: § § frühes Markieren / spätes Markieren ( early tagging / late tagging ) frühes Strukturieren / spätes Strukturieren ( early structuring / late structuring ) early tagging late tagging outside early structuring inside outside inside outside ( frühes Markieren macht ohne vorheriges Strukturieren keinen Sinn ) late structuring inside Abb. 5 Diese 3 Alternativen ( Abb. 5 ) werden noch zusätzlich unterschieden, ob die Arbeit innerhalb der relationalen Maschine erledigt werden kann. § inside the engine ( completely inside ) § outside the engine ( not necessarily all outside ) 4.1. early tagging & early structuring 4.1.1. the stored procedure approach Der einfachste Weg relationale Daten zu strukturieren, ist die Verwendung einer explizit geschachtelten Anfrage, welche die Daten in XML-Form bringt. Man beginnt bei der Wurzel und arbeitet sich dann iterativ nach unten durch. Im Beispiel aus Abb.1 würde man zuerst den Customer mit all seinen Attributen in XMLForm bringen, dann mit Hilfe der CustomerID die dazugehörige Account konvertieren, dann die PurchaseOrder. Anschließend ( ein level tiefer ), verarbeitet eine Query Item und Payment. Der Prozess für einen Customer ist nun abgeschlossen, für jeden weiteren Customer muß die Prozedur erneut durchgeführt werden. Ordnen kann man die Struktur innerhalb der SQL-Anfrage mit Hilfe der bekannten order by Anweisung. Hier wird eine externe Schleife über SQL-Anweisungen zur Strukturierung der Daten genutzt. Das Strukturieren und Markieren geschieht hier frühzeitig, daher charakterisiert man diesen Ansatz als early tagging & early structuring ouside the engine. Dieser Ansatz beinhaltet zwei Probleme, zum einen sind eine große Anzahl an SQL-Queries nötig ( äußerst ineffizient ), zum anderen fordert diese Methode eine Sortierung beim union und Schleifenmethoden zur Schachtelung. Hier wären andere Methoden eventuell sinnvoller, bzw effektiver. 4.1.2. the correlated CLOB approach Um die große Anzahl an Queries zu umgehen verlagert man alles in eine große Query mit Sub-Queries. Das tagging und structuring ist komplett innerhalb der Maschine zu lösen, durch die Verwendung von XML-Konstruktoren und der XMLAGG-Funktion. Die erstellte Query wird dann als nested-Query ausgeführt, sie folgt dabei im wesentlichen der bereits in Abb. 3 gezeigten Sprache. Die konstruierten XMLFragmente können dabei beliebig groß werden, so dass diese als große Objekte [ CLOBs ], ( Character Large Objects ) betrachtet werden. Die festen Zuordnungen ( Correlation ) der Tables fordern wieder Schleifen zur Schachtelung, die wiederum Einbußen bei der Effizienz zur Folge haben. Objekte werden unabhängig von ihren Tupeln abgelegt, so kann das Speichern in parallen Netzen ineffizient werden. Bei einer Sortierung müssen Objekte in den Zwischenspeicher kopiert werden (overhead). Der Aufruf eines XML-Konstruktors ist somit sehr teuer. ( custXML ) CUST() Data flow Correlation ( custId,custName ) Customer ( acctXML ) Groupby: XMLAGG(ACCT()) ( acctId, acctNum ) Join custId = acct.custId ( poXML ) custID Groupby: XMLAGG(PORDER()) ( poId, poAcct, poDate ) Join custId = po.custId ( itemXML ) ( payXML ) Groupby: XMLAGG(ITEM()) Groupby: XMLAGG(PAY ()) custID ( custId, acctId, acctNum ) Account ( custId, poId, poAcct, poDate ) poID PurchOrder poID ( itemId, itemInfo ) ( payId, payInfo ) Join poId = item.poId Join poId = pay.poId (poId, itemId, itemInfo ) (poId, payId, payInfo ) Item Payment Abb. 6 4.1.3. the decorrelated CLOB approach Um die Verwendung von Schleifen zu umgehen, kann eine Query ohne feste Zuordnung ( de-correlated ) erstellt werden, dadurch wird ein hohes Maß an Flexibilität gewonnen. ( Abb. 7 ) Die Verbindung von der Wurzel zu den jeweiligen Blättern wird durch einen join hergestellt. Diese outer-joins werden verwendet, damit Informationen über den Stamm erhalten bleiben. Die XML-Darstellung der Blätter wird erstellt und unter Verwendung von XMLAGG eine Gruppierung nach ID des Parent vorgenommen. Durch die Id kann der Pfad zurück verfolgt werden. Die Struktur wird erstellt durch das Zusammenführen dieser ID-Felder und der anschließenden Verwendung des XML-Konstruktors, dieses wird bis zum root-level ausgeführt. Dieser Ansatz ist zwar flexibler, beinhaltet aber die gleichen Probleme wie der correlated-CLOB Ansatz, da auch hier durch das frühe Strukturieren und Markieren, das Zwischenspeichern von CLOBs nötig ist. ( custXML ) Join: CUST() custId = custId ( custId, porderXML ) Groupby: custId XMLAGG(PORDER()) ( custId, poId, poAcct, poDate, itemXML, payXML ) Join custId = custId and poId = poId ( custId,poId,poAcct,poDate,itemXML ) Groupby: custId, poId XMLAGG(ITEM()) ( custId, poId, payXML ) Groupby: custId, poId XMLAGG(PAY()) ( custId, custName, acctXML ) Groupby: custId XMLAGG(ACCT()) ( custId,poId,poAcct,poDate,itemId,itemInfo ) ( custId,poId,payId,payInfo ) Right Outer Join item.poId = po.id Left Outer Join pay.poId = po.id (custId, custName, acctId, acctNum) Right Outer Join acct.custId = custId ( itemId, itemInfo ) Item ( custId, acctId, acctNum ) ( custId,custName ) Account Customer Left Outer Join cust.id = po.custId Payment ( custId, potId, poAcct, poDate ) PurchOrder Abb. 7 4.2. late tagging & late structuring Das Erstellen von XML-Dokumenten, wobei Strukturieren und Markieren am Ende stattfindet, unterteilt sich in zwei wesentliche Schritte: 1. Das Erstellen der relationalen Daten ( content creation ) 2. Das Strukturieren und Markieren zur Erstellung des XML-Dokuments ( structuring / tagging ) Die folgenden Ansätze werden komplett innerhalb der Maschine verwirklicht um auszunutzen, daß Funktionalitäten wie join bereits gegeben sind. 4.1.4. content creation: redundant relation approach Erstelle die Daten durch einen join über alle Tables, wobei die Beziehungen beachtet werden müssen ( Abb. 8 ). Es ergeben sich dadurch zwei Probleme, zum einen verwendet man redundante Prozesse und zum anderen erhält man durch den join redundante Inhalte. So werden beispielsweise die Informationen des Customer_Accounts unnötigerweise PurchaseOrder * Items per PO * Payments p. PO wiederholt. Dadurch wird der enstehende Table unnötig groß. Das Umwandeln in eine hierachische Struktur wird aufwendig. Select cust.id, cust.name, acct.id, acct.num, po.id, po.acctId, po.date, item.id, item.info, pay.id, pay.info From Customer cust left join Account acct on cust.id = acct.custId left join PurchOrder po on cust.id = po.custId left join Item item on po.id = item.poId left join Payment pay on po.id = pay.poId Abb. 8 4.2.2. content creation: ( unsorted ) outer union approach Mit diesem Ansatz wird versucht die multiplikative durch eine additive Vergrößerung zu ersetzen, um so zu viele redundante Daten zu vermeiden. Dazu betrachten wir die einzelnen Blätter eines Stammes separat, so wird auf dem Pfad nur die Repräsentation dieses Astes gespeichert und keine Informationen seiner Nachbarn. ( Abb. 9 ) Im Beispiel werden 3 Pfade ( path outer union ) erstellt, ( Customer-Account, CustomerPurchaseOrder-Item und CustomerPurchaseOrder-Payment ) so wird viel redundante Vervielfälltigung vermieden. Zuletzt werden alle Tupel zu einer Relation zusammengefasst ( outer union ), dabei müssen folgende Dinge beachtet werden: § Die Anzahl der Spalten kann sich von Blatt zu Blatt unterscheiden, durch das Einfügen von null-Spalten stellt man die Gleichheit wieder her § Der ursprünglichen Pfad geht verloren, dieses umgeht man durch das Hinzufügen einer Type-Spalte die quasi den dazugehörigen Pfad identifiziert ( type, custId, custName, acctId, acctNum, poId, poAcct, poDate, itemId, itemInfo, payId, payInfo ) Outer Union ( custId, poId, poAcct, poDate, itemId, itemInfo ) ( custId, poId, payId, payInfo ) Rigth Outer Join poId = poId Left Outer Join poId = poId ( custId, custName, acctId, acctNum ) Item ( custId, poId, poAcct, poDate ) Rigth Outer Join custId = custId ( acctId, acctNum ) Account Payment Left Outer Join poId = poId ( poId, poAcct, poDate ) ( custId, custName ) PurchaseOrder Customer Path Outer Union - Abb.9 Redundante Daten erhält man hier durch die Wiederholung von root-Daten, man könnte diese auch direkt in das outer union schreiben ( node outer union ( Abb. 10 )), würde so allerdings eine größere Anzahl an Tupel bekommen, was wiederum nicht unbedingt effizient wäre. Bei diesem Ansatzt wächst die Anzahl der Spalten, mit der Tiefe und Weite des XMLDokuments, obwohl nur wenige Tupel Daten enthalten ( viel null-wertigen Spalten ), kann sich durch das Nicht-komprimieren von null-Werten die Effizienz verringern. 4.2.3. structuring / tagging: hash-based tagger Nachdem die relationalen Daten nun auf XML-Struktur gebracht wurden, müssen diese noch getagged werden. Eine Möglichkeit innerhalb der Maschine zu taggen ist die Verwendung von den bereits vorgestellten XML-Konstruktoren und dem XMLAGG. ( wieder das Problem aus dem CLOB Ansatz ) Ob inner- oder außerhalb der Maschine, im wesentlichen sind 2 Aufgaben zu lösen. § Zusammenfassen aller Geschwister gleicher Eltern und löschen von doppelten Elementen § Jedes Tupel analysieren und entsprechend markieren um das XML-Dokument fertig zu stellen. Die erste Aufgabe kann man mit Hilfe eines Hash-basierten Ansatzes lösen. Ein Tupel, welches Informationen bezüglich eines XML-Elements enthält, wird in einem Hashtable eingefügt unter Beachtung seines Element-Types und der ID seines Parent, so kann festgestellt werden ob sein Parent bereits im Table vorhanden ist. Ist dies der Fall, wird ein neues XML-Element erstellt und als child eingefügt, falls nicht, wird ein hash ausgeführt auf Typ und IDs aller Vorfahren ausgenommen Parent. Auf dieser Art wird das Dokument durchlaufen bis zum root Element. Nachdem alle Tupel „gehashed“ wurden, kann die XML-Datei geschrieben werden. Falls eine bestimmte Ordnung der Elemente gefordert ist, wird dies entweder bei Erstellung eines Childs oder zuvor in einem Sortierverfahren geschehen. Dieser Ansatz ist effizient, wenn genügend Speicher für die Tabellen zur Verfügung steht, ist dies nicht der Fall, wird der Ansatzt schnell ineffizient. Lösung hierfür wäre eine Partitionierung der Daten ( verteiltes Hashing ). ( type, custId, custName, acctId, acctNum, poId, poAcct, poDate, itemId, itemInfo, payId, payInfo ) Outer Union ( custId, poId, itemId, itemInfo ) ( custId, poId, payId, payInfo ) Join poId = poId Join poId = poId ( custId, custName, acctId, acctNum ) Join custId = custId ( poId,itemId,itemInfo ) Item ( custId, acctId, acctNum ) Account ( custId, poId, poAcct, poDate ) ( poId,payId,payInfo ) Join custId = custId Payment ( custId, poId, poAcct, poDate ) ( custId, custName ) PurchaseOrder Customer Node Outer Union - Abb.10 4.3. late tagging & early structuring Das Erstellen von strukturiertem Inhalt und anschießendem tagging mittels eines platzkonstanten Taggers wird hier verwendet, um das Problem der Speicherverwaltung aus 4.2.2 zu umgehen. 4.3.1. structured content creation: sorted outer union approach Die relationalen Daten müssen so sortiert werden, wie sie dann auch ins XMLDokument geschrieben werden sollen. Dabei muß folgendes beachtet werden: 1. Die Information eines Parent kommt vor der Information vom Child 2. Auf Informationen eines Knotens folgen die Informationen seiner Nachfolger, Informationen von Nicht-Nachfolgern werden nicht mit hinein gemischt Im folgenden wird anhand des path-outer-union Ansatzes gezeigt, dass es ausreichend ist eine eine Sortierung auf dem unstruktiertenEgebnis von 4.2.2. auszuführen um die oben beschriebenen Forderungen zu erfüllen. Um Bedingung 1 und 2 zu erfüllen, muß das Ergebnis des outer union Ansatzes nach IDs sortiert werden. ( IDs der parents sind höher als IDs der childs ) Im Outer Union Null Spalten hinzugefügt, wenn ein Eintrag von A nicht keinen „Partner“ in B hat. Die dadurch entstehenden Tupel mit null-wertigen Einträgen müssen in der Sortierreihenfolge vor den anderen Tupeln stehen, somit ist gesichert, dass parentTupel vor den child-Tupeln stehen ( Bedingung 1 ). Ebenso werden hiermit die Childs des jeweiligen parent in einer Gruppe hinter dem Parent sortiert, was die Bedingung 2 erfüllt. ( type, custId, custName, acctId, acctNum, poId, poAcct, poDate, itemId, itemInfo, payId, payInfo ) Order by: custId, poDate, poId, acctId, payId, itemId ( type, custId, custName, acctId, acctNum, poId, poAcct, poDate, itemId, itemInfo, payId, payInfo ) Outer Union ( custId, poId, poAcct, poDate, itemId, itemInfo ) ( custId, poId, payId, payInfo ) Rigth Outer Join poId = poId Left Outer Join poId = poId ( custId, custName, acctId, acctNum ) Item ( custId, poId, poAcct, poDate ) Rigth Outer Join custId = custId ( acctId, acctNum ) Account Payment Left Outer Join poId = poId ( poId, poAcct, poDate ) ( custId, custName ) PurchaseOrder Customer sorted Path Outer Union - Abb.9a Dieser Ansatz hat den Vorteil große Datenvolumen speicherfreundlich zu sortieren, und mit geringem Kostenaufwandt Benutzeranfragen zu erfüllen. Da es aber nicht wichtig ist alle „Geschwister“ zu sortieren ( es ist lediglich nötig die Reihenfolge von parents und childs einzuhalten), wird zu viel Arbeit in die Gesamtsortierung gesteckt. 4.3.2. tagging sorted data: constant space tagger Die strukturierten Daten werden in ihrer sortierten Reihenfolge eingelesen und markiert. Der Tagger benötigt Speicher, um sich die IDs des parent zu merken, um so entscheiden zu können, ob ein Endtag gesetzt werden muß oder nicht. Die Größe des Speichers ist konstant in der Anzahl der Level und unabhängig von der Größe des XML-Dokumentes. 5. Beurteilung bzgl. Effizienz der vorgestellten Alternativen Vor- und Nachteile der Methoden wurden bereits erwähnt, im folgenden Abschnitt wird untersucht welche Methode wann am sinnvollsten angewendet wird. Es werden insgesamt vier Parameter definiert, mit denen man die einzelnen Tests variieren kann und Schlüsse aus den Ergebnissen ziehen kann. 5.1. Modellerstellung Um die Schachtelung der Daten zu charakterisieren, definiert man zwei Parameter, der Erste gibt die maximale Anzahl von sub-querys eines parents an, ( query fan out ) der Zweite repräsentiert die Tiefe der Schachtelung ( query depth ). In diesem Versuch werden nur ausgeglichene Strukturen verwendet. § jedes Element, welches kein Blatt ist, hat die gleiche Anzahl an direkt verschachtelten Sub-Queries § alle Blätter haben die gleiche Tiefe, bzw. sind auf dem selben Level Diese beiden Parameter ( fan out & depth ) spezifizieren lediglich die Struktur. Die Effekte der Variierung dieser Parameter ist Ziel der Untersuchung, nicht die Komplexität der SQL-Query zur Erstellung eines XML Elementes. Im folgenden wird ein Schema verwendet, ähnlich dem aus Abb.2 + Abb.3, jede Relation wird durch einen Table dargestellt. Ein Table enthält einen ID Eintrag ( Primary key ) und eine ParentJoinID Eintrag ( Foreign key ), um parents und childs zu verknüpfen, wird jeweils ein join über ID und PJID ausgeführt. Zusätzlich zu den beiden Feldern werden zwei Datenfelder unterschiedlichen Typs ( IntVal : Integer ) & ( CharVal : String[20] ) hinzugefügt. Die beiden anderen Parameter reichen aus um die Datenbank zu beschreiben, zum einen number of roots, der die Anzahl der Tupel im root level wiedergibt. Der zweite Parameter ist number of leaf tuples, der entspricht der Anzahl aller Blatt-level Tupel geteilt durch die Anzahl aller Blatt-level Tables. ( Tupel pro Table ). Zusammengefaßt erhält man den instance fan out, der die Anzahl der Child-Tupel jedes Typen, der einen Parent-Tupel besitzt, spezifiziert. ( Voraussetzung dafür ist, daß jedes Parent Tupel die gleiche Anzahl an Child Tupel besitzt ) Der Parameter number of leaf tuples ist interessant, da dieser Wert in Beziehung zur Größe des entstehenden XML-Dokuments steht, und es somit möglich ist bei konstanter Anzahl an leaf tupels die unterschiedlichen Strukturierungs Ansätze zu analysieren. Das gewonnene XML-Dokument sieht folgendermaßen aus: § die Werte der Int und Char Spalte wurden mit einen String der Länge 3 markiert § die XML-Fragmente der Child Tupel sind verschachtelt unter den der parents § das Ergebnis ist immer ein einzelnes gesamtes XML-Dokument Zu beachten ist, dass lediglich number of roots und number of leaf tuples variieren und die Tables gleich bleiben. 5.2. Aufbau des Experiments Implementation der Alternativen auf DB2 System, wobei die XML-Konstruktoren und XMLAGG als built-in Funktionen umgesetzt wurden. Der stored procedure Ansatz läuft im gleichen Addressraum wie die relationale Maschine ( unfenced ), um die Performence zu maximieren. Alle outside the engine Ansätze werden lokal als eingebundene SQL-Programme auf der gleichen Maschine wie der DB Server implementiert, um so Kommunikationsaufwand im Netz zu vermeiden. Die Zeitmessung erfolgt über ein SQL-Programm, die Ausgabe wird in eine NT-Datei geschrieben. Ein Pentium 366 MHz, 256 MB Arbeitsspeicher und das Windos NT 4.0 Betriebssystem bilden die Hardware. Die verwendeten Parameter wurden wie in Abb. 11 dargestellt variiert. Alle Prozesse konnten innerhalb des Arbeitsspeichers abgewickelt werden, somit gibt es keinen Verlust von Effizienz durch Auslagerung. Da sich node-outer-union und path-outerunion nur sehr gering unterschieden, wurde standartmäßig mit path-outer-union getestet, deren Unterschiede werden dann im Anschluß separat diskutiert. Parameter Query Fan Out Query Depth # Roots # Leaf Tuples Range of Values 2, 3, 4 2, 3, 4 1, 50, 500, 5000, 40000 160000, 320000, 480000 Default 2 2 5000 320000 Abb. 11 5.3. Inside the engine vs. ouside the engine Zunächst wird der query fan out variiert und die restlichen Parameter konstant gehalten. In Abb. 12 a & b werden inside und ouside Ansätze verglichen, wobei redundant relation nicht mit aufgetragen wurde da dessen schlechte Performence bei hohem fan out zu gravierend war. ( Seine reine Ausführungszeit bei einem fan out von 4 betrug rund 155 Sek ) Abb. 12a Abb. 12b Abb. 12 b zeigt deutlich den overhead beim stored procedure Ansatz, der correlated CLOB Ansatz ( inside the engine ) benötigt nur ein Drittel gegenüber ( outside the engine ). Die inside Methoden sind durchweg effizienter. In Abb. 13 sind die einzelnen Zeitaufwände aufgezeigt, § Zeit zum Umformen der relationalen Daten ( execution ) § Zeit um den relationalen Inhalt für outside Funktionen verfügbar zu machen ( bind out ) § Zeit den Inhalt zu taggen und möglicherweise das Ergebnis zu strukturieren ( tagging ) § Zeit die gewonnene Ergebnis in eine Datei zu schreiben ( XML file ) Zu beachten ist folgendes: inside the engine Ansätze enthalten kein bind out und CLOB Ansätze besitzen tagging als festen Bestandteil der execution. Es ist deutlich zu beobachten, daß den größte Zeitanteil der outside Ansätze das bind out einnimmt, auch durch anpassen der Kommunikationsparameter ( z.B. Buffervergrößerung ) erhält man kein besseres Ergebnis. Somit disqualifizieren sich die outside the engine Ansätze für weitere Untersuchungen, dennoch haben diese Ansätze den Vorteil, daß sie bei Datenbanken eingesetzt werden können, die keine zusätzlichen XML-Funktionen unterstützen. Abb. 13 5.4. Effekt des query fan out Eine Erhöhung des query fan out Wertes erzeugt einen größeren Zeitaufwand bei der Erstellung des XML-Dokumentes, begründet ist dies durch die größere Anzahl an joins die durchgeführt werden müßen. Betrachtet man die Ansätze einzelnd, fällt auf, daß der correlated CLOB die schlechtesten Werte hervorbringt. Grund dafür ist die Verwendung der verschachtelten loop joins. Desweiteren ist zu beobachten, daß der unsortet outer union plan effizienter als der sortet outer union plan ist. Die Verwendung von komplexen Hashtabellen scheint effizienter ( zumindest bei genügend Speicher ) zu sein als eine Sortierung mit anschließendem platzkonstanten Tagger. Ein überaschendes Ergebnis erhält man für den decorrelated CLOB Ansatz, der bei kleinem fan out die besten Werte liefert. Grund hierfür ist der DB2 Optimierer, welcher kleinere Objekte im Hauptspeicher behält, ebenso bleibt der overhead bei geringer query depth klein. In Abb. 12 b sind die Werte der outer engine Ansätze dargestellt, hier zeigt sich die stored procedure Methode als ineffektiv ( zu viele queries müssen erstellt werden; Verwendung einer fixen join Strategie ). Im Gegensatz zur inside the engine Umsetzung, sind die Ergebnisse des sorted und unsorted outer union Ansatzes outside sehr ähnlich, da hier der Tagger ein streaming Operator ist, d.h. sobald ein Tupel erkannt wird, wird dieses in die Datei geschrieben, wohingegen der hash-basierte zunächt alle Prozesse abwarten muß und erst dann die XML Datei schreiben kann. 5.5. Effekt der query depth In Abb. 14 sieht man die Ergebnisse ( inside the engine ) bei Variierung des query depth Parameters. Die de-correlated CLOB Methode steigt mit der Tiefe gegenüber den anderen Kandidaten drastisch an. Begründen kann man dies mit den Fehlern die der relationale query Optimierer begeht, wenn die Queries zu komplex werden. Der Optimierer entscheidet sich beispielsweise zu einer Sortierung der Daten nach Ausführung von XMLAGG, hierbei müssen einige CLOBs in temporären Speicher kopiert und wieder verwendet werden, was die Effektivität stark verringert. Die traditionellen Optimierer können mit der Aggregatsfunktion nicht viel anfangen und somit die Größe des CLOB Ergebnisses nicht gut kalkulieren. 5.6. Effekt der number of roots Allgemein kann man sagen, daß das Ändern dieses Parameters keine wesentlichen Auswirkungen auf die Laufzeit der verschiedenen Methoden hat, lediglich die Methode des correlated CLOBs optimiert sich bei wenig root Elementen und verschlechtert sich relativ zu den anderen stark bei größeren Werten für number of roots. ( Bei nur einem root-Element müssen nur 2 sub-queries erstellt werden, sehr effektiv ) Abb. 14 Abb. 15 5.7. Effekt der number of leaf tuples, memory size Es sind keine gravierenden Einbußen der Effizienz zu erkennen, wenn man die Anzahl der leaf – Tupel erhöht und genügend Speicherplatz zur Verfügung steht. Bei zu wenig Hauptspeicher zeigt sich, daß die unsorted outer union Methode kein Ergebnis liefern kann. Das Problem liegt hier beim hash-basierten Tagger, der ( noch ) nicht in der Lage ist overflows zu handhaben. Im Gegensatz dazu, kommt der sorted outer union plan mit der Speichereinschränkung gut zurecht. 5.8. path outer union vs. node outer union Wie bereits zuvor angekündigt, werden jetzt die beiden Methoden untersucht, die bei ausreichend Speicherplatz, ähnliche Ergebnisse liefern. Obgleich der höheren Daten Redundanz weist der path outer union Ansatz etwas bessere Werte auf, da hier weniger Tupel erstellt werden müssen. Ist der Speicher nicht ausreichend und gibt es einen hohen instance fan out, ist der node outer union ca 3 Sekunden besser, der path Ansatz erstellt dann mehr redundante Daten und erhält einen overhead beim Auslagern. 5.9. Zusammenfassung der erarbeiteten Ergebnisse Drei wesentliche Aussagen können bzgl. der Messergebnisse getroffen werden : 1. XML-Dokumente gewinnt man am effizientesten mit inside the engine Ansätze 2. Wenn genügend Speicher vorhanden ist, um den kompletten Prozeß im Hauptspeicher zu halten, so ist der unsorted outer union Ansatz ( inside & outside ) die effizienteste Lösung. 3. Falls der Speicher nicht ausreicht, sollte man die sorted outer union Methode verwenden, da der relationale Sortierungsoperator sehr gut skaliert 6. Abschließender Kommentar und Ideen für zukünftige Arbeiten Daten im WWW werden immer häufiger mittels XML veröffentlich, somit ist es nötig, Lösungen zu erforschen, die es ermöglichen relationale Datenbanken in eine XML Form zu konvertieren. Relationale Daten müssen strukturiert und getagged werden, dieses kann innerhalb oder außerhalb der relationalen Maschine geschehen. In diesem Dokument wurden verschiedene Ansätze vorgestellt und vor dem Hintergrund der Effizienz diskutiert und beurteilt. Die vorgestellten Ansätze fordern keine Neuimplementierung von Systemen, sondern bauen das bestehende SQL – System mit Hilfe von erweiterten Funktionen aus, Applikationen und werden APIs können weiterverwendet. Die Messungen dieses Experiments haben ergeben, daß es effizienter ist, alle Prozesse innerhalb der Maschine ablaufen zu lassen, und daß der outer union Ansatz sich gegenüber den anderen Alternativen als effizientester und stabilster durchgesetzt hat. Die Weiterentwicklung von Parallelmaschinen, neue Laufzeitoperatoren innerhalb der relationalen Maschine und Techniken der effizienten Speicherverwaltung können eine Steigerungen der Effizienz bei outer union Ansätzen bringen. Es ist desweiteren notwendig den tagger-Algorithmus derart zu modellieren, daß verschachtelte Strukturen von beliebiger Tiefe kein Problem mehr darstellen. Den outer union Ansatz könnte man eventuell so verändern, daß Informationen von ungebundenen Hierachien aufgefaßt werden können unter Verwendung von Schlüsselspalten. 7. References www.acm.org/sigmod/vldb/conf/2000/P065.pdf