Java/JDBC Implementierung und Auswertung von Algorithmen zur Format-Optimierung von Multimedia-Datenbanken Diplomarbeit von Stefan Holland im Studiengang Diplom-Wirtschaftsmathematik an der Universitat Augsburg Erstgutachter: Prof. Dr. Werner Kieling Zweitgutachter: Prof. Dr. Bernhard Moller Betreuer: Matthias Wagner Augsburg, Juli 1999 Vorwort Am Ende des 20. Jahrhunderts be ndet sich die Gesellschaft im Umbruch von der Industrie- zur Informationsgesellschaft. Zu dieser Entwicklung tragt das World-Wide-Web (WWW), der weltweite Informationsdienst im Internet, mageblich bei. Firmen konnen sich im WWW prasentieren und so um Kunden werben, Versandhauser ermoglichen Home-Shopping, indem sie ganze Kataloge im Netz bereitstellen, Forscher konnen Publikationen im Internet veroentlichen und so einem breiten Leserkreis zur Verfugung stellen u.v.m. Wesentlich fur die Prasentation im Internet ist eine u bersichtliche Darstellung dieser Informationsut. Dies wird zum einen durch sogenannte Hyperlinks (Verweise auf andere Textstellen bzw. Dokumente) erreicht, so da eine u bersichtliche Gliederung das Lesen erleichtert. Zum anderen erlaubt der Einsatz multimedialer Hilfsmittel (Bilder, Audio- und Videodokumente) eine optisch und akustisch sehr ansprechende Darstellung von Information. Man denke hier beispielsweise an einen Reiseveranstalter, der sein Angebot online zur Verfugung stellt: Erst die Abbildung eines Reiseziels ermoglicht dem Kunden eine genaue Vorstellung seines potentiellen Urlaubsorts. Da die Benutzer unterschiedliche Browser, Viewer und Player zum Anzeigen bzw. Abspielen von Multimediadokumenten verwenden, sollten diese in verschiedenen Formaten (z.B. GIF, JPG und Postscript bei Bildern, AUX und WAV bei Audiodaten) verfugbar sein. Ebenso machen die Heterogenitat der verwendeten Netzwerkhardware (LAN, WAN, ISDN, Modem u.a.) und die damit verbundenen unterschiedlichen Datenubertragungsraten auch wahlbare Qualitatsstufen sinnvoll, so da durch eine geringere Bildauosung bzw. Samplingrate auch bei niederen Transferraten die Ladezeit klein bleibt. Wird nun ein bestimmtes Format in einer bestimmten Qualitat hau g angefordert, sollten die Dokumente eventuell auch in diesem gespeichert werden und nicht erst bei der Anfrage aus dem Original konvertiert werden. Hierbei mu allerdings genau zwischen Rechenersparnis und Festplattenbedarf abgewagt werden. W. Kieling, W. Kowarschick und G. Kostler haben in KKK97] einen Algorithmus vorgestellt, der diesen Proze automatisiert, Peter Rieger hat eine erste prototypische Implementierung vorgenommen (Rie97]). In dieser Diplomarbeit wird zum Algorithmus aus KKK97] eine Variante mit erheblich geringerer Komplexitat vorgestellt, die dafur allerdings bestimmte Anforderungen an das Konvertierungstool stellt (siehe Kapitel 2). Auch werden die Kostenfunktionen erweitert, so da Speicher- und Rechenaufwand moglichst gut an die Realitat angepat werden konnen. Im Gegensatz zu Rie97] beruck- ii sichtigt hier die Implementierung zusatzlich zu den Formaten auch verschiedene Qualitatsstufen. Danksagungen Ich bedanke mich bei Herrn Prof. Dr. W. Kieling und seinen Mitarbeitern am Lehrstuhl fur Datenbanken und Informationssysteme fur die umfangreiche fachliche Unterstutzung, die Bereitstellung neuester Hard- und Software und die freundliche Beratung bei jeder Art von Problemen. Besonderer Dank gilt meinem Betreuer Herrn Matthias Wagner, der mich in allen Belangen der Diplomarbeit hervorragend unterstutzte und dadurch mageblich zum Gelingen beigetragen hat. Dank schulde ich auch Herrn Thorsten Ehm, der auf nahezu alle Java-Fragen eine Antwort wute. Herzlich bedanke ich mich auch bei Frau Gudrun Bauer, Herrn Stefan Fischer und Herrn Jurgen Vogel, die die Arbeit korrektur gelesen haben. Schlielich sei auch meinen Kollegen im Datenbankraum fur die gute Zusammenarbeit gedankt. Inhaltsverzeichnis 1. Einleitung 1 2. Optimierungsalgorithmen 7 1.1. Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2. Die DB2-Extender . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3. Eine Beispielanwendung . . . . . . . . . . . . . . . . . . . . . . . 2.1. 2.2. 2.3. 2.4. Der Basisalgorithmus . . . . . . . . Modi kation des Basisalgorithmus Kostenfunktionen . . . . . . . . . . Modi kation der Kostenfunktionen 2.4.1. Speicherkosten . . . . . . . 2.4.2. Zugriskosten . . . . . . . . 2.5. Verbesserung der Laufzeit . . . . . 2.6. Aktualitat der Daten . . . . . . . . 3. Testszenarien 3.1. 3.2. 3.3. 3.4. 3.5. 3.6. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vereinbarungen und Darstellung . . . . . . . Die Benutzeroberache . . . . . . . . . . . . . Kostenbewertung des Speicherbedarfs . . . . Berechnung der Zugriskosten . . . . . . . . . Reduzierung der Rechenzeit . . . . . . . . . . Ausfuhrliche Beispiele . . . . . . . . . . . . . 3.6.1. Anfragen an eine Heraldik-Datenbank 3.6.2. Abfragen von Aktiencharts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 2 4 7 9 11 12 13 13 14 15 17 17 19 20 23 25 27 27 35 Inhaltsverzeichnis iv 4. Implementierung 42 4.1. Java und die Datenbankschnittstelle JDBC 4.2. Das Datenmodell . . . . . . . . . . . . . . . 4.3. Die Implementierung der Klassen . . . . . . 4.3.1. Die Klasse Attribut . . . . . . . . . 4.3.2. Die Klasse Optimization . . . . . . . 4.3.3. Die Klasse Opti . . . . . . . . . . . . 4.4. SQL-Fehler und Java-Ausnahmen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 44 46 46 47 52 53 5. Kritische Anmerkungen zu den DB2-Extendern 55 6. Resumee und Ausblick 57 A. Shell-Skripte 59 B. Programmcode 63 A.1. Anlegen der Tabellen . . . . . . . . . . . . . . . . . . . . . . . . . 59 A.2. Einfugen der Bildinformation (gekurzt) . . . . . . . . . . . . . . 61 A.3. Einfugen der Bilder (gekurzt) . . . . . . . . . . . . . . . . . . . . 62 B.1. Die Webseite . . . . . . . . . B.2. Das CGI-Programm . . . . . B.3. Java und JDBC Programme . B.3.1. Attribut.java . . . . B.3.2. Optimization.java . Literaturverzeichnis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 65 68 69 70 91 1. Einleitung 1.1. Motivation Seit ihrer Einfuhrung in den 60er Jahren haben sich Datenbanksysteme (DBS) zu einer Querschnittstechnologie in den verschiedensten Anwendungsbereichen etabliert, z.B.: Personal- und Kundenverwaltung von U Bestandserfassung im Bibliothekswesen Fahrplanorganisation von Verkehrsbetri ♦ ♦ ♦ Dabei sind die Standarddatentypen (Integer, Char, u.a.) nicht fur alle Anwendungen ausreichend, beispielsweise konnte man in der Personaldatei eines Mitarbeiters zusatzlich zu Name, Vorname, Postleitzahl und Wohnort auch Informationen in multimedialer Form speichern, wie z.B. Photo und Stimmprobe. Auch Bibliotheken konnten zusatzlich zu Titel, Autor und Verlag auch Bilder von Verfasser und Buchumschlag speichern. Im SQL92-Standard steht dafur der Datentyp Blob zur Verfugung, der Multimediadokumente mit 2 Gigabyte Maximalgroe in binarer Form aufnehmen kann. Die moglichen Operationen sind aber leider recht durftig: ♦ ugen, Loschen und A ndern eines Blobs ♦ ♦ ange eines Blobs ♦ Einf Test auf NULL Ausgabe der L Selektion eines Blobs, bei Bedarf mit A Fur Multimediadokumente waren aber zusatzliche Informationen wunschenswert, wie z.B.: ♦ ♦ ange einer Audio- oder Videosequenz osung (Bilder)das verwendete Format und die verwen die L 1.2 Die DB2-Extender 2 Insbesondere bei Bildern waren zusatzlich Formatkonvertierungen und Skalierungen wunschenswert, um die Dokumente moglichst vielseitig verwenden zu konnen (GIF- und JPG-Bilder mittlerer Qualitat fur Prasentationen im Internet, PS- und EPS-Bilder hoher Auosung zum Drucken, PCX und BMP zum Weiterverarbeiten unter Microsoft Windows u.v.m.). Das Tool DB2-Extender1 von IBM erlaubt dies fur DB21 -Datenbanken und ermoglicht eine Ad-hoc-Formatkonvertierung und -Skalierung bei einer entsprechenden Anfrage. Falls nun ein bestimmtes Format in einer bestimmten Auflosung hau g angefragt wird, ist es eventuell sinnvoll, die Bilder auch in diesem Format mit der entsprechenden Auosung physikalisch zu speichern, um den Rechner durch weniger Konvertierungen zu entlasten. Andererseits steht der Rechenersparnis ein erhohter Festplattenbedarf gegenuber, so da eine zusatzliche physikalische Speicherung der Bilder stets genau abgewogen werden sollte. Im Kapitel 2 werden Algorithmen vorgestellt, die diesen Vorgang automatisieren. Die Testszenarien im Kapitel 3 veranschaulichen den Nutzen der Optimierung und beschreiben die Auswirkungen der einzelnen Parameter. Kapitel 4 stellt die Programmiersprache Java mit der Datenbankschnittstelle JDBC und die wesentlichen Aspekte der Implementierung vor. Im Kapitel 5 wird kurz auf typische Probleme beim Einsatz der DB2-Extender eingegangen. Resumee und Ausblick im Kapitel 6 beschlieen die Diplomarbeit. 1.2. Die DB2-Extender In DB2-Datenbanken kann der Benutzer die vorde nierten Datentypen (Char, Integer, Blob, ...) und Funktionen (count, max, avg, ...) um sog. User De ned Types (UDTs) und User De ned Functions (UDFs) erweitern. Die DB2Extender stellen solche UDTs und UDFs zur Verwaltung von Multimediadatenbanken zur Verfugung. Die Datentypen heien ♦ DB2Image ♦ DB2Audio ♦ DB2Video und werden als Varchar(250) de niert. Sie beinhalten naturlich nicht die eigentlichen Dokumente, sondern lediglich Verweise auf von den DB2-Extendern intern angelegte Tabellen (falls die Dokumente als Blobs gespeichert sind) oder auf Dateien (falls die Dokumente im Filesystem abgelegt sind). Eine Vielzahl von Funktionen ermoglicht eine umfangreiche Bearbeitung von Multimediadokumenten. Die wichtigsten UDFs fur Bilder lauten: 1 DB2r und DB2r Extenders sind eingetragene Warenzeichen der International Business Machines Corporation (IBM) 1.2 Die DB2-Extender Funktion content db2image format size 3 Beschreibung liefert das Bild als Blob oder Datei zuruck, einschlielich Formatkonvertierung und Skalierung speichert, konvertiert und skaliert Bilder gibt das Format zuruck berechnet die Bildgroe in Byte Zusatzlich gibt es noch etliche Funktionen zur bildinhaltlichen Recherche, auf die hier nicht naher eingegangen wird. Folgende Tabelle stellt die von den DB2-Extendern unterstutzten Bildformate vor: Format BMP EPS EP2 GIF IMG IPS JPG PCX PGM PS PSC PS2 TIF YUV Beschreibung OS/2 - Microsoft Windows bitmap verkapseltes Postscript verkapseltes Postscript, Level 2 (Farbe) Compuserve GIF89a (einschlielich animierte GIFs) und GIF87 IOCA image Brooktrout FAX Dateien JPEG (3) PC paint Dateien Portable grey map Postscript komprimiertes Postscript Postscript, Level 2 (Farbe) TIFF 5.0 digitales Video fur YUV Fur Konvertierungen zwischen diesen Formaten gilt: 1. Die Postscript-Formate (EPS, EP2, PS, PSC, PS2) konnen nicht Quellformat einer Konvertierung sein. 2. Ansonsten sind beliebige Formatumwandlungen moglich. Beispiel nicht erlaubt erlaubt GIF ! BMP TIF ! PS PS ! TIF GIF ! JPG TIF ! PCX PS ! EPS Bei einer Formatkonvertierung ist auch gleichzeitig eine Skalierung der Bilder moglich. Die DB2-Extender stellen zusatzlich das nicht sehr gangige Format IM (Beschreibung lt. Dokumentation in Ext]: PS/2 Audio Video Connection (AVC)) 1.3 Eine Beispielanwendung 4 zur Verfugung. Bilder in diesem Format konnen gelesen werden, Konvertierungen zu IM sind aber nicht gestattet. Deshalb wird dieses Format in dieser Arbeit nicht verwendet. Weitere Einschrankungen und Probleme bei der Verwendung der DB2-Extender werden im Kapitel 5 beschrieben. 1.3. Eine Beispielanwendung Die Internet-Seite2 in Abbildung 1.1 zeigt beispielhaft die Verwendung der DB2Extender. Abbildung 1.1.: Bildauswahl Die hier aufgelisteten Bildbeschreibungen werden aus einer Tabelle einer DB22 http://heron.informatik.uni-augsburg.de/db2www-bin/db2www/da1 net/input 1.3 Eine Beispielanwendung 5 Datenbank gelesen. Nach dem Anklicken des gewunschten Bildes kann der Benutzer Format und Skalierung auswahlen. Abbildung 1.2.: Auswahl von Format und Skalierung Ein Skalierungsfaktor von 100% gibt das Bild in seiner ursprunglichen Groe zuruck, ansonsten wird es entsprechend der Prozentangabe verkleinert. Man beachte, da dadurch auch die Auosung gewahlt wird, denn wird das Originalbild auf z.B. 50% skaliert, so fallt in jeder Dimension die Halfte der Punkte weg. Wird dieses Bild danach manuell auf die Originalgroe vergroert, so hat es im Vergleich zum ursprunglichen Bild nur noch die halbe Auosung. Aus diesem Grund werden in dieser Arbeit die Begrie "Qualitat\, "Skalierung\ und "Auosung\ synonym verwendet. Ein Klick auf den "Submit\-Button schickt die Anfrage ab. Der Web-Server leitet sie an den Datenbankserver weiter. Da in dieser Anwendung die Bilder im GIF-Format in der Datenbank vorliegen, kann das gewunschte Bild ohne 1.3 Eine Beispielanwendung 6 Konvertierung zuruckgeliefert werden. Abbildung 1.3.: Anfrageergebnis ohne Konvertierung Wahlt der Benutzer dagegen das JPG-Format und eine 75%-Skalierung, so wird es aus dem dazugehorenden GIF-Bild konvertiert und gleichzeitig verkleinert. Abbildung 1.4.: Anfrageergebnis mit Konvertierung Fur den Benutzer ist es also vollkommen transparent, ob das angefragte Bild tatsachlich im gewunschten Format vorliegt oder erst konvertiert werden mu. Die einzelnen Anfragen werden in einer Tabelle registriert und ermoglichen so dem Administrator eine Optimierung der Multimediadatenbank: Aufgrund dieser statistischen Daten kann er entscheiden, welche Formate bzw. Qualitatsstufen zukunftig in der Datenbank physikalisch gespeichert werden und welche aus bestehenden Bildern konvertiert werden. Dazu werden im nachsten Abschnitt geeignete Algorithmen entwickelt. 2. Optimierungsalgorithmen Dieses Kapitel stellt Algorithmen vor, die abhangig vom Anfragepro l die Menge der zu speichernden und der zu konvertierenden Formate bestimmen. Der zunachst vorgestellte Basisalgorithmus aus KKK97] ist unabhangig von der Menge der moglichen Konvertierungen anwendbar. Die schnellere Variante aus Abschnitt 2.2 eignet sich fur den Fall, da alle Bilder zunachst in einem einzigen Referenzformat vorliegen und auch alle anderen unterstutzten Formate sich daraus berechnen lassen. Die DB2-Extender erfullen diese Voraussetzungen fur verschiedene Referenzformate (vgl. Abschnitt 1.2) und eignen sich damit fur den 2. Algorithmus. 2.1. Der Basisalgorithmus Zunachst werden die primar gespeicherten Bilder betrachtet. Denition 2.1 (Referenzbilder, Referenzformat) Die ursprunglich in der Datenbank vorliegenden Bilder heien Referenzbilder, ihre Formate werden als Referenzformate bezeichnet. Diese Bilder sollen nun nicht nur in verschiedenen Formaten, sondern auch in mehreren Qualitatsstufen verfugbar sein. Denition 2.2 (Attribut) Ein Attribut A besteht aus einem Tupel (Format, Qualitatsstufe). Dabei wird die Qualitat prozentual zur Grundauosung angegeben, die durch die Referenzbilder festgelegt ist. A bezeichnet eine Menge von Attributen, Aphys ist die Menge der zu speichernden Attribute und Acomp sind die aus Aphys zu konvertierenden Attribute, wobei Acomp = A n Aphys gilt. Um die Notation zu vereinfachen werden Attribute stets mit TIF100 statt (TIF, 100%), GIF50 statt (GIF, 50%) usw. bezeichnet. Denition 2.3 (funktionale Abhangigkeit) A sei ein Attribut, X eine Menge von Attributen und f eine Funktion. Dann heit fC (A = f (X )) funktionale Abhangigkeit. Hierbei ist A Kopfattribut und X sind Rumpfattribute von fC . 2.1 Der Basisalgorithmus 8 Falls nun f eine Konvertierungsfunktion ist, so kann das Attribut A damit aus X berechnet werden. Verwendet man die DB2-Extender als Konvertierungstool, so ist X stets einelementig (z.B. X = fB g fur ein Attribut B ). Die funktionale Abhangigkeit lautet in diesem Fall fC (A = f (B )). Denition 2.4 (funktionale Basis) Sei F eine Menge funktionaler Abhangigkeiten. Dann heit Fcomp 2 F genau dann funktionale Basis, wenn gilt: 1. Kein Attribut hangt von sich selbst funktional ab (weder direkt noch transitiv). 2. Jedes A 2 A ist hochstens Kopfattribut einer funktionalen Abhangigkeit fC 2 Fcomp . Hierbei verhindert 1., da ein Attribut zyklisch von sich selbst abhangt, und sorgt 2. dafur, da die Berechnung von A 2 Acomp eindeutig ist. Denition 2.5 (optimale funktionale Basis) Sei cost eine Kostenfunktion. Eine funktionale Basis Fopt heit genau dann optimal, wenn cost(Fopt ) = minfcost(Fcomp)j Fcomp ist funktionale Basis g Ziel der Optimierung ist es also, eine bzgl. einer Kostenfunktion beste funktionale Basis zu bestimmen. Daraus ergibt sich Acomp als Menge der Kopfattribute von Fopt und damit Aphys = A n Acomp. Algorithmus 2.1 Attributmenge A Menge F der moglichen Konvertierungen Kostenfunktion cost Initialisierung: Fopt := min := cost() FOR Fcomp F WHERE Fcomp is functional base DO IF cost(Fcomp ) < min THEN min := cost(Fcomp) Fopt := Fcomp FI OD Fopt min Ausgabe: Eingabe: Geeignete Kostenfunktionen werden im Abschnitt 2.3 vorgestellt. Eine detaillierte theoretische Betrachtung ndet sich in KKK97], eine Implementierung dieser Optimierung erfolgt in Rie97]. 2.2 Modikation des Basisalgorithmus 9 2.2. Modikation des Basisalgorithmus Die DB2-Extender erlauben nahezu beliebige Konvertierungen zwischen den Attributen, d.h. bei n Attributen gibt es fast n2 funktionale Abhangigkeiten. Fur diesen Fall hat obiger Algorithmus lt. KKK97] eine worst-case Komplexitat von O(n2 (n + 1)n ). Der folgende Algorithmus ermoglicht eine Laufzeitverkurzung, indem er nicht die Potenzmenge der funktionalen Abhangigkeiten, sondern die der Attribute durchlauft. Algorithmus 2.2 Attributmenge A Kostenfunktion cost Initialisierung: Aphys = A Acomp = min = cost(Aphys Acomp) FOR A~phys A DO A~comp = A n A~phys IF cost(A~phys A~comp ) < min THEN Aphys = A~phys Acomp = A~comp min = cost(A~phys A~comp) FI OD Ausgabe: Aphys Acomp cost Eingabe: Dieser Algorithmus wahlt aus der Attributmenge A die zu speichernden Attribute direkt aus. Dabei wird ebenso wie im Algorithmus 2.1 eine Kostenfunktion verwendet, auf die noch genauer eingegangen wird. Damit dem Benutzer stets alle unterstutzten Formate zur Verfugung stehen, werden folgende Voraussetzungen verlangt: 1. Alle Bilder liegen vor der ersten Optimierung in einem einheitlichen Referenzformat vor. 2. Samtliche zu unterstutzenden Attribute konnen aus diesem konvertiert werden. Der 1. Punkt ist keine groe Einschrankung, denn in vielen Fallen werden die Bilder bereits im gleichen Format vorliegen (z.B. bei eingescannten Bildern). Falls jedoch unterschiedliche Formate verwendet wurden, so konnen die Bilder mit den DB2-Extendern leicht auf ein einheitliches Format konvertiert werden. Die 100% Qualitatsstufe des Referenzformats sollte nicht in die Attributmenge A der Optimierung aufgenommen werden, damit diese nie geloscht wird. 2.2 Modikation des Basisalgorithmus 10 Die Erfullbarkeit der 2. Voraussetzung hangt von der Machtigkeit des Konvertierungstools ab. Bei den DB2-Extendern sind folgende Referenzformate moglich (vgl. Abschnitt 1.2): BMP, GIF, IMG, IPS, JPG,PCX, PGM, TIF, YUV Ebenso wie beim Basisalgorithmus mu auch hier gewahrleistet werden, da fur jedes A 2 Acomp die Konvertierungsfunktion eindeutig ist. Fur die DB2Extender garantieren dies folgende Regeln fur die Wahl des Quellattributs der Konvertierung: 1. Sei A ein Attribut, dessen Format weder EPS, EP2, PS, PSC noch PS2 ist. Falls nun zu diesem A ein Attribut in Aphys existiert, das gleiches Format, aber bessere Auosung hat, so wahle dieses. Gibt es davon mehrere, so wahle dasjenige, dessen Auosung der von A am nachsten ist. 2. Ansonsten verwende das Referenzformat als Quellattribut. Bilder in Postscript-Formaten konnen von den DB2-Extendern nicht skaliert werden und mussen deshalb stets aus der Referenzbildern konvertiert werden, sofern sie nicht in der Datenbank prasent sind. Beispiel Sei TIF das Referenzformat, GIF, JPG, PCX und PS die weiteren verfugbaren Formate und die moglichen Qualitatsstufen 100%, 50% und 25%. Eine Optimierung habe Aphys = fGIF100, GIF50, JPG50, PCX25, PS100g ergeben. Die Attribute werden dann gema dem Graphen aus Abbildung 2.1 erzeugt. Naturlich mussen nur an den durchgezogenen Pfeilen Konvertierungen durchgefuhrt werden. ; GIF100 ? ; GIF100 ; ; ; GIF50 GIF50 ? ; ? JPG50 ; GIF50 GIF25 ? ; JPG50 ; ; JPG50 ? ; PCX25 PS100 ; JPG25 ? ; ? ; 9 ; ) TIF100 ; ? ; j ; JPG100 PCX100 PCX50 PS50 q ; PS25 Abbildung 2.1.: Beispiel zulassiger Konvertierungen Komplexitat ; PCX25 PS100 Ist n die Anzahl der Attribute in A, dann hat deren Potenzmenge die Machtigkeit 2n . Falls nun der Aufwand der Kostenberechnung quadratisch in n ist (siehe Seite 12), so hat der Algorithmus eine Komplexitat von O(n2 2n ). 2.3 Kostenfunktionen 11 Folgende Tabelle vergleicht die Laufzeit beider Algorithmen, falls n Attribute vorliegen und das Konvertierungs-Tool beliebige Konvertierungen zwischen den Attributen erlaubt: n 3 4 5 7 9 11 13 15 20 25 30 Algorithmus 2.1 Algorithmus 2.2 n2 (n + 1)n n 2 2n 576 72 10000 256 194400 800 8 1:03 10 6272 8:10 1010 41472 8:99 1013 247808 1:34 1017 1384448 2:59 1020 7372800 29 1:11 10 4:19 108 38 1:48 10 2:10 1010 47 4:96 10 9:66 1011 2.3. Kostenfunktionen Die Gute der Optimierung hangt entscheidend von der Wahl der Kostenfunktion ab. Denition 2.6 (Kostenfunktion) cost(Aphys Acomp) := (1 ; z ) store cost(Aphys) +z acc cost(Aphys Acomp) Die Kosten setzen sich also aus Speicher- und Zugriskosten zusammen, wobei z 2 0 1] ein Gewichtungsparameter ist. Diese Parameterisierung der Kostenfunktion entspricht zwar dem Algorithmus 2.2, kann aber ebenso im Basisalgorithmus verwendet werden, da ja Fcomp die Attributmenge in Acomp und Aphys zerlegt, so da cost(Fcomp ) = cost(Aphys Acomp) gilt. Denition 2.7 (Speicherkosten) P store cost(Aphys) := cS A2Aphys avg size(A) Die Speicherkosten sind also proportional zur Summe der durchschnittlichen Attributgroen. 2.4 Modikation der Kostenfunktionen 12 Denition 2.8 (Zugriskosten) P acc cost(Aphys Acomp ) := A2A avg acc(A) acc cost(A) wobei avg acc(A) die durchschnittliche Zugrisrate ist. Die Zugriskosten summieren sich also aus den attributbezogenen Zugriskosten, gewichtet mit der durchschnittlichen Zugrisrate. Denition 2.9 (Zugriskosten fur ein Attribut) acc cost(A) := cA avg size(A) falls A 2 Aphys comp cost(B A) + acc cost(B ) falls A 2 Acomp wobei comp cost(B A) die Rechenkosten fur die Konvertierung des Attributs A aus dem Attribut B 2 Aphysist. Fur die Wahl des Quellattributs B konnen beispielsweise die auf Seite 10 vorgestellten Regeln verwendet werden. Im Algorithmus 2.1 wird die verwendete Konvertierung und damit das Quellattribut durch die Menge Fcomp festgelegt. Denition 2.10 (Konvertierungskosten) comp cost(B A) := cC avg conv time(B A) wobei cC ein Skalierungsparameter und avg conv time(B A) die durchschnittliche Dauer fur eine Konvertierung B ! A ist. Falls die durchschnittliche Rechenzeit fur eine Formatumwandlung nicht bekannt ist, sollte sie aus statistischen Daten ermittelt werden. Komplexitat der Kostenfunktionen Die Berechnungen gema De nitionen 2.6 - 2.8 und 2.10 haben hochstens linearen Aufwand (bzgl. der Anzahl der Attribute), sofern die benotigten statistischen Daten bereits bekannt sind. Bei den Zugriskosten fur ein Attribut mu fur jedes A 2 Acomp das entsprechende Quellattribut gesucht werden. Dazu durchlauft Algorithmus 2.1 die Menge Fcomp und Algorithmus 2.2 die Menge Aphys, so da sich der Rechenaufwand fur die Kosten durch O(n jFj) bzw. O(n2 ) nach oben abschatzen lat. Naturlich kann man die Ermittlung des Quellattributs auch ezienter implementieren (z.B. durch Verwendung einer Hashtabelle), allerdings rechtfertigt die schnellere Suche nicht unbedingt den zusatzlichen Verwaltungsaufwand (v.a. bei kleinen Mengen). 2.4. Modikation der Kostenfunktionen In diesem Abschnitt werden verbesserte Kostenfunktionen vorgestellt, die durch zusatzliche Parameter (de-)aktiviert und eingestellt werden konnen. 2.4 Modikation der Kostenfunktionen 13 2.4.1. Speicherkosten Die Kosten fur die persistente Speicherung der Bilder entstehen durch die Belegung von Speicherplatz auf Datentragern. De nition 2.7 erfat dies nur unzureichend, da hier nur die durchschnittliche Bildgroe relevant ist. Besser ware es, hier den tatsachlichen Speicherbedarf zu berucksichtigen. Denition 2.11 (Speicherkosten (2)) P store cost(Aphys) := cS A2Aphys number of images avg size(A) wobei number of images die Anzahl der Bilder ist. Dieser Ansatz modelliert also die Speicherkosten als proportional zu dem belegten Speicherplatz. Da die Kosten moglicherweise sprunghaft beim Vergroern eines Tablespace oder beim Kauf eines neuen Datentragers anfallen, konnen sie durch eine auf den Speicherbedarf angewendeten Treppenfunktion F berechnet werden. Denition 2.12 (Speicherkosten (3)) P store cost(Aphys) := F A2Aphys number of images avg size(A) wobei F eine geeignete Treppenfunktion ist. Beispiel Bei Verwendung von 3 Festplatten, wobei die erste 500 MB Kapazitat hat und die Kosten 150 betragen, die zweite gleiche Kapazitat hat jedoch nur 100 kostet und die dritte eine 1-GB-Platte zu 150 ist, so konnte die Treppenfunktion F beispielsweise folgende Form habe: 8 x = 0 > < 0150 falls falls 0 < 500 F (x) = > 250 falls 500 < xx 1000 : 400 falls 1000 < x 2000 wobei x der tatsachliche Speicherbedarf in MB ist. 2.4.2. Zugriskosten Gema De nition 2.8 werden die Kosten fur ein Attribut mit der durchschnittlichen Zugrisrate gewichtet. Dies bedeutet aber, da die Anfragepro le Anfrageprol 1 Attribut Anzahl der Anfragen GIF100 1 JPG100 2 Anfrageprol 2 Attribut Anzahl der Anfragen GIF100 100 JPG100 200 2.5 Verbesserung der Laufzeit 14 die gleichen Zugriskosten haben konnen. Ist dies nicht erwunscht, so kann als Gewicht die tatsachliche Zahl der Anfragen fur ein Attribut verwendet werden. Denition 2.13 (Zugriskosten (2)) P acc cost(Aphys Acomp) := A2A total acc(A) acc cost(A) wobei total acc(A) die Anzahl der Anfragen fur das Attribut A ist. Dabei ist allerdings zu beachten, da dadurch die Zugriskosten sehr gro werden konnen, so da u.U. eine Anpassung der anderen Parameter (v.a. z , vgl. De nition 2.6) notwendig wird. 2.5. Verbesserung der Laufzeit Algorithmus 2.2 hat exponentielle Komplexitat bezuglich der Anzahl der Attribute. Aus diesem Grund sollte der Suchraum klein gehalten werden, indem beispielsweise nur die Attribute in die Optimierung eingehen, die tatsachlich angefragt worden sind. Dies kann noch weiter verfeinert werden, indem davon nur die berucksichtigt werden, die mehr als p-mal angefordert wurden. Aus diesen wahlt dann der Algorithmus die zu speichernden Attribute aus. Dieses Vorgehen ermoglicht es damit auch, dem Benutzer eine groere Anzahl an Qualitatsstufen anzubieten, ohne da sich die Laufzeit des Algorithmus wesentlich verschlechtert. Beispiel Gegeben sei folgendes Anfragepro l: Attribut Anzahl der Anfragen GIF100 80 GIF75 3 GIF50 75 GIF25 7 PS100 110 PS50 12 PCX100 40 PCX75 8 JPG100 60 JPG50 2 Dann vergleicht folgende Tabelle die Laufzeiten bei Variation des oben beschriebenen Parameters p: 2.6 Aktualitat der Daten 15 p ausge lterte Attribute 1 2 3 5 10 15 JPG50 JPG50, GIF75 JPG50, GIF75, GIF25, PCX75 JPG50, GIF75, GIF25, PCX75, PS50 Anzahl n relevanter Attribute 10 10 9 8 6 5 O(n) = n2 2n 102400 102400 41472 16384 2304 800 Dies ermoglicht also eine Aufteilung in "wichtige\ und "unwichtige\ Attribute. 2.6. Aktualitat der Daten Abhangig vom aktuellen Query-Pro l liefert der Algorithmus 2.2 die Menge der zu speichernden Attribute als Ergebnis. Falls nun bis zur nachsten Optimierung keine Anfragen an ein Attribut dieser Menge gestellt werden, schlagt der Algorithmus u.U. vor, dieses Attribut zu loschen. Dieses Verhalten kann zu einem unnotig hau gen Speichern und Loschen von Attributen fuhren. Um dies zu verhindern, sollten auch altere Querys in die Optimierung eingehen. Um andererseits aber auch die Aktualitat weiterhin gewahrleisten zu konnen, sollte jede Anfrage nur fur eine begrenzte Anzahl von Optimierungen relevant sein. In der Implementierung fuhrt dies zur Einfuhrung eines neuen Parameters q, der die Anzahl der Optimierungen angibt, fur die im Query-Pro l registrierte Anfragen verwendet werden sollen. Beispiel Folgendes Szenario (Referenzformat z.B. TIF, 100 Bilder) ist denkbar, falls jede Anfrage fur nur eine Optimierung verwendet wird (q = 1): Lauf 1 2 3 4 5 6 7 8 Anfragepro l 50 GIF100 50 JPG100 50 GIF100 50 JPG100 50 GIF100 50 JPG100 50 GIF100 50 JPG100 Aphys GIF100 JPG100 GIF100 JPG100 GIF100 JPG100 GIF100 JPG100 Werden die Anfragen fur zwei Optimierungslaufe verwendet (q = 2), so ist folgender Ablauf moglich: 2.6 Aktualitat der Daten Lauf 1 2 3 4 5 6 7 8 Anfragepro l 50 GIF100 50 JPG100 50 GIF100 50 JPG100 50 GIF100 50 JPG100 50 GIF100 50 JPG100 16 Aphys GIF100 GIF100, JPG100 GIF100, JPG100 GIF100, JPG100 GIF100, JPG100 GIF100, JPG100 GIF100, JPG100 GIF100, JPG100 Nur nach den Laufen 1 und 2 erfolgen A nderungen in Aphys, wahrend im obigen Fall nach jedem Lauf 100 Bilder konvertiert und 100 Bilder geloscht werden mussen. Eine ausfuhrliche Analyse von Testlaufen erfolgt im nachsten Kapitel. 3. Testszenarien Im Kapitel 2 wurden Algorithmen zur Formatoptimierung vorgestellt, die nun an Beispielen getestet und analysiert werden sollen. Dabei wird insbesondere auf Praxisbezug groen Wert gelegt und gezeigt, wie die bereits vorgestellten Parameter mit physikalischen Groen wie Festplattengroe und -kosten, Datentransferrate u.a. zusammenhangen. 3.1. Vereinbarungen und Darstellung Denition 3.1 (Lauf, Szenario) Ein (Optimierungs-)Lauf besteht aus einer Menge von Anfragen gefolgt von einer Optimierung, ein Szenario besteht aus mehreren Laufen. Um auch komplexe Szenarien ubersichtlich darstellen und analysieren zu konnen, werden nicht alle moglichen Formate verwendet. ♦ ♦ Als Anfrageformate werden nur BMP, G eingesetzt. oglichen Skalierungen sind 100%, 75%, 50% und 25%. Die m Da die Testszenarien eine Fulle von Datenmaterial liefern, soll deren Auswertung i.a. graphisch (vgl. Abbildung 3.1) erfolgen. Dafur werden folgende Vereinbarungen getroen: ♦ ♦ ♦ ♦ ♦ Das Anfragepro l wird durch ein gestap wobei die Hohe eines Balkens die Gesamtanzahl der Anfragen eines Laufs wiedergibt. Kosten, Rechenzeiten u.a. werden durch derder Anfraprim aren y-Achse (in Graphiken links) kann die ZahlAn gen abgelesen werden, rechts an der sekundaren y-Achse die Kosten oder Rechenzeiten. Die Einheiten werden soweit m oglich mit angegeben. Die x-Achse ist mit der Nummer der aufe und/oder den physikalisch gespeicherten Attributen beschriftet. 3.1 Vereinbarungen und Darstellung 18 100000 40 35 10000 30 25 number of requests 20 1000 computing_time (log scale, ms) 100 15 10 10 5 1 0 1 2 3 4 5 6 7 8 9 10 run 11 12 13 14 15 16 17 18 19 BMP100 BMP75 BMP50 BMP25 GIF100 GIF75 GIF50 GIF25 JPG100 JPG75 JPG50 JPG25 PCX100 PCX75 PCX50 PCX25 computing_time (q=100) computing_time (q=1) Abbildung 3.1.: Beispielgraphik Die Legendenbeschriftungen stammen direkt aus der Datenbank und werden in der folgenden Tabelle erlautert: Beschriftung number of requests A phys cost store cost acc cost pre opt post opt no opt save all computing time total time Bedeutung Anzahl der Anfragen gespeicherte Attribute Gesamtkosten Speicherkosten Zugriskosten vor der Optimierung nach der Optimierung ohne Optimierung Speicherung aller angefragten Attribute Rechenzeit der Optimierung Gesamtzeit einschl. Aktualisierung der Datenbank Wie aus Abbildung 3.2 ersichtlich, werden verschiedene Formate durch Farben unterschieden. Den Skalierungsfaktoren entsprechen unterschiedliche Helligkeitsstufen. 3.2 Die Benutzeroberache 19 BMP100 BMP75 BMP50 BMP25 GIF100 GIF75 GIF50 GIF25 IPS50 IPS25 1,2 1 0,8 0,6 0,4 0,2 0 IPS100 IPS75 JPG100 JPG75 JPG50 JPG25 PCX100 PCX75 PCX50 PCX25 PS100 PS75 PS50 PS25 TIF100 TIF75 TIF50 TIF25 hallo 1 Abbildung 3.2.: Legende der Attribute 3.2. Die Benutzerober ache Das Programm Scenery.java (zum Ausfuhren wird java Scenery standard eingegeben) stellt eine graphische Oberache zur Verfugung, die die einfache Eingabe der Parameter und des Anfragepro ls ermoglicht. Fur jedes Szenario gibt man die Anzahl der Bilder in der Datenbank, das Referenzformat und die durchschnittliche Bildgroe ein. Ebenso werden die im Kapitel 2 vorgestellten Parameter z, c_s, c_a, c_c, p und q eingestellt. Wird der Schalter use_total_store aktiviert, so verwenden die Speicherkosten den Gesamtspeicherbedarf aller Attribute, ansonsten nur die durchschnittlichen Bildgroen der Attribute (vgl. De nitionen 2.7 und 2.11). Mit use_stepfunction werden das Feld c_s deaktiviert und die Eingabe von Plattengroen und -kosten ermoglicht (De nition 2.12). U ber use_total_access entscheidet man schlielich zwischen durchschnittlicher Zugrisrate und Gesamtzugriszahl (De nitionen 2.8 und 2.13). Im ersten Textfeld wird das Anfragepro l wie im Beispiel (Abbildung 3.3) eingegeben. Dabei wird an jedem senkrechten Strich (|) eine Optimierung durchgefuhrt. Das untere Textfeld gibt Informationen uber den Verlauf des Szenarios aus. Am Ende ndet sich hier fur jede Optimierung eine Auistung der Kosten, die Menge der physikalisch gespeicherten Attribute und die benotigte Rechenzeit. Dies kann ebenso wie die Eingabe gespeichert werden. Auerdem werden diese Daten zur spateren Auswertung auch in der Datenbank erfat. 3.3 Kostenbewertung des Speicherbedarfs 20 Das Programm kann auch mit java Scenery inputfile outputfile gestartet werden. Dabei werden aus inputfile die Eingabedaten (Parameter und Anfragepro l) gelesen und das Ergebnis des Szenarios in die Datei outputfile geschrieben. Dies ermoglicht den Ablauf von Szenarien ohne Benutzerinteraktion, so da sie z.B. auch nachts ausgefuhrt werden konnen. Abbildung 3.3 zeigt die Oberache wahrend eines Szenarios. Abbildung 3.3.: Oberache fur die Testszenarien 3.3. Kostenbewertung des Speicherbedarfs Im Abschnitt 2.3 und 2.4 wurden fur Speicherkosten verschiedene De nitionen vorgestellt, deren praktische Relevanz nun erlautert werden soll. Gema De nition 2.7 ist fur die Speicherkosten lediglich die durchschnittliche Attributgroe ausschlaggebend, d.h. die Anzahl der Bilder in der Datenbank ist irrelevant. Zur Veranschaulichung werden drei Szenarien getestet, die bis auf die Zahl der Bilder vollkommen identisch sind (Abbildung 3.4). Dabei besteht jede Datenbank primar aus 10, 100 oder 200 Bildern im TIF-Format, wobei jedes 3.3 Kostenbewertung des Speicherbedarfs 21 Bild etwa 100 KB gro ist. Als Ergebnis der Optimierungen werden in jedem Szenario die Bilder auch im Attribut TIF50 gespeichert. 12 140 10 120 100 8 80 number 6 of requests 4 store_cost 60 40 2 20 0 0 TIF50 TIF50 TIF50 TIF50 TIF50 TIF50 TIF50 TIF50 TIF50 TIF50 A_phys TIF50 store_cost (10 pictures) store_cost (100 pictures) store_cost (200 pictures) Abbildung 3.4.: Speicherkosten verwenden die durchschnittliche Attributgroe Die Kosten zum Speichern des Referenzformats werden nicht berucksichtigt, da sie stets gleich sind und somit als Konstante die Optimierung nicht beeinussen. Die durchschnittliche Attributgroe der TIF50-Bilder betragt 28074 Byte, so da sich mit c_s=0.005 Speicherkosten von etwa 140 ergeben. Dies ist unabhangig von der Anzahl der Bilder und damit unabhangig vom tatsachlich belegten Speicherplatz. Dieses Problem kann gelost werden, indem man den Parameter c_s erhoht, falls mehr Bilder in der Datenbank sind. Trotzdem bleibt die Wahl von c_s ziemlich willkurlich, insbesondere kann nicht gewahrleistet werden, da die errechneten Speicherkosten den tatsachlichen Speicherbedarf bzw. die Kosten fur die Datentrager wiedergeben. Als mogliche Verbesserung kann man den Schalter use_total_store aktivieren, so da sich die Speicherkosten gema De nition 2.11 als Produkt aus c_s und Gesamtspeicherbedarf (in Byte) zusammensetzen. Damit konnen die DaPF = tentragerkosten direkt berucksichtigt werden: Ein Medienpreis von 10 MB 1 PF (z.B. SCSI-Festplatten) ergibt c_s=0.00001. Damit werden die Spei100000 Byte cherkosten in Pfennig angegeben, andere Einheiten erfordern eine entsprechende A nderung von c_s (z.B. DM: c_s=0.0000001, Euro: c_s=0.000000511). Ein Beispiel be ndet sich unten (Abbildung 3.5). Die Szenarien sind identisch 3.3 Kostenbewertung des Speicherbedarfs 22 mit den vorigen, nur da use_total_store aktiviert und c_s=0.00001 gewahlt PF werden dann die Speicherkosten in wird. Bei einem Medienpreis von 10 MB Pfennig angegeben. 12 60 10 50 8 number of requests 6 40 4 20 2 10 store_cost 30 0 0 TIF50 TIF50 TIF50 TIF50 TIF50 TIF50 TIF50 TIF50 TIF50 TIF50 A_phys TIF50 store_cost (10 pictures) store_cost (100 pictures) store_cost (200 pictures) Abbildung 3.5.: Speicherkosten verwenden die tatsachliche Attributgroe Hier erkennt man deutlich, da die Speicherkosten direkt von der Anzahl der Bilder abhangen und den tatsachlichen Datentragerkosten entsprechen: 200 TIF50Bilder brauchen 200 28074 = 5614800 Byte und damit betragen die Kosten 0:00001 5614800 = 56:148 Pfennig. Da hier die Bilder recht klein sind (ca. 28 KB), sind naturlich auch die Speicherkosten gering. In der Praxis ist auch denkbar, da sich die Kosten sprunghaft verandern, beispielsweise beim Vergroern eines Tablespace oder beim Kauf und Einbau einer neuen Festplatte. Dies kann man modellieren, indem man auf den Speicherbedarf eine Treppenfunktion F anwendet. Fur das Beispiel in Abbildung 3.6 wird F folgendermaen gewahlt: 8 <0 F = : 100 220 Dabei wird x in MB eingegeben. falls x = 0 falls 0 < x 10 falls 10 < x 25 3.4 Berechnung der Zugriskosten 23 In der Oberache wird fur diesen Fall use_stepfunction aktiviert, wodurch das c_s-Feld aus- und die Felder hd_size und hd_cost eingeschaltet werden. Obige Treppenfunktion wird durch hd_size=10,15 und hd_cost=100,120 eingegeben. Bei einem Speicherbedarf groer als 25 MB wird durch eine oder mehrere 15-MB-Blocke mit Kosten zu 120 interpoliert. Das etwas komplexere Beispiel aus Abbildung 3.6 zeigt den moglichen Verlauf der Speicherkosten. 45 40 200 35 30 150 25 number of requests 20 store_cost 100 15 10 50 5 0 0 GIF100 GIF100 GIF100 GIF75 GIF75 GIF75 GIF50 GIF50 GIF25 GIF100 GIF75 GIF50 GIF25 A_phys GIF100 GIF100 GIF100 GIF75 GIF50 GIF25 PCX100 PCX50 PCX50 PCX25 JPG100 JPG75 JPG50 JPG25 GIF75 GIF75 GIF75 GIF50 GIF25 PCX100 PCX75 PCX25 PCX25 JPG100 JPG75 JPG50 JPG25 BMP100 GIF50 GIF50 GIF50 GIF25 PCX100 PCX75 PCX50 JPG100 JPG100 JPG75 JPG50 JPG25 BMP100 BMP75 GIF25 GIF25 GIF25 PCX100 PCX75 PCX50 PCX25 JPG75 JPG75 JPG50 JPG25 BMP100 BMP75 BMP50 PCX100 PCX100 PCX100 PCX75 PCX50 PCX25 JPG100 JPG50 JPG50 JPG25 BMP100 BMP75 BMP50 BMP25 PCX75 PCX75 PCX75 PCX50 PCX25 JPG100 JPG75 JPG25 JPG25 BMP100 BMP75 BMP50 BMP25 BMP100 BMP75 BMP50 BMP25 PCX50 PCX50 PCX25 JPG100 JPG75 JPG50 BMP75 BMP50 BMP25 PCX25 JPG100 JPG75 JPG50 JPG25 BMP100 BMP75 BMP50 BMP25 GIF100 GIF75 GIF50 GIF25 JPG100 JPG75 JPG50 JPG25 PCX100 PCX75 PCX50 PCX25 store_cost Abbildung 3.6.: Speicherkosten als Treppenfunktion Wie in den vorigen Beispielen besteht die Datenbank primar aus 100 TIFBildern zu je 100 KB Groe. Im ersten Lauf wird kein Attribut zusatzlich gespeichert, in den folgenden vier und im dreizehnten Lauf wird nur die 10-MBPlatte gebraucht, andernfalls werden soviele Attribute gespeichert, da dafur mehr als 10 MB benotigt werden. 3.4. Berechnung der Zugriskosten Zunachst werden fur jedes Attribut einzeln die Zugriskosten berechnet. Diese hangen fur physikalisch gespeicherte Attribute von der durchschnittlichen Groe und von der U bertragungsgeschwindigkeit des Datentragers (bei lokalem Zugri) oder des Netzwerks ab. Die Transfergeschwindigkeit kann mit dem 3.4 Berechnung der Zugriskosten 24 Parameter c_a (vgl. De nition 2.9) berucksichtigt werden: U bertragt beispielsB weise die Festplatte die Daten mit 20 MB s = 20000 ms , so kann c_a=0.00005 gewahlt werden, da die durchschnittliche Bildgroe in Byte errechnet wird. Die Zugriskosten sind dann in Millisekunden angegeben. Mu das Attribut jedoch erst konvertiert werden, dann summieren sich die Kosten (gema De nition 2.9) aus den Zugriskosten fur das Quellformat und der Konvertierungsdauer. Letztere wird aus statistischen Daten ermittelt und ist in Millisekunden angegeben. Fur obiges c_a kann dann der Skalierungsparameter c_c=1 gew ahlt werden. Sollen die Zugriskosten in anderen Einheiten berechnet werden (z.B. Sekunden), so sind sowohl c_a als auch c_c entsprechend zu verandern. Die Gesamtzugriskosten ergeben sich dann aus der Summe der Zugriskosten fur die Attribute, jeweils gewichtet mit der durchschnittlichen Zugrisrate (vgl. De nition 2.8). Dies kann sinnvoll sein, falls es nicht auf die tatsachliche Zahl der Anfragen pro Attribut ankommt. Andernfalls ware es besser, als Gewicht nicht die Zugrisrate, sondern die tatsachliche Zahl der Anfragen herzunehmen (vgl. De nition 2.13). 70 160 60 140 120 50 100 acc_cost 80 number 40 of requests 30 60 20 40 10 20 0 0 TIF50 TIF50 TIF50 TIF50 TIF50 TIF50 TIF50 TIF50 TIF50 TIF75 TIF75 TIF75 TIF75 TIF75 TIF75 TIF75 TIF75 TIF75 A_phys TIF50 TIF75 acc_cost post_opt (total acc) acc_cost post_opt (avg acc) Abbildung 3.7.: Durchschnittliche Zugrisrate vs. absolute Zugriszahl Dieses Vorgehen liefert insbesondere dann gute Ergebnisse, wenn c_a und c_c gema obigen Vorschlagen gewahlt werden. Dann geben namlich die Gesamtzugriskosten genau die Summe der Ladezeiten aller Anfragen wieder (beispielsweise in Millisekunden). In der Graphik (Abbildung 3.7) wurde c_a=0.00005 und c_c=1 gewahlt. Deut- 3.5 Reduzierung der Rechenzeit 25 lich ist zu erkennen, da bei Verwendung der durchschnittlichen Zugrisraten (dunne Linie) die Kosten unabhangig von der tatsachlichen Zugriszahl sind, wahrend im zweiten Fall die Kosten entsprechend der Anfragezahl steigen. Auerdem konnen die Kosten dann direkt als Zeit (in Millisekunden) fur die Dauer aller Anfragen interpretiert werden (falls die Transferrate 20 MB s betragt). 3.5. Reduzierung der Rechenzeit Werden zu den verschiedenen Formaten auch etliche Qualitatsstufen zur Verfugung gestellt, so gehen u U. sehr viele Attribute in die Optimierung ein. Da der Algorithmus aber exponentielle Laufzeit bzgl. der Zahl der Attribute hat, sollten vielleicht nur die Attribute relevant sein, die mehr als p-mal angefragt worden sind. Wird p=1 gesetzt, so gehen alle angefragten Attribute in die Optimierung ein, fur beispielsweise p=5 nur die, die 5 mal oder ofter verlangt wurden. Dadurch kann erheblich Rechenzeit eingespart werden, wie Abbildung 3.8 verdeutlicht. 1000 40 35 30 100 25 number of requests 20 computing_time (ms, log scale) 15 10 10 5 1 0 1 2 3 4 BMP100 GIF100 PCX100 TIF50 computing_time (p=5) 5 6 7 run BMP75 GIF75 PCX75 TIF25 8 9 10 11 12 13 BMP50 GIF50 TIF75 computing_time (p=1) Abbildung 3.8.: Reduzierung der Rechenzeit Man beachte, da die Rechenzeit in Millisekunden angegeben und die rechte Achse logarithmisch skaliert ist. Der nahezu lineare Anstieg der Kurve fur p=1 bedeutet somit exponentielle Rechenzeit. In jedem Lauf kommen neue Attribute hinzu, wobei die meisten davon weniger als 5 mal angefragt werden. Diese werden im 2. Fall (p=5) herausge ltert, so da hier die Rechenzeit konstant niedrig bleibt. 3.5 Reduzierung der Rechenzeit 26 Die relativ lange Rechenzeit im ersten Optimierungslauf liegt am Just-in-TimeCompiler von Java: Programmfragmente wie die Methoden zur Optimierung werden erst dann compiliert, wenn sie zum erstenmal gebraucht werden. Dies kann verhindert werden, indem der Just-in-Time-Compiler deaktiviert wird. Dazu mu das Programm mit folgender Syntax aufgerufen werden: java -Djava.compiler=NONE Scenery standard Aus Ezienzgrunden sollte dies aber nur in Ausnahmefallen gemacht werden. Das Einfugen und Loschen von Bildern in die Datenbank ist sehr zeitaufwendig und sollte deshalb auf ein Minimum reduziert werden. Falls ein Attribut jedoch nur in jedem zweiten oder dritten Lauf angefragt wird, schlagt der Optimierungsalgorithmus u.U. ein standiges Speichern und Loschen dieses Attributs vor. Um dies zu verhindern, kann mit dem Parameter q die Anzahl der Optimierungen eingestellt werden, fur die ein Attribut verwendet werden soll. Wird beispielsweise ein Bild in GIF100 angefragt und ist q=3, so ist diese Anfrage fur die nachsten drei Optimierungen relevant. A_phys (q=1) GIF100 BMP100 PCX100 GIF100 BMP100 PCX100 GIF100 BMP100 PCX100 GIF100 BMP100 PCX100 GIF100 BMP100 PCX100 12 120000 10 100000 80000 8 total_time (ms) number of requests 6 60000 4 40000 2 20000 0 0 GIF100 GIF100 BMP100 BMP100 BMP100 BMP100 BMP100 BMP100 BMP100 BMP100 BMP100 BMP100 BMP100 BMP100 BMP100 BMP100 GIF100 GIF100 GIF100 GIF100 GIF100 GIF100 GIF100 GIF100 GIF100 GIF100 GIF100 GIF100 GIF100 PCX100 PCX100 PCX100 PCX100 PCX100 PCX100 PCX100 PCX100 PCX100 PCX100 PCX100 PCX100 PCX100 A_phys (q=3) BMP100 GIF100 PCX100 total_time (q=1) total_time (q=3) Abbildung 3.9.: Beispiel mit q=1 und q=3 Abbildung 3.9 zeigt die mogliche Zeitersparnis bei geschickter Wahl von q. Selbst in diesem kleinen Beispiel (100 TIF-Bilder, nur drei angefragte Attribute) lat sich dadurch ab der 4. Optimierung u ber eine Minute Zeit pro Lauf einsparen. 3.6 Ausfuhrliche Beispiele 27 Allerdings sollte q nicht beliebig gro gewahlt werden, da sonst u.U. sehr viele verschiedene Attribute in die Optimierung eingehen und somit der Rechenaufwand wieder ansteigt. Die Abbildung 3.10 verdeutlicht den mit zunehmender Zahl der zu berucksichtigten Attribute exponentiell ansteigenden Rechenaufwand. 100000 40 35 10000 30 25 number of requests 20 1000 computing_time (log scale, ms) 100 15 10 10 5 1 0 1 2 3 4 5 6 7 8 9 10 run 11 12 13 14 15 16 17 18 19 BMP100 BMP75 BMP50 BMP25 GIF100 GIF75 GIF50 GIF25 JPG100 JPG75 JPG50 JPG25 PCX100 PCX75 PCX50 PCX25 computing_time (q=100) computing_time (q=1) Abbildung 3.10.: Beispiel mit q=1 und q=100 Die Wahl der Parameter p und q ist also eine schwerwiegende Entscheidung, die stark von der jeweiligen Anwendung abhangt. In der Praxis haben p=5 und q=2 i.a. recht gute Ergebnisse geliefert. 3.6. Ausfuhrliche Beispiele In diesem Abschnitt sollen praxisnahe Szenarien analysiert werden. 3.6.1. Anfragen an eine Heraldik-Datenbank Der Lehrstuhl fur Datenbanken und Informationssysteme der Universitat Augsburg analysiert im Heron-Projekt (Informationen dazu im Internet1 und in 1 http://heron.informatik.uni-augsburg.de/ 3.6 Ausfuhrliche Beispiele 28 KEUB+ 98]) mittelalterliche Familien- und Amtswappen. Die zugrundeliegenden Abbildungen wurden aus Johann Siebmachers "Wappenbuch\ (Sie56]) eingescannt (Format: TIF, Groe: jeweils 1 MB) und in einer DB2-Datenbank gespeichert. Da die Abbildungen einem breiten Personenkreis zuganglich gemacht werden sollen, kann die Datenbank uber das Internet angefragt werden. Aus diesem Grund werden fur das Anfragepro l des nachfolgenden Szenarios folgende Annahmen getroen: ♦ ♦ ♦ Die angefragten Formate sind GIF und auf dem Browser und PS zum Ausdrucken. GIF- und ahlt,JPG-Bilder werden h au g in niedriger Qualitat ausgew um das Browsen zu beschleunigen nur bei Interesse fur ein bestimmtes Wappen fordert der Benutzer dann bessere Auosungen an. Das da Postscript-Format zum wird nur in der at angefragt, Drucken stets die beste Bildqualitat verwendet wird. Abbildung 3.11.: Einstellungen fur das Heron-Beispiel 3.6 Ausfuhrliche Beispiele 29 Das Anfragepro l kann den Abbildungen 3.11 und 3.12 entnommen werden. Des weiteren wird unterstellt, da in der Datenbank 500 Bilder vorliegen. Die Optimierungsparameter werden gema den Vorschlagen aus den vorherigen Abschnitten eingestellt, d.h. c_s=0.00001, c_a=0.00005, p=5 und q=2. Der Schalter use_total_store wird ebenso wie use_total_access eingeschaltet, dagegen bleibt use_stepfunction deaktiviert. Der Parameter z entscheidet, mit welchem Gewicht die Speicher- bzw. Zugriskosten in die Gesamtkosten eingehen (vgl. De nition 2.6). Die Zugriskosten werden wie in Abschnitt 3.4 in Millisekunden berechnet und mussen monetar bewertet werden, damit sie mit den Speicherkosten verglichen werden konnen. Unterstellt man, da das Warten auf das gewunschte Bild dem Benutzer ArPF so ergibt sich beitszeit kostet und wird diese mit 72 DM h = 0:002 ms angegeben, 0:002 1 z = 1+0:002 0:002. Damit konnen die Gesamtkosten als 100 DM bzw. Pfennig interpretiert werden. Auswertung der Zugriskosten Abbildung 3.12 zeigt die Zugriskosten mit und ohne Optimierung. Dabei bedeutet letzteres, da die Bilder nur im TIF-Format vorliegen und alle anderen konvertiert werden mussen. 2000000 1000 1800000 1600000 800 1400000 1200000 acc_cost 1000000 (ms) 600 number of requests 800000 400 600000 400000 200 200000 0 0 GIF25 GIF25 GIF25 GIF25 GIF25 GIF25 GIF50 GIF50 GIF50 JPG25 JPG25 JPG25 JPG25 GIF50 GIF50 GIF50 A_phys JPG50 JPG50 GIF25 GIF25 GIF25 JPG25 GIF50 JPG50 GIF25 JPG25 GIF50 JPG50 GIF25 JPG25 GIF50 JPG50 GIF25 GIF25 GIF25 GIF25 GIF25 GIF25 JPG25 JPG25 GIF50 GIF50 GIF50 GIF50 JPG50 GIF100 GIF75 GIF50 GIF25 JPG100 JPG75 JPG50 JPG25 PS100 acc_cost post_opt acc_cost no_opt Abbildung 3.12.: Vergleich der Zugriskosten Aufgrund der Wahl der Parameter geben hier die Zugriskosten die Ladezeiten 3.6 Ausfuhrliche Beispiele 30 fur alle Anfragen in Millisekunden an. Damit erklaren sich auch die hohen Zahlen an der rechten Achse. Im ersten Lauf sind die optimalen Zugriskosten sehr gering. Ursache dafur sind die gespeicherten GIF25-Bilder, die aufgrund ihrer geringen Groe kaum Ladezeit benotigen. Die Optimierung ermoglicht eine immense Zeitersparnis, die durch den Unterschied der beiden Kurven deutlich wird. Im Balkendiagramm aus Abbildung 3.13 wird diese Zeitdierenz (in Minuten umgerechet) dargestellt. 14 12 10 8 6 time (min) 4 2 0 1 2 3 4 5 6 7 8 9 run 10 11 12 13 14 15 16 17 saved time (post_opt vs no_opt) Abbildung 3.13.: Absolute Einsparung an Zugriskosten Im funften Lauf werden beispielsweise bei 600 Anfragen (200 GIF25, 150 GIF50, 100 GIF75, 50 GIF100 und 100 JPG25) uber 10 Minuten Zeit eingespart, das entspricht einer Verbesserung von u ber 60 %, wie aus Abbildung 3.14 ersichtlich ist. Im Durchschnitt liegt der prozentuale Zeitgewinn aller 17 Laufe bei uber 50 %, so da sich fur die Endbenutzer eine enorme Ezienzsteigerung bemerkbar macht. 100 80 60 percent 40 20 0 1 2 3 4 5 6 7 8 9 10 run 11 12 13 14 15 16 17 saved time (percent) Abbildung 3.14.: Prozentuale Einsparung an Zugriskosten 3.6 Ausfuhrliche Beispiele 31 Auswertung der Speicherkosten Naturlich ist diese immense Verringerung der Zugriskosten nicht umsonst, vielmehr werden dafur hohere Speicherkosten in Kauf genommen. Deren Entwicklung ist in Abbildung 3.15 dargestellt. Dabei sind nur die von der Optimierung verursachten Speicherkosten angegeben. Wird nicht optimiert, so wird auch kein Attribut zusatzlich gespeichert und es entstehen auch keine Kosten (d.h. Speicherkosten = 0). 600 1000 500 800 number of requests 400 600 store_cost (PF) 300 400 200 200 100 0 0 GIF25 GIF25 GIF25 GIF50 GIF25 GIF50 A_phys GIF25 GIF50 JPG25 GIF25 JPG25 GIF50 GIF25 JPG25 GIF50 JPG50 GIF100 GIF25 JPG50 store_cost post_opt GIF25 JPG25 GIF50 JPG50 GIF25 JPG25 GIF50 JPG50 GIF75 JPG100 JPG25 GIF25 JPG25 GIF50 JPG50 GIF25 JPG25 GIF50 JPG50 GIF25 JPG25 GIF50 JPG50 GIF25 JPG25 GIF50 GIF25 GIF50 GIF25 GIF50 GIF25 GIF25 GIF50 JPG75 PS100 Abbildung 3.15.: Entwicklung der Speicherkosten 1 DM bzw. Pfennig angeGema obiger Wahl fur c_s werden die Kosten in 100 geben. Deutlich ist zu erkennen, da die Speicherkosten mit zunehmender Zahl der zu speichernden Attribute wachsen. Ebenso sieht man, da die Bilder in GIF50 etwa viermal soviel Speicherkosten verursachen als in GIF25 (Lauf 2 und 3, bzw. Lauf 15 und 16). Die Ursache dafur ist, da die Bilder bei der Skalierung von GIF25 nach GIF50 in zwei Dimensionen vergroert werden, so da sich der Speicherbedarf vervierfacht. Auswertung der Gesamtkosten Die Gesamtkosten setzen sich aus den Speicher- und Zugriskosten zusammen (vgl. De nition 2.6). In Abbildung 3.16 sind die Kosten mit und ohne Optimierung dargestellt. Die gestrichelte Linie zeigt den Kostenverlauf bei physikalischer Speicherung aller angefragten Attribute. Diese sind relativ hoch, da v.a. die Speicherung im Postscript-Format teuer ist. Im optimalen Fall wird PS nie physikalisch gespeichert. 3.6 Ausfuhrliche Beispiele 32 1000 7000 6000 800 number of requests 5000 cost (PF) 4000 600 3000 400 2000 200 1000 0 0 GIF25 GIF25 GIF25 GIF25 GIF50 GIF50 A_phys GIF25 GIF25 GIF25 GIF50 JPG25 JPG25 JPG25 GIF50 GIF50 JPG50 GIF25 JPG25 GIF50 JPG50 GIF25 JPG25 GIF50 JPG50 GIF25 JPG25 GIF50 JPG50 GIF25 JPG25 GIF50 JPG50 GIF25 GIF25 GIF25 GIF25 GIF25 JPG25 JPG25 GIF50 GIF50 GIF50 GIF50 JPG50 GIF25 GIF100 GIF75 GIF50 GIF25 JPG100 JPG75 JPG50 JPG25 PS100 cost post_opt cost no_opt cost save_all Abbildung 3.16.: Verlauf der Gesamtkosten Hier lat sich nun der tatsachliche monetare Gewinn der Optimierungen ablesen, da die Parameter entsprechend gewahlt worden sind. Die Dierenz zwischen den Kostenkurven mit und ohne Optimierung und der damit korrespondierende prozentuale Gewinn sind in den beiden Balkendiagrammen in 3.17 und 3.18 dargestellt. 1000 800 cost (PF) 600 400 200 0 1 2 3 4 5 6 7 8 9 run 10 11 12 13 14 15 16 saved cost (post_opt vs no_opt) Abbildung 3.17.: Absolute Kosteneinsparung 17 3.6 Ausfuhrliche Beispiele 33 60 50 40 percent 30 20 10 0 1 2 3 4 5 6 7 8 9 10 run 11 12 13 14 15 16 17 saved cost (percent) Abbildung 3.18.: Prozentuale Kosteneinsparung Da hier Zugris- und Speicherkosten gemeinsam betrachtet werden, ist der Gewinn naturlich nicht so gro wie bei den Zugriskosten allein. Trotzdem konnen beispielsweise in den Laufen 7 - 11 fast 10 DM eingespart werden. Noch deutlicher wird der Nutzen, wenn man wieder die prozentuale Verbesserung betrachtet: Im Mittel werden pro Lauf etwa 30 % an Gesamtkosten eingespart. Ab dem 9. Lauf rutscht die Verbesserung unter die 30 %-Marke. Dies wird durch die Anfragen an das Postscript-Format verursacht: Der Optimierer lehnt es aufgrund ihrer Groe ab, PS-Bilder zu speichern. Folglich kann fur diese Anfragen keine Einsparung erreicht werden, so da auch die Gesamtverbesserung sinkt. Sortiert man die Laufe nach ihrer prozentualen Verbesserung und bildet mehrere Klassen (0 - 10 % Verbesserung, 10 - 20 %, 20 - 30 %, 30 - 40 %, 40 - 50 %, > 50 %), so lat sich dies in einem Tortendiagramm (Abbildung 3.19) darstellen. 20 - 30 % 30 - 40 % 40 - 50 % 10 - 20 % > 50 % Abbildung 3.19.: Verteilung der Laufe gema der prozentualen Verbesserung Hier wird deutlich, da die Optimierung nicht nur in Einzelsituationen, sondern in einem Groteil der Laufe gute Ergebnisse liefert, denn in uber 23 der Falle liegt die Verbesserung zwischen 20 und 40 % und in 15 der Laufe sogar uber 40 %. 3.6 Ausfuhrliche Beispiele 34 Ebenso lohnt es sich, die Verbesserung in jedem einzelnen Lauf zu betrachten, d.h. man vergleicht die Kosten vor und nach jeder Optimierung. Dabei werden bei der Berechnung der Kosten vor der Optimierung (pre opt) die momentan gespeicherten Attribute berucksichtigt. Abbildung 3.20 zeigt den Verlauf der Kostenkurven. 3000 1000 2500 800 number of requests 2000 600 cost 1500 400 1000 200 500 0 0 GIF25 GIF25 GIF25 GIF50 GIF25 GIF50 A_phys GIF25 JPG25 GIF50 GIF25 GIF50 JPG25 GIF25 JPG25 GIF50 JPG50 GIF25 JPG25 GIF50 JPG50 GIF25 JPG25 GIF50 JPG50 GIF25 JPG25 GIF50 JPG50 GIF25 JPG25 GIF50 JPG50 GIF25 JPG25 GIF50 JPG50 GIF25 JPG25 GIF50 GIF25 GIF50 GIF25 GIF50 GIF25 GIF100 GIF75 GIF50 GIF25 JPG100 JPG75 JPG50 JPG25 PS100 cost post_opt cost pre_opt GIF25 Abbildung 3.20.: Vergleich der pre- und postoptimalen Kosten 60 50 40 percent 30 20 10 0 1 2 3 4 5 6 7 8 9 run 10 11 12 13 14 15 16 17 saved cost (post_opt vs pre_opt) Abbildung 3.21.: Prozentuale Verbesserung in jedem Lauf 3.6 Ausfuhrliche Beispiele 35 In den Fallen, in denen die Optimierung keine A nderung in Aphys induziert, sind diese beiden Kosten gleich (Laufe 2, 4, 6, 8 - 12, 15 und 17). Ansonsten ermoglicht die Optimierung eine Verbesserung, die naturlich nicht so auallig ist wie die in Abbildung 3.16. Der prozentuale Gewinn ist aus Abbildung 3.21 ersichtlich. 3.6.2. Abfragen von Aktiencharts Anleger wollen standig uber die aktuellen Kurswerte ihrer Wertpapiere informiert sein. Banken und Anlageberater stellen deshalb sog. Aktiencharts (graphische Darstellung eines Kursverlaufs) uber das Internet bzw. per Faxabruf zur Verfugung. Abbildung 3.22.: Einstellungen fur das Aktiencharts-Beispiel In diesem Szenario sollen entsprechende Anfragen simuliert werden. Dazu werden folgende Annahmen gemacht: ♦ Format. u ber das Internet fordern eine Ausgabe der Charts Dieim Anfragen GIF- 3.6 Ausfuhrliche Beispiele ♦ ♦ ♦ 36 Faxabrufe verlangen die Ausgabe in ein Beispiel wird das Faxformat IPS verwendet, das von der Firma Brooktrout2 zur Datenubertragung an Faxkarten eingefuhrt wurde. otigt. Zum Ausdrucken wird gelegentlich das Die IPS- und GIF-Bilder werden in hoh Auosung angefragt. Das Anfragepro l ist aus den Abbildungen 3.22 und 3.23 ersichtlich. Des weiteren wird unterstellt, da in der Datenbank 700 Charts (Format: BMP) vorliegen, deren Groe jeweils etwa 1 MB betragt. Die Zugriskosten werden wie zuvor in Millisekunden berechnet, so da der Button use_total_access eingeschaltet und c_a=0.00005 gewahlt werden mu. Die Speicherkosten werden hier mittels einer Treppenfunktion berechnet, d.h. use_total_store und use_stepfunction werden aktiviert. Dabei wird angenommen, da Tablespaces mit 500 MB Speicher verwendet werden und das Einrichten eines neuen Tablespace jeweils 20 DM kostet (verursacht durch die Festplattenkosten bzw. Arbeitszeit). Da die Zugriskosten in Millisekunden und die Speicherkosten in DM berechnet werden, wird der Parameter z=0.00002 gesetzt (zwei Zehnerpotenzen kleiner als im vorherigen Beispiel, siehe Seite 29). Weiterhin werden p=5 und q=2 gewahlt. 1600000 500 1400000 400 1200000 number of requests 1000000 acc_cost 800000 (ms) 300 200 600000 400000 100 200000 0 GIF50 GIF50 GIF50 GIF100 GIF100 GIF100 IPS100 IPS100 IPS100 A_phys 0 GIF50 GIF100 IPS50 IPS100 GIF50 GIF50 GIF50 IPS50 GIF100 GIF100 GIF100 IPS100 IPS100 IPS100 GIF100 GIF50 IPS100 PS100 acc_cost no_opt acc_cost post_opt Abbildung 3.23.: Verlauf der Zugriskosten 2 http://www.brooktrout.com/ IPS50 3.6 Ausfuhrliche Beispiele 37 Auswertung der Zugriskosten Ohne Optimierung verlaufen die Zugriskosten entsprechend der Zahl der Anfragen (dunne Kurve aus Abbildung 3.23), so da insbesondere in den Laufen 4, 5 und 12-14 diese Kosten sehr hoch sind. Besonders in diesen Fallen bringt die Optimierung einen hohen Gewinn, da durch das Speichern eines GIF- oder IPS-Formats viel Zeit eingespart werden kann: Zum einen entfallt fur solche Attribute naturlich die aufwendige Formatkonvertierung, zum andern sind GIFund IPS-Bilder komprimiert, so da sie viel kleiner als die Originale im BMPFormat sind und damit kurzere Ladezeiten benotigen. 25 20 15 time (min) 10 5 0 1 2 3 4 5 6 7 8 run 9 10 11 12 13 14 15 16 saved time (post_opt vs no_opt) Abbildung 3.24.: Absolute Verbesserung der Zugriskosten 100 80 60 percent 40 20 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 run saved time (percent) Abbildung 3.25.: Prozentuale Verbesserung der Zugriskosten Die eingesparte Gesamtzeit liegt deshalb in den Laufen 4-6 und 12-15 zwischen 18 und 25 Minuten, wie aus Abbildung 3.24 abgelesen werden kann. Die prozentuale Verbesserung liegt in diesen Fallen bei u ber 90 %, teilweise ist sie nur knapp unter 100 %. Trotz dieser immensen Einsparungen lehnt der Optimierer in vielen Fallen (1-3, 7-11 und 16) das Speichern zusatzlicher Attribute ab. Dies liegt naturlich an den Speicherkosten, die im folgenden analysiert werden sollen. 3.6 Ausfuhrliche Beispiele 38 Auswertung der Speicherkosten In diesem Szenario wird ein treppenformiger Verlauf der Speicherkosten unterstellt: Jeder angefangene 500-MB-Block kostet 20 DM. Entsprechend verlaufen die Speicherkosten in 20-DM-Schritten, wie aus Abbildung 3.26 ersichtlich wird. 20 500 400 15 number of requests 300 store_cost (DM) 10 200 5 100 0 0 GIF50 GIF50 GIF50 GIF100 GIF100 GIF100 IPS100 IPS100 IPS100 GIF100 GIF50 IPS100 A_phys IPS50 GIF50 GIF50 GIF50 GIF50 GIF100 IPS50 GIF100 GIF100 IPS50 GIF100 IPS100 IPS100 IPS100 IPS100 PS100 store_cost post_opt Abbildung 3.26.: Verlauf der Speicherkosten Werden keine Attribute zusatzlich gespeichert, so sind die Speicherkosten naturlich gleich Null (Lauf 1-3 und 7-11 und 16), ansonsten wird maximal ein 500-MB-Block benotigt, so da die Kosten hochstens 20 DM betragen. Hierbei wird auch die Komprimierung durch die Formate GIF und IPS deutlich: Die Speicherung aller 700 Bilder in vier GIF- und IPS-Attributen (Laufe 12 und 13) braucht weniger als 500 MB Speicher, obwohl ein Bild im Original 1 MB gro ist. Auswertung der Gesamtkosten Werden alle angefragten Attribute gespeichert (GIF100, GIF50, IPS100, IPS50, PS100), so werden zwei 500-MB-BLocke benotigt, so da die Speicherkosten 40 DM betragen und die Gesamtkosten nahezu konstant bei 40 DM liegen (cost save all, gestrichelte Linie in Abbildung 3.27). Die dunne durchgezogene Linie zeigt den Kostenverlauf, falls keine Optimierung durchgefuhrt wird und alle angefragten Attribute stets aus den Referenzbildern konvertiert werden. Andernfalls ist wieder eine groe Kosteneinsparung moglich, wie der Vergleich mit der dickeren Linie (cost post opt) zeigt. Durch die Optimierung konnen die Kosten um bis zu 10 DM (Lauf 13) reduziert werden, damit werden im Vergleich zu "no opt\ uber 30 % eingespart. In den Laufen, in denen der Optimierer eine physikalische Speicherung von Attributen 3.6 Ausfuhrliche Beispiele 39 500 40 400 number of requests 300 30 cost (DM) 20 200 10 100 0 0 GIF50 GIF50 GIF50 GIF100 GIF100 GIF100 IPS100 IPS100 IPS100 GIF100 PS100 GIF50 GIF100 IPS50 IPS100 A_phys GIF50 cost save_all GIF50 GIF50 GIF50 IPS50 GIF100 GIF100 GIF100 IPS100 IPS100 IPS100 IPS100 cost save_no IPS50 cost post_opt Abbildung 3.27.: Verlauf der Gesamtkosten vorschlagt (4-6, 12-15) werden im Durchschnitt etwa 20 % gespart, mittelt man uber alle Laufe, so betragt die Einsparung knapp 10 %. 30 25 20 percent 15 10 5 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 run saved cost (percent) Abbildung 3.28.: Prozentuale Kostenersparnis Werden die Laufe gema ihrer prozentualen Verbesserung auf die Kategorien < 10%, 10 ; 20%, 20 ; 30%, 30 ; 40%, 40 ; 50% und > 50% verteilt, so ist die < 10%-Kategorie naturlich am groten (Abbildung 3.29), da bereits 9 der 16 Laufe keine Verbesserung liefern. Trotzdem liegt in 51 der Falle der Gewinn zwischen 20 und 40 %. 3.6 Ausfuhrliche Beispiele 40 < 10 % 30 - 40 % 10 - 20 % 20 - 30 % Abbildung 3.29.: Verteilung der Laufe gema der prozentualen Verbesserung Schlielich soll auch hier der Nutzen in jedem einzelnen Lauf analysiert werden, indem Kosten vor und nach der Optimierung verglichen werden (Abbildung 3.30). 500 40 400 number of requests 300 30 cost (DM) 20 200 10 100 0 0 GIF50 GIF50 GIF50 GIF100 GIF100 GIF100 IPS100 IPS100 IPS100 GIF100 PS100 GIF50 cost post_opt A_phys GIF50 GIF100 IPS50 IPS100 IPS100 cost pre_opt GIF50 GIF50 GIF50 IPS50 GIF100 GIF100 GIF100 IPS100 IPS100 IPS100 IPS50 Abbildung 3.30.: Vergleich der pre- und postoptimalen Kosten Da die preoptimalen Kosten von den vor der Optimierung gespeicherten Attributen abhangen, konnen die postoptimalen Kosten nur dann geringer sein, wenn die Optimierung eine Veranderung in Aphys induziert (Laufe 4, 7, 12, 14 und 16). Die prozentuale Verbesserung in jedem Lauf ist in Abbildung 3.31 dargestellt. 3.6 Ausfuhrliche Beispiele 41 30 25 20 percent 15 10 5 0 1 2 3 4 5 6 7 8 run 9 10 11 12 13 14 15 16 saved cost (post_opt vs pre_opt) Abbildung 3.31.: Prozentuale Verbesserung in jedem Lauf Wird durch die Optimierung eine A nderung der physikalisch gespeicherten Attribute verursacht, so betragt in diesen Laufen die Verbesserung etwa 20 %. Lauf 14 stellt dagegen eine Ausnahme dar: Die Verbesserung ist so gering, da sie in der Graphik verschwindet. In diesem Kapitel wurden die Optimierungsalgorithmen an umfangreichen praxisrelevanten Beispielen getestet. Deren Auswertung ergab, da durch die Formatoptimierung eine enorme Kosteneinsparung moglich ist, die sich fur den Endbenutzer vor allem durch kurzere Ladezeiten bemerkbar macht. 4. Implementierung Im Kapitel 2 wurden Algorithmen zur Formatoptimierung vorgestellt. Der Basisalgorithmus 2.1 wurde bereits von Peter Rieger (Rie97]) in C/ESQL realisiert, die auf Algorithmus 2.2 (einschlielich samtlicher Modi kationen) basierende Re-Implementierung in Java/JDBC ist Bestandteil der vorliegenden Arbeit. Dazu werden in diesem Kapitel die verwendete Programmiersprache Java und die wesentlichen Aspekte der Implementierung vorgestellt. Der Quellcode der Optimierung (Attribut.java und Optimierung.java, siehe Anhang B) ist 1200 Zeilen lang, der der Oberachen umfat 800 (Scenery.java) bzw. 300 (Opti.java) Zeilen. Samtliche Programmtexte nden sich auch im Internet1 . 4.1. Java und die Datenbankschnittstelle JDBC Die Programmiersprache Java und die dazugehorigen Klassenbibliotheken bieten eine portable, interpretierbare, leistungsfahige, objektorientierte Entwicklungsumgebung. Damit konnen auch Programme erstellt werden, die u ber das Internet verschickt und von einem Browser gestartet werden (sog. Applets). Sie dienen v.a. zur Auockerung von Web-Seiten. Ebenso erlaubt Java aber auch die Programmierung komplexer Applikationen, wie sie in dieser Arbeit entwickelt werden. Der zentrale Bestandteil eines Java-Programms ist die Klasse. Jede Variable und jede Methode mu Bestandteil einer Klasse sein. Bei einer Applikation mu in einer Klasse eine Methode public static void main (String ] args) vorliegen, die mit der main-Funktion in C-Programmen vergleichbar ist. Applets enthalten keine main-Methode, da sie nicht selbstandig ablaufen, sondern von einem Browser gestartet und beendet werden. Daneben gibt es als Strukturierungsmittel sog. Pakete, die verwandte Klassen zusammenfassen. Gangige Pakete sind java.lang und java.util, die u.a. Klassen fur Datenstrukturen, Zeichenkettenoperationen und Fehlerbehandlung beinhalten. In jedem Java-Programm wird java.lang automatisch geladen, andere Pakete mussen mit dem Befehl import zu Beginn des Java-Programms eingebunden werden, z.B.: 1 http://heron.informatik.uni-augsburg.de/tmplobs/doc/main.htm 4.1 Java und die Datenbankschnittstelle JDBC 43 import java.util.* Fur die Datenbankschnittstelle JDBC (Java Database Connectivity) steht das Paket java.sql zur Verfugung, in dem Schnittstellen und Klassen de niert sind, deren Methoden den Zugri und die Manipulation von Datenbanktabellen erlauben. (Eine Schnittstelle ist eine Klasse, deren Methoden noch nicht implementiert sind.) Diese sind unabhangig von der verwendeten Datenbanksoftware, so da ein JDBC-Programm auf verschiedenen Datenbanksystemen lauahig ist. Technisch wird das realisiert, in dem die Schnittstellen im java.sql-Paket vom jeweiligen Datenbanksystem implementiert werden. Deshalb ist es erforderlich, zu Beginn eines JDBC-Programms einen datenbankspezi schen Treiber zu laden. Unter DB2 geschieht dies mit folgendem Programmfragment: static { try { Class.forName("COM.ibm.db2.jdbc.app.DB2-Driver") } catch(ClassNotFoundException x) { System.out.println("\nError loading DB2-Driver") x.printStackTrace() } } Bei Informix-Datenbanken wurde die funfte Zeile stattdessen Class.forName("informix.api.jdbc.JDBCDriver") lauten. Nachdem das Paket java.sql und der Treiber geladen sind, konnen die Klassen und die dazugehorigen Methoden der JDBC verwendet werden. Damit werden u.a. folgende Funktionen zur Verfugung gestellt: ♦ und ohne "Auto Commit\ ♦ ♦ ♦ u ber die Datenbank utzung von statischem und dynamischem SQL Aufbau einer Datenbankverbindung, Ve Abfrage von Meta-Informationen Unterst Verwendung der UDFs, insbesondere au Die Ergebnisse von SELECT-Anfragen werden ahnlich wie bei Embedded SQL mit einem Cursor durchlaufen. Beispiel Gesucht sind die Formate und die Qualitatsstufen, in denen die Bilder momentan vorliegen. 4.2 Das Datenmodell 44 . . . Connection con = DriverManager.getConnection("jdbc:db2:stefandb") . . . String sql = "SELECT DISTINCT mmdbsys.format(ext_image),quality"+ " FROM raw_image" Statement stmt = con.createStatement() ResultSet rs = stmt.executeQuery(sql) while(rs.next) { String format = rs.getString(1) int quality = rs.getInteger(2) System.out.println(format+", "+quality) } Zunachst wird also eine Verbindung mit der Datenbank stefandb aufgebaut und ein Objekt vom Typ Statement erzeugt. Die Anfrage wird als Zeichenkette verschickt und die Ergebnismenge mit dem Cursor rs durchlaufen. Fur die UDF format wurde hier das Schema mmdbsys mit angegeben. Dieser Zusatz kann entfallen, wenn mmdbsys der Variable CURRENT FUNCTION PATH hinzugefugt wird. Das Argument ext_image bezeichnet eine Spalte vom Typ DB2Image in der Tabelle raw_image (vgl. Datenmodell im nachsten Abschnitt). Das Ergebnis kann beispielsweise so aussehen: GIF, GIF, GIF, GIF, JPG, JPG, 25 50 75 100 50 100 4.2. Das Datenmodell Zur Speicherung der Bilder, der moglichen Formate und Konvertierungen und der statistischen Daten wurde das in Abbildung 4.1 dargestellte Datenbankschema (Entity-Relationship-Modell) gewahlt. Die eigentlichen Bilder werden unter ext_image (Datentyp: DB2Image) in der Entitat raw_image gespeichert, Name und Beschreibung nden sich dagegen in image. Dies erm oglicht, da die Bilder in mehreren Formaten und Qualitatsstufen vorliegen, aber nur einmal beschrieben sind, so da keine Redundanzen auftreten. 4.2 Das Datenmodell raw_image ext_image name quality static 45 describes image name description selects_description selects_picture conversion source_format source_quality target_format target_quality z_hist avg_conv_time is_allowed uses_conversion query_profile date_time name source_format source_quality target_format target_quality target_image_sz conv_time age Abbildung 4.1.: Datenmodell Die Entitat conversion beinhaltet alle von den DB2-Extendern zur Verfugung gestellten Formatkonvertierungen und markiert die momentan zulassigen mit is_allowed=1. Ebenso wird hier die durchschnittliche Konvertierungszeit gespeichert. Diese kann standig aktualisiert werden: Neuere Daten (Gewicht: 1-z_hist) verbessern die alteren (Gewicht: z_hist). In query_profile wird jede Anfrage registriert. Falls dabei konvertiert werden mu, wird die benotigte Rechenzeit unter conv_time in Millisekunden gespeichert. Ebenso wird auch die Groe des dabei entstandenen Bildes vermerkt. Die des Quellbildes mu nicht gespeichert werden, da sie mit der UDF size berechnet werden kann. Die Spalte age gibt an, fur wieviele Optimierungen die Anfrage bereits verwendet wurde. Sie dient auch der Entfernung nicht mehr relevanter Querys. Zu jeder Anfrage mu eine entsprechende Konvertierung existieren (Quell- und Zielattribut durfen auch gleich sein), das Quellattribut des Bildes mu in raw_image und die Beschreibung in image vorliegen. Dies sichern die Relationships uses_conversion, selects_picture und selects_description. Die Relationship describes ordnet jedem gespeicherten Bild eine dazugehorige Beschreibung zu. Die Tabelle opti_log in Abbildung 4.2 wird nicht fur die Optimierung benotigt, sondern dient zum Speichern der Parameter und Ergebnisse der einzelnen Optimierungslaufe. Es werden die Speicher- und Zugriskosten vor (preopt) und nach (postopt) der Optimierung eingetragen, ebenso die Kosten, falls alle angefragten Attribute (saveall) oder nur das Referenzformat (saveno) gespeichert werden. Die Gesamtkosten konnen aus dem Parameter z und den jeweiligen Speicher- und Zugriskosten ermittelt werden. Zusatzlich werden auch die reinen Rechenzeiten (computing_time) und die Gesamtdauer (total_time) vermerkt. Schlielich gibt a_phys als Zeichenkette die Menge der zu speichernden 4.3 Die Implementierung der Klassen 46 Attribute an. opti_log datetime static_format z c_s c_a c_c p q number_of_images hd_size hd_cost computing_time total_time acc_cost_preopt store_cost_preopt acc_cost_saveall store_cost_saveall acc_cost_saveno store_cost_saveno acc_cost_postopt store_cost_postopt a_phys Abbildung 4.2.: Die Tabelle opti log Die Entitaten werden im Relationenmodell zu Tabellen, die Relationships werden durch Fremdschlussel realisiert. Ein Shell-Script zur Ausfuhrung der entsprechenden SQL-Statements fur DB2Datenbanken ndet sich im Anhang A.1. 4.3. Die Implementierung der Klassen Java-Programme konnen modularisiert werden, indem der Quellcode auf mehrere sinnvolle Klassen verteilt wird. Die Klasse Attribut dient der Speicherung von Attributinformationen, in Optimization wird die eigentliche Optimierung durchgefuhrt, und Opti erzeugt eine graphische Benutzeroberache zur Kon guration der Optimierung. Kurzinformationen zu den wichtigsten Variablen und Methoden dieser Klassen nden sich auch im Internet2 . 4.3.1. Die Klasse Attribut Hier werden die zur Optimierung notwendigen Informationen u ber die Attribute gespeichert. Diese sind im einzelnen: 2 http://heron.informatik.uni-augsburg.de/tmplobs/doc/tree.html 4.3 Die Implementierung der Klassen 47 Variable Beschreibung acc_cost Zugriskosten fur dieses Attribut avg_acc durchschnittliche Zugrisrate oder absolute Zugriszahl avg_conv_time Dauer einer Konvertierung vom Referenzformat bzw. von "besseren\ Attributen in dieses Attribut in Anlehnung an die Konvertierungsregeln auf Seite 10 (realisiert als Integer-Feld der Lange vier) avg_image_size durchschnittliche Bildgr oe bit_best =1, falls dieses Attribut nach der Optimierung zu Aphys gehort, sonst bit_best=0 bit_used =1, falls dieses Attribut im aktuellen Schritt zu Aphys gehort, sonst bit_used=0 format Bildformat quality Bildqualitat Die einzige Methode dieser Klasse heit equals und testet zwei Attribute auf Gleichheit. 4.3.2. Die Klasse Optimization Die Optimierung wird in Methoden dieser Klasse realisiert. Die Variablen z, c_s, c_a, c_t, c_c, p und q realisieren die in Kapitel 2 bereits vorgestellten Parameter. Die boolschen Variablen use_total_store, use_stepfunction und use_total_access entsprechen den auf Seite 19 vorgestellten Schaltern der graphischen Oberache Scenery, ebenso die IntegerFelder hd_size und hd_cost. Aktualisierung der durchschnittlichen Konvertierungszeiten Fur die Anfragen, die seit der letzten Optimierung gestellt worden sind, wird fur jede verwendete Konvertierung die durchschnittliche Rechenzeit conv_time_new bestimmt. Damit wird die Spalte avg_conv_time der Tabelle conversion gema folgender Vorschrift angepat: avg_conv_time=z_hist*avg_conv_time + (1-z_hist)*conv_time_new Der Parameter z_hist kann fur jede Konvertierung individuell angegeben werden, so da beispielsweise im Falle unbekannter Konvertierungszeiten z_hist=0 gesetzt werden kann und im anderen Extremfall, falls die Rechenzeit bekannt und stets konstant ist, z_hist=1 gewahlt wird. Im allgemeinen wird jedoch z_hist 2 (0 1) gelten. Analyse der statistischen Daten Vor der Optimierung mussen naturlich die statistischen Daten (durchschnittliche Bildgroe, Konvertierungszeiten usw.) aus der Datenbank gelesen werden. 4.3 Die Implementierung der Klassen 48 Die angefragten Attribute werden der Tabelle query_profile entnommen. Dabei mussen die Parameter p und q beachtet werden, so da der SQL-String lautet: String sql = "SELECT target_format, target_quality, "+ "avg(target_image_sz), count(*) "+ "FROM query_profile "+ "WHERE age < "+ p + "GROUP BY target_format, target_quality "+ "HAVING count(*) >= " + q Jedes Ergebnis wird in einem Objekt der Klasse Attribut gespeichert. Aus obiger Anfrage werden das Format, die Qualitat, die durchschnittliche Bildgroe und die Anzahl der Anfragen ermittelt. Letztere wird direkt in avg_acc gespeichert, falls die Gesamtzugriszahl relevant ist (use_total_access=true), andernfalls wird durch die Anzahl aller Zugrie dividiert und die damit errechnete Zugrisrate in avg_acc abgelegt. Zu jedem Attribut mussen noch die Konvertierungszeiten vom Referenzformat und von den "besseren\ Attributen aus der Tabelle conversion ausgelesen werden. Fur das Attribut a lauten die Statements: String sql = "SELECT avg_conv_time FROM conversion " + "WHERE target_format = '" + a.format + "' " + "AND target_quality = " + a.quality + " "+ "AND source_format = '" + static_format + "' " + "AND source_quality = " +static_quality und String sql = "SELECT avg_conv_time FROM conversion " + "WHERE target_format = '" + a.format + "' " + "AND target_quality = " + a.quality + " "+ "AND source_format = '" + a.format + "' " + "AND source_quality > " +a.quality + " " + "ORDER BY source_quality DESC" Dabei sind static_format und static_quality Referenzformat und Referenzqualitat, wobei meist static_quality=100 gelten wird. Die einfachen Anfuhrungsstriche kennzeichnen Strings in DB2. Die Ergebnisse werden in einer festgelegten Reihenfolge in das Feld avg_conv_time des jeweiligen Attributs eingetragen. Die durchschnittliche Bildgroe eines Attributs wird mit avg(target_image_sz) aus den angefragten Bildern geschatzt. Bei Attributen, in denen die Bilder bereits vor der Optimierung gespeichert waren, kann diese mit 4.3 Die Implementierung der Klassen 49 String sql = "SELECT avg(mmdbsys.size(ext_image)) "+ "FROM raw_image "+ "WHERE mmdbsys.format(ext_image) = '" + a.format+ "' AND quality = " + a.quality genauer berechnet werden, da hier der Durchschnitt uber alle Bilder bestimmt wird. Realisierung der Potenzmenge der Attribute Die Attribute werden in der Datenstruktur Vector (aus dem Paket java.util) abgelegt. Dies ist eine Liste, in der die einzelnen Elemente indiziert werden, so da leicht auf bestimmte Attribute zugegrien werden kann. Nachteilig ist, da ein Vector nur Objekte kennt, die bei jedem Zugri in den entsprechenden Datentyp (hier die Klasse Attribut) umgewandelt werden mussen. Fur Aphys mu jede mogliche Teilmenge der Attribute getestet werden. Dazu wird die Variable bit_used verwendet, die zu Beginn fur alle Attribute =0 ist, d.h. kein Attribut ist physikalisch gespeichert. Die u brigen Teilmengen werden analog zur Implementierung in Rie97] erzeugt: Die Menge der Variablen bit_used wird als Bin arzahl interpretiert, die in jedem Optimierungsschritt inkrementiert wird. bit_used 1. Optimierungsschritt Attribut 1 Attribut 2 Attribut 3 0 0 0 bit_used 0 0 1 bit_used 0 1 0 bit_used 0 1 1 bit_used 1 0 0 2. Optimierungsschritt 3. Optimierungsschritt 4. Optimierungsschritt 5. Optimierungsschritt usw. In jedem Schritt werden die Kosten berechnet und mit den Kosten der bisher besten Menge Aphys verglichen. Bei einer Verbesserung wird die aktuelle Menge Aphys gemerkt, indem hier bit_best=1 gesetzt wird. Mit diesem Vorgehen steht am Ende die optimale Menge der zu speichernden Attribute fest. Berechnung der Speicherkosten Zunachst wird die Summe der durchschnittlichen Bildgroen a.avg_image_size aller Attribute a 2 Aphys bestimmt. Ist der Gesamtspeicherbedarf relevant (use_total_store=true), so wird diese Summe zusatzlich mit der Bildanzahl multipliziert. 4.3 Die Implementierung der Klassen 50 Falls keine Treppenfunktion verwendet werden soll (use_stepfunction= false), so sind die Speicherkosten das Produkt aus dieser Summe mit der Variablen c_s. Andernfalls ist die Berechnung etwas aufwendiger: Die Treppenfunktion sei durch die Arrays hd_size und hd_cost gegeben, wobei die Groe in MB angegeben ist (z.B. hd_size=100,150,250 und hd_cost=50, 90,140). Reichen die vorgegebenen Gr oen nicht aus, so soll mit der letzten Angabe (im Beispiel Groe 250 und Kosten 140) interpoliert werden. Dies kann deaktiviert werden, indem eine zusatzliche Platte mit (fast) unendlichen Kosten hinzugefugt wird (hier hd_size=100,150,250,1 und hd_cost=50,90,140, 999999). Zur Berechnung der Speicherkosten mu zunachst die obige Summe durch 1000000 dividiert werden, da diese in Byte angegeben ist. Aus dem resultierenden Speicherbedarf (in MB) werden die benotigten Platten ermittelt, die Speicherkosten ergeben sich dann aus der Summe der Kosten dieser Platten. Berechnung der Zugriskosten In jedem Optimierungsschritt wird die Attributmenge A in zu speichernde und zu berechnende Attribute zerlegt. Fur ein physikalisch gespeichertes Attribut a sind die Zugriskosten gema De nition 2.9 das Produkt aus der durchschnittlichen Bildgroe (a.avg_image_size) und dem Parameter c_a und werden unter a.acc_cost abgelegt. Bei den zu berechnenden Attributen mu zunachst das Quellformat ermittelt werden. Dies geschieht unter Berucksichtigung der momentan zu speichernden Attribute und den Konvertierungsregeln auf Seite 10. Daraus ergibt sich, welche Konvertierungszeit aus dem Array a.avg_conv_time verwendet werden mu. Die Zugriskosten ergeben sich dann additiv aus der mit c_c skalierten Konvertierungszeit und der mit c_a multiplizierten durchschnittlichen Bildgroe des Quellformats. Die Summe uber die mit der Variable a.avg_acc gewichteten attributbezogenen Zugriskosten liefert die Gesamtzugriskosten. Ist use_total_access=false, so gibt a.avg_acc die Zugrisrate (2 0 1]) an, andernfalls die tatsachliche Zahl der Anfragen an dieses Attribut (vgl. Seite 48). Bestimmung der Optimalitat Die Gesamtkosten ergeben sich aus der Summe der Speicherkosten (Gewicht: (1-z)) und der Zugriskosten (Gewicht: z). Eine Zerlegung der Attributmenge in Aphys und Acomp ist optimal, wenn diese Gesamtkosten minimal sind. 4.3 Die Implementierung der Klassen 51 Aktualisierung der Datenbank Zunachst werden die Bilder in den Attributen geloscht, die vor der Optimierung gespeichert und nun berechnet werden. Zum Loschen des Formats f in der Qualitat q dient folgendes Statement: String sql = "DELETE FROM raw_image "+ "WHERE mmdbsys.format(ext_image) = '" + f + "AND quality = " + q + " AND static = 0" Die Zusatzbedingung static=0 verhindert, da das Referenzformat geloscht wird. Die DB2-Extender ermoglichen das Speichern der Bilder als Blobs in der Datenbank oder als Dateien im Filesystem. In dieser Implementierung wird die zweite Variante verwendet, da etliche UDFs der DB2-Extender nur dann funktionieren. Nachteilig ist, da diese Funktionen zwar Dateien erzeugen konnen (z.B. beim Einfugen neuer Attribute), diese aber nicht zu loschen vermogen. Dies kann jedoch leicht von Java ubernommen werden, denn mit folgender kurzer Anweisung kann die Datei geloscht werden, die in der Zeichenkette filename (in der Form Pfad+Dateiname) steht: File f1 = new File(filename) f1.delete() Der Dateiname eines Bildes kann beispielsweise mit der UDF filename der DB2-Extender bestimmt werden. Ezienter ist jedoch folgendes Vorgehen: Beim Erzeugen der Bilder werden bereits eindeutige und sinnvolle Dateinamen verteilt, die der Form "Bildname+Qualitatsstufe+.+Format\ genugen. Die Qualitat wird hier nicht in der Form 100, 75, 50, 25 sondern wegen besserer Lesbarkeit mit s1, s2, s3, s4 bezeichnet. Soll nun ein gewisses Attribut geloscht werden, so kann mit Java leicht eine Liste der zugehorigen Dateien bestimmt und diese geloscht werden. Dies geht naturlich wesentlich schneller als der hau ge Zugri auf die Datenbank. Zum Einfugen neuer Bilder in die Datenbank braucht man die Dateinamen der Bilder im Referenzformat und mu gema obigem Vorgehen Dateinamen fur die neuen Bilder entwickeln. Lauten diese Dateinamen filename und filename_new und soll das Bild mit der Bezeichnung name im Attribut a eingefugt werden, so verwendet man folgendes Statement: String sql = "INSERT INTO raw_image VALUES("+ "mmdbsys.DB2Image(CURRENT SERVER,"+ "CAST('"+filename+"' AS LONG VARCHAR),"+ "CAST('"+static_format+"' AS VARCHAR(8)),"+ "CAST('"+a.format+"' AS VARCHAR(8)),"+ "CAST('"+option+"' AS VARCHAR(100)),"+ "CAST('"+filename_new+"' AS LONG VARCHAR),''),"'+ name+"',"+a.quality+",0)" 4.3 Die Implementierung der Klassen 52 Hierbei gibt option die Skalierung in der Form -s x an, wobei x=1 beispielsweise 100% und x=0.75 einer 75%-Auosung entspricht. Die Typumwandlungen sind notwendig, da die UDFs nur Parameter im korrekten Datentyp akzeptieren. In der Tabelle conversion mu die Menge der zulassigen Konvertierungen angepat werden. Dazu wird zunachst fur alle Konvertierungen is_allowed=0 gesetzt: String sql = "UPDATE conversion SET is_allowed=0" Um die Konvertierungsregeln von Seite 10 zu erfullen, mu fur jedes gespeicherte Attribut a, dessen Format nicht EPS, EP2, PS, PSC oder PS2 ist, das Attribut b 2 Aphys mit der n achstschlechteren Qualitat min bestimmt werden. Falls es kein solches b gibt, so sei min=0. Aus a werden dann die Attribute berechnet, deren Auosung besser als min ist: String sql = "UPDATE conversion SET is_allowed = 1 WHERE " + "source_format = '" + a.format + "' AND " + "source_quality = " + a.quality + " AND " + "target_format = '" + a.format + "' AND " + "target_quality <= " + a.quality + " AND " + "target_quality > " + min Die ubrigen Attribute a 2 Acomp werden aus dem Referenzformat erzeugt: String sql = "UPDATE conversion SET is_allowed = 1 WHERE " + "source_format = '" + static_format + "' AND " + "source_quality = " + static_quality + " AND " + "target_format = '" + a.format + "' AND " + "target_quality = " + a.quality Schlielich mu noch die Tabelle query_profile aktualisiert werden: Das Alter der Anfragen (Spalte age) wird inkrementiert. Wird das Hochstalter u berschritten, dann werden die entsprechenden Daten geloscht. String sql = "UPDATE query_profile SET age = age + 1" String sql2 = "DELETE FROM query_profile WHERE age >= " + q 4.3.3. Die Klasse Opti Zur Kon guration und Durchfuhrung der Optimierungen stellt diese Klasse eine graphische Oberache zur Verfugung. Die Parameter werden wie im Kapitel 3 verwendeten Programm Scenery.java gesetzt. Naturlich wird hier kein Anfragepro l eingegeben, da dies den statistischen Daten der Tabelle query_profile entnommen wird. Das Textfeld dient der Ausgabe von Statusinformationen. Nach der Optimierung wird in einem kleinen Fenster abgefragt, ob die Datenbank aktualisiert werden soll oder nicht. Dies ermoglicht den Ablauf mehrerer 4.4 SQL-Fehler und Java-Ausnahmen 53 Optimierungen (z.B. um verschiedene Parameterkombinationen zu testen) ohne das zeitraubende Loschen und Einfugen von Bildern. Abbildung 4.3 zeigt die Oberache nach einer Optimierung, die Ergebnisse sind im Textfeld zu sehen. Wird im Question-Fenster "Yes\ angeklickt, so wird die Datenbank aktualisiert, andernfalls ist der Lauf beendet. Abbildung 4.3.: Benutzerschnittstelle Die zugrundeliegende Bilddatenbank ist das im Abschnitt 1.3 vorgestellte Beispiel. 4.4. SQL-Fehler und Java-Ausnahmen Fur das Versagen von SQL-Statements kann es verschiedene Ursachen geben, z.B.: ♦ Der Datenbankserver wurde herunterge 4.4 SQL-Fehler und Java-Ausnahmen 54 Die angefragten Tabellen oder Spalten Die Zugrisrechte reichen nicht aus. ur die Ergebnismengen ist zu gering. Der Zwischenspeicher f ... ♦ ♦ ♦ ♦ Bei Verwendung der DB2-Extender kann es noch weitere Probleme geben: ♦ ♦ ♦ ♦ abled\). Der Extender-Server ist heruntergefahre ur die Extender freigegeben Die Tabellen ("en- oder Spalten sind nicht f ur die UDFs reicht nicht aus. Der Speicher f ... Java ermoglicht die komfortable Behandlung von Ausnahmesituationen (sog. Exceptions). Kritische Anweisungen wie z.B. SQL-Statements konnen in einem try-Block ausgef uhrt werden. Treten dann Fehler auf, so wird ein Objekt eines Ausnahmetyps (z.B. SQLException) erzeugt und die Anweisungen des catchBlocks ausgefuhrt, z.B.: String sql = "UPDATE conversion SET is_allowed = 0" Statement stmt try { stmt = con.createStatement() stmt.executeUpdate(sql) stmt.close() } catch (SQLException x) { System.out.println("Error in method update_conversion\n"+ +"while updating table conversion\n"+ +x.getMessage() } Die Methode x.getMessage() gibt die SQL-Fehlermeldung als String zuruck. Im obigen Beispiel erfolgt die Ausgabe in der Shell, naturlich kann sie auch in einem Textfeld einer GUI gezeigt werden. 5. Kritische Anmerkungen zu den DB2-Extendern Bei der Implementierung traten hau g Schwierigkeiten mit den DB2-Extendern auf. Typische Probleme, Software-Bugs und Fehler in der Dokumentation Ext] sollen hier nun erlautert werden. Dies dient nicht der Abwertung der DB2Extender, sondern ist als Hilfestellung fur andere User gedacht, die zukunftig mit dieser Software arbeiten. Da die DB2-Extender mit groen Datenmengen arbeiten, treten hau g Speicherprobleme auf. Diese konnen leicht behoben werden, indem die entsprechenden DB-Umgebungsvariablen geeignet gesetzt werden. Folgende Modi kationen haben sich als ausreichend erwiesen: Variable Beschreibung Default Neu Einheit aslheapsz Heap-Speicher fur Programme 15 1000 4 KB query_heap_sz Heap-Speicher f ur Querys 1000 5000 4 KB udf_mem_sz Speicher fur Datentransfer 256 1024 4 KB UDF $ Datenbank Gesetzt werden sie im sog. Command-Line-Prozessor (CLP) mit folgender Anweisung: UPDATE DBM CFG variable wert Die Werte aller Variablen konnen mit GET DBM CFG angezeigt werden. Naheres ndet sich in der Dokumentation von IBM (Com]). In der Dokumentation der DB2-Extender traten folgende Unstimmigkeiten auf: ♦ ♦ ♦ nicht DB2IMAGE (bzw.BeiDB2AUDIO der UDF content wird als "handle\ oder DB2VIDEO) angegeben, sondern der Name der Spalte vom Datentyp DB2Image (DB2Audio, DB2Video). Im Gegensatz zur Beschreibung darf d Konvertierung sein. ussen kleingeschrieDie Postscript-Formate EPS, EP2, PS, ben werden, die anderen Formate werden grogeschrieben. 56 Beispiel: SELECT DISTINCT name FROM raw_image WHERE mmdbsys.format(ext_image)='GIF' OR mmdbsys.format(ext_image)='ps' Unschon ist auch, da Bilder in Postscript-Formaten nicht skaliert werden konnen (weder mit der UDF content noch mit db2image). Auch dies wird in der Dokumentation nicht erwahnt. Ein weiterer Schwachpunkt ist, da die Funktion db2image Skalierungen nur mit gleichzeitiger Formatumwandlung erlaubt. Sollen beispielsweise die Bilder im Referenzformat zusatzlich in einer schwacheren Qualitat gespeichert werden (als Ergebnis einer Optimierung), so mussen die Bilder mit der UDF content skaliert und temporar gespeichert werden und konnen erst dann mit db2image in die Datenbank eingefugt werden. Mit content ist u brigens das Skalieren ohne Konvertierung moglich. Auch diese Anomalie ist es nicht wert, in der Dokumentation erwahnt zu werden. Schlielich erlauben die DB2-Extender pro Tabelle nur eine Spalte des Datentyps DB2Image. Dies war in dieser Arbeit kein Problem, konnte aber fur andere Anwendungen durchaus eine enorme Einschrankung darstellen. U.U. kann dies zu einem unnotigen und inezienten Splitting von Datenbanktabellen fuhren, die bei Querys durch teure Joins wieder zusammengefuhrt werden mussen. Die hier aufgefuhrten De zite der DB2-Extender kosteten bei der Implementierung viel Zeit. Es ware zu wunschen, da IBM in zukunftigen Versionen oder Fixpacks diese Probleme lost oder zumindest die Dokumentation etwas praziser und ausfuhrlicher gestaltet. 6. Resumee und Ausblick Die Zahl der Benutzer im Internet wachst stetig an, ein Ende ist nicht abzusehen. Die entsprechend hohe Netzlast reduziert die Transfergeschwindigkeit, so da die Anzeige oder das Download von Daten hau g zu einer Geduldsprobe fur den User wird. Gangige Methoden, dieses Problem zu mildern, sind: ♦ ♦ ♦ lation neuer Hochgeschwindigkeitsleitungen den langsamen Transatlantik-Datenverkehr zu umgehen Proxyserver Verbesserung der Hardwarevoraussetzun Spiegelung von Webservern an geograph Verwendung einer intelligenten Cacheve In dieser Arbeit wurde ein erganzender Ansatz gewahlt: Dokumente sollen in verschiedenen Qualitatsstufen angeboten werden, denn zum Durchbrowsen genugen dem Benutzer meist schwache Auosungen (geringe Groe, kaum Netzbelastung, kurze Ladezeiten). Interessiert er sich fur einen Artikel genauer, so kann dieser dann in besserer Qualitat angezeigt werden. Der Web- bzw. Datenbankserver mu die Dokumente also in verschiedenen Qualitatsstufen bereitstellen. Aufgrund der Heterogenitat der verwendeten Hard(ISDN, Modem, LAN usw.) und Software (z.B. unterschiedliche Browser, Viewer und Player) sollten insbesondere Multimediadokumente auch in verschiedenen Formaten zur Verfugung stehen. Da aber die Speicherung aller Formate und Auosungen zu einem enormen Speicherbedarf fuhren kann, mu zwischen zu speichernden und zu konvertierenden Formaten und Qualitaten entschieden werden. Dazu wurden in dieser Arbeit Algorithmen implementiert und ausfuhrlich getestet. Die Szenarien verdeutlichten, da bereits durch geringen Speichermehraufwand auf der Benutzerseite viel Zeit eingespart werden kann. Dadurch konnen auch die Betriebskosten von Unternehmen gesenkt werden, da die Mitarbeiter weniger Arbeitszeit zum Herunterladen von Multimendiadokumenten benotigen. Das verwendete Kostenmodell ist der Realitat bereits recht gut angepat: Festplattenkosten, Datentransferraten und Konvertierungszeiten gehen direkt in das Modell ein. 58 Die moglichen Formate hangen von der verwendeten Software ab: Die DB2Extender unterstutzen 14 meist gangige Formate (siehe Seite 3). Dies reicht sicher fur viele Anwendungen aus, ist aber naturlich bei weitem nicht vollstandig. Insbesondere ist bedauerlich, da das Format PNG (portable network graphics), dessen Bedeutung im Internet stetig wachst, noch nicht zur Verfugung steht. Moglicherweise stellt IBM in zukunftigen Versionen der DB2-Extender noch mehr Formate bereit. Falls man nicht solange warten will, hat man die Moglichkeit, zusatzliche Konvertierungstools zu verwenden. Fur die Optimierung macht dies keinen Unterschied, da dafur lediglich die Dauer der Formatumwandlung relevant ist. Trotzdem muten etliche Anpassungen vorgenommen werden: 1. Die Tabelle raw_image braucht eine zusatzliche Spalte (Datentyp: Blob), da unter ext_image nur von den DB2-Extendern unterstutzte Formate verwaltet werden konnen. 2. In conversion ist eine zusatzliche Spalte notig, die angibt, von welchem Tool die jeweilige Konvertierung durchzufuhren ist. 3. Das Einfugen der Bilder in neuen Formaten erfordert eine Anpassung der Methode insert_raw_image der Klasse Optimization: Statt der UDF db2image mu hier das zus atzliche Konvertierungstool und dessen Syntax berucksichtigt werden. Der Einsatz zusatzlicher Formate erfordert also nur geringe Mehrarbeit. Trotzdem sollte dies aus Performancegrunden soweit wie moglich vermieden werden, denn zum einen entsteht ein zusatzlicher Verwaltungsaufwand (Erweiterung der Tabellen und des Quellcodes), zum andern fuhren die zusatzlichen Funktionen zu erhohtem Rechen- und Speicherbedarf. Die UDFs der DB2-Extender konnen hingegen auf einem vom Datenbanksystem speziell fur UDFs angelegten Speicherbereich ausgefuhrt werden, so da hier kein zusatzlicher Speicher belegt wird. In dieser Arbeit wurde speziell die Formatoptimierung fur Bilder implementiert. Fur Audio- und Videodaten ist ein analoges Vorgehen moglich: Auch hier gibt es verschiedene Formate, die Qualitat wird hier aber nicht durch die Auosung, sondern durch die Samplingrate (in Samples sec ) bestimmt. Zukunftige Internet-Standards wie XML1 (Extensible Markup Language) in Verbindung mit XSL2 (Extensible Stylesheet Language) und CSS3 (Cascading Style Sheets) unterstutzen zunehmend die Trennung semantischer Inhalte der Web-Seiten von ihrer Display-Information. Insbesondere hier entstehen neue Einsatzfelder fur (selbst-optimierende) Multimedia-Datenbanksysteme. http://www.w3.org/xml/ http://www.w3.org/style/xsl/ 3 http://www.w3.org/style/css/ 1 2 A. Shell-Skripte Diese Programme dienen dem einfachen Anlegen und Fullen der von der Optimierung benotigten Tabellen. Sie konnen bei Bedarf aus dem Internet1 runtergeladen werden. A.1. Anlegen der Tabellen Dieses Programm legt die Datenbanktabellen an, die dazugehorige Datei heit create tables.sql. #! /bin/ksh ################################################# # This shell-script creates tables for the # optimization # # creating the tables image, raw_image, # query_profile, conversion, optimization # ################################################# # connect to the database stefandb db2 connect to stefandb # delete existing tables db2 drop table image db2 drop table raw_image db2 drop table query_profile db2 drop table conversion db2 drop table opti_log ### image: ### -----db2 create table image\ "("\ name varchar"("100")" primary key not null,\ description varchar"("1000")"\ ")" ### raw_image: ### ---------db2 create table raw_image\ "("\ 1 http://heron.informatik.uni-augsburg.de/tmplobs/doc/main.htm A.1 Anlegen der Tabellen ext_image mmdbsys.db2image primary key not null,\ name varchar"("100")",\ quality integer,\ static integer,\ foreign key "("name")" references image\ ")" ### conversion: ### ----------db2 create table conversion\ "("\ source_format varchar"("10")" not null,\ source_quality integer not null,\ target_format varchar"("10")" not null,\ target_quality integer not null,\ z_hist double,\ avg_conv_time integer,\ is_allowed integer,\ primary key "("source_format,target_format,\ source_quality,target_quality")"\ ")" ### query_profile: ### -------------db2 create table query_profile\ "("\ date_time timestamp primary key not null,\ name varchar"("100")",\ source_format varchar"("10")" ,\ source_quality integer,\ target_format varchar"("10")" ,\ target_quality integer,\ target_image_sz integer,\ conv_time integer,\ age integer,\ foreign key "("name")" references image,\ foreign key "("source_format,target_format,\ source_quality,target_quality")" \ references conversion\ ")" ### opti_log: ### ------------db2 create table opti_log\ "("\ date_time timestamp primary key not null,\ static_format varchar"("10")",\ z double,\ c_s double,\ c_a double,\ c_c double,\ p int,\ q int,\ number_of_images int,\ hd_size varchar"("50")",\ hd_cost varchar"("50")",\ 60 A.2 Einfugen der Bildinformation (gekurzt) comp_time total_time acc_cost_preopt store_cost_preopt acc_cost_saveall store_cost_saveall acc_cost_saveno store_cost_saveno acc_cost_opt store_cost_opt a_phys ")" 61 int,\ int,\ int,\ int,\ int,\ int,\ int,\ int,\ int,\ int,\ varchar"("450")"\ # disconnect all db2 connect reset # enable tables and columns for the DB2-Extenders db2ext connect to stefandb db2ext enable table raw_image for db2image db2ext enable column raw_image ext_image for db2image db2ext connect reset ### end of file A.2. Einfugen der Bildinformation (gekurzt) Hier wird die Tabelle image mit Name und Beschreibung der Bilder gefullt. Die Datei heit insert image.sql. #! /bin/ksh ################################################ # # Shell-script for inserting the hagar-data # into the table image # ################################################ # connect to stefandb db2 connect to stefandb # delete existing rows db2 delete from image # insert new rows db2 insert into image values \ "(""'"achtzehn"'","'"Ach ja, ich war auch schon mal Achtzehn..."'"")",\ "(""'"achten"'","'"Es ist nicht so schlimm...Aber achte einige Tage \ darauf, was Du isst"'"")",\ . . . A.3 Einfugen der Bilder (gekurzt) 62 "(""'"wollschmetterling"'","'"Ein harter Winter"'"")",\ "(""'"zapfhahn"'","'"He, Haegar! Sieh Dir das mal an!"'"")" # disconnect db2 connect reset # end of file A.3. Einfugen der Bilder (gekurzt) Zum Einfugen der Bilder in die Tabelle raw image wird die UDF benotigt. Die auszufuhrende Datei heit insert_raw_image.sql. #! /bin/ksh ################################################ # # Shell-script for inserting the hagar-pictures # into the table raw_image # ################################################ # connect to stefandb db2 connect to stefandb # delete existing rows db2 delete from raw_image # insert new rows db2 insert into raw_image values \ "("mmdbsys.DB2Image"("CURRENT SERVER,"'"/home/db2inst3/\ DA/image/static_raw_image/achtzehn.gif"'",\ "'"ASIS"'",0,"'" "'"")","'"achtzehn"'",100,1")" db2 insert into raw_image values \ "("mmdbsys.DB2Image"("CURRENT SERVER,"'"/home/db2inst3/\ DA/image/static_raw_image/achten.gif"'",\ "'"ASIS"'",0,"'" "'"")","'"achten"'",100,1")" . . . db2 insert into raw_image values \ "("mmdbsys.DB2Image"("CURRENT SERVER,"'"/home/db2inst3/\ DA/image/static_raw_image/wollschmetterling.gif"'",\ "'"ASIS"'",0,"'" "'"")","'"wollschmetterling"'",100,1")" db2 insert into raw_image values \ "("mmdbsys.DB2Image"("CURRENT SERVER,"'"/home/db2inst3/\ DA/image/static_raw_image/zapfhahn.gif"'",\ "'"ASIS"'",0,"'" "'"")","'"zapfhahn"'",100,1")" # disconnect db2 connect reset # end of file db2image B. Programmcode In diesem Kapitel werden die Quelltexte aufgelistet. Sie konnen auch aus dem Internet1 runtergeladen werden. B.1. Die Webseite An die Hagar-Datenbank konnen u ber das Internet2 Anfragen gestellt werden. Zur Erstellung der Webseite wurde das Tool Net.Data3 von IBM verwendet. %{ ************************************************************************** Define Section: Use this section to define variables (e.g. DATABASE) used in your macro file. At a minimum, the DATABASE variable must be defined. ************************************************************************** %} %DEFINE{ DATABASE="stefandb" SHOWSQL="NO" get_image= %EXEC "/home/db2inst4/bin/image2file $(name) $(format) $(scal)" %} %{ ************************************************************************** Function query: Use this section to define SQL queries. ************************************************************************** %} %FUNCTION(DTW_SQL) query1() { select name,description from db2inst4.image %REPORT{ %ROW{ <dd><input type="radio" name="name" value="$(V1)"> $(V2) %} %} %} %{ ************************************************************************** INPUT Section: Use this section to specify the page (in HTML) to http://heron.informatik.uni-augsburg.de/tmplobs/doc/main.htm http://heron.informatik.uni-augsburg.de/db2www-bin/db2www/da1 net.d2w/input 3 http://www.software.ibm.com/data/net.data 1 2 B.1 Die Webseite be used to collect information from the user to be used in the query. Note how the value of ACTION specifies the report section of this macro file. When the user selects the "Submit Query" button, the REPORT section specified below will be processed. ************************************************************************** %} %HTML(INPUT){ <HTML> <HEAD> <TITLE>The big Hagar collection</TITLE> </HEAD> <BODY BACKGROUND="/pictures/tan_paper.gif"> <p> <H1> Querying the HAGAR-database </H1> <p> <hr> <FORM METHOD="POST" ACTION="/db2www-bin/db2www/da1_net.d2w/report"> First, choose a picture ... <p> <dl> @query1() </dl> <p> <hr> ... then select a format ... <p> <dd><input type="radio" name="format" value="BMP"> BMP: Microsoft Windows bitmap <dd><input type="radio" name="format" value="eps"> EPS: Encapsulated PostScript <dd><input type="radio" name="format" value="ep2"> EP2: Encapsulated level 2 PostScript <dd><input type="radio" name="format" value="GIF"> GIF: Compuserve GIF89a and 87 <dd><input type="radio" name="format" value="IMG"> IMG: IOCA Image <dd><input type="radio" name="format" value="IPS"> IPS: Brooktrout FAX card file <dd><input type="radio" name="format" value="JPG"> JPG: JPEG(3) <dd><input type="radio" name="format" value="PCX"> PCX: PC paint file <dd><input type="radio" name="format" value="PGM"> PGM: Portable gray map <dd><input type="radio" name="format" value="ps"> PS: PostScript <dd><input type="radio" name="format" value="psc"> PSC: Compressed PostScript image <dd><input type="radio" name="format" value="ps2"> PS2: PostScript level 2 <dd><input type="radio" name="format" value="TIF"> TIF: All TIFF 5.0 formats <dd><input type="radio" name="format" value="YUV"> YUV: Digial video for YUV 64 B.2 Das CGI-Programm 65 <p> <hr> ... and the scaling factor ... <p> <dd><input type="radio" name="scal" value="s1"> 100 % <dd><input type="radio" name="scal" value="s2"> 75 % <dd><input type="radio" name="scal" value="s3"> 50 % <dd><input type="radio" name="scal" value="s4"> 25 % <p> <hr> ... and finally klick on the "Submit"-Button. <hr> <INPUT TYPE="submit" VALUE="Submit"> </FORM> </BODY> </HTML> %} %{ ************************************************************************** REPORT Section: Use this section to specify the page (in HTML) to be seen after the SQL queries are executed. ************************************************************************** %} %HTML(REPORT){ $(get_image) <HTML> <HEAD> <TITLE>Show the selected hagar picture</TITLE> </HEAD> <BODY BACKGROUND="/pictures/tan_paper.gif"> Please klick <a href="/tmplobs/$(name)$(scal).$(format)">here</a>. </BODY> </HTML> %} B.2. Das CGI-Programm Zur Formatkonvertierung und Skalierung verwendet die Webseite das CGIProgramm image2file (Dateiname image2file.sqc). Hier werden auch die Anfragen registriert und damit die Tabelle query_profile gefullt. #include <stdio.h> #include <string.h> #include <sqlenv.h> int main(int argc, char *argv ]) { EXEC SQL INCLUDE SQLCA EXEC SQL BEGIN DECLARE SECTION char dbname 10] = "stefandb" B.2 Das CGI-Programm char char char char char name 100] filename 100] = *name_pointer = *format_pointer *scal_pointer = 66 "/usr/local/apache/htdocs/tmplobs/" argv 1] = argv 2] argv 3] char target_format 10] short target_quality long target_image_size char scal 10] char msgbuffer 500] SQL TYPE IS BLOB_FILE newpicture char source_format 10],sf 10] short source_quality,sq long source_image_size = 0 char dat_tim1 26] char dat_tim2 26] long timdif1, timdif2, timdif char command 30] = "chmod a+r " short i EXEC SQL END DECLARE SECTION EXEC SQL WHENEVER SQLERROR GO TO badnews /**** get the parameters name, format, scal ****/ i=0 do { name i]=*name_pointer name_pointer++ i++ } while(*name_pointer!='\0') name i]='\0' i=0 do { target_format i]=*format_pointer format_pointer++ i++ } while(*format_pointer!='\0') target_format i]='\0' scal 0]=*scal_pointer scal 1]=*(scal_pointer+1) scal 2]='\0' /**** create the filename and prepare the newpicture-variable strcat(filename,name) strcat(filename,scal) strcat(filename,".") strcat(filename,target_format) strcpy(newpicture.name,filename) ****/ B.2 Das CGI-Programm 67 newpicture.name_length = strlen(newpicture.name) newpicture.file_options = SQL_FILE_OVERWRITE if if if if (strcmp(scal,"s1")==0) (strcmp(scal,"s2")==0) (strcmp(scal,"s3")==0) (strcmp(scal,"s4")==0) target_quality target_quality target_quality target_quality = = = = 100 75 50 25 putenv("DB2INSTANCE=db2inst4") EXEC SQL CONNECT to :dbname EXEC SQL SELECT DISTINCT CURRENT TIMESTAMP INTO :dat_tim1 FROM db2inst4.image /**** get the picture without conversion if possible ****/ EXEC SQL SELECT mmdbsys.content(ext_image), mmdbsys.format(ext_image), mmdbsys.size(ext_image),quality INTO :newpicture, :source_format, :source_image_size, :source_quality FROM db2inst4.raw_image WHERE name = :name AND quality = :target_quality AND mmdbsys.format(ext_image) = :target_format target_image_size = source_image_size i = 0 /**** else convert the picture ****/ if(source_image_size == 0) { EXEC SQL SELECT source_format, source_quality INTO :sf, :sq FROM db2inst4.conversion WHERE target_format = :target_format AND target_quality = :target_quality AND is_allowed=1 /**** compute the right scaling factor ****/ if(sq == 100) { if(target_quality == 100) strcpy(scal,"-s 1.0") else if(target_quality == 75) strcpy(scal,"-s 0.75") else if(target_quality == 50) strcpy(scal,"-s 0.50") else strcpy(scal,"-s 0.25") } else if(sq == 75) { if(target_quality == 75) strcpy(scal,"-s 1.0") else if(target_quality == 50) strcpy(scal,"-s 0.67") else strcpy(scal,"-s 0.33") } else if(sq == 50) { if(target_quality == 50) strcpy(scal,"-s 1.0") else strcpy(scal,"-s 0.5") } else strcpy(scal,"-s 1.0") EXEC SQL SELECT mmdbsys.content(ext_image, :target_format, :scal), B.3 Java und JDBC Programme 68 mmdbsys.format(ext_image), mmdbsys.size(ext_image), quality INTO :newpicture, :source_format, :source_image_size, :source_quality FROM db2inst4.raw_image WHERE name = :name AND quality = :sq AND mmdbsys.format(ext_image) = :sf target_image_size = newpicture.data_length i = 1 } EXEC SQL SELECT DISTINCT CURRENT TIMESTAMP INTO :dat_tim2 from db2inst4.image /**** get the duration for the conversion ****/ EXEC SQL SELECT DISTINCT minute(:dat_tim1)*60000+second(:dat_tim1)*1000+ trunc(microsecond(:dat_tim1)/1000,0), minute(:dat_tim2)*60000+second(:dat_tim2)*1000+ trunc(microsecond(:dat_tim2)/1000,0) INTO :timdif1,:timdif2 FROM db2inst4.image timdif=i*(timdif2-timdif1) strcat(command,filename) system(command) /*** put the data into the table "query_profile" ***/ EXEC SQL INSERT INTO db2inst4.query_profile VALUES( CURRENT TIMESTAMP, :name, :source_format, :source_quality, :target_format, :target_quality, :target_image_size, :timdif,0) EXEC SQL COMMIT EXEC SQL CONNECT RESET return 0 badnews: printf("Unexpected return code from DB2. \n") sqlaintp(msgbuffer, 500, 70, &sqlca) printf("Message: %s\n",msgbuffer) return 0 } B.3. Java und JDBC Programme In diesem Abschnitt werden die Java-Quellcodes der Klassen Attribut und Optimization aufgelistet. Diese und die u brigen Klassen nden sich auch im Internet4 . 4 http://heron.informatik.uni-augsburg.de/tmplobs/doc/main.htm B.3 Java und JDBC Programme B.3.1. Attribut.java Attribute werden in einer eigenen Klasse abgelegt. /** * class Attribut contains data about the attributes */ public class Attribut { /** * format of the attribut */ protected String format /** * quality of the attribut */ protected int quality /** * avg_image_size <= 2 GB */ protected int avg_image_size /** * 0 <= avg_acc <= 1 */ protected double avg_acc /** * bit_used = 1 if the set of the physical stored attributs * during the current optmization step contains this attribut * else bit_used = 0 */ protected int bit_used /** * bit_best = 1 for the optimal set * of physical stored attributs */ protected int bit_best /** * access cost of this attribut */ protected double acc_cost /** * avg_conv_time contains the * converting duration from the static_format * (avg_conv_time 0]), and from the "better" * formats to this format, e.g. if attribut = GIF50 * then avg_conv_time 1] is the duration of * GIF100 -> GIF50 and avg_conv_time 2] is the time for * GIF75 -> GIF50 */ protected int ] avg_conv_time 69 B.3 Java und JDBC Programme /** * constructor for an attribut, it's used by * the class Optimization */ protected Attribut(String form,int qual, int size, double avg_a) { format = form quality = qual avg_image_size = size avg_acc = avg_a bit_used = 0 bit_best = 0 avg_conv_time = new int 4] } // End of construktor /** * test if two attributs are equal */ protected boolean equals(Attribut a) { if((format.compareTo(a.format)==0) && (quality == a.quality)) return true else return false } // end of method equals } // end of class Attribut B.3.2. Optimization.java In diesem Programm ndet die eigentliche Optimierung statt. import java.io.* import java.util.* import java.sql.* /** * the class Optimization contains the optimization algorithm */ public class Optimization { /** * z is the weight of the acc_cost and (1-z) is the weight of * store_cost */ public double z /** * c_s is the factor of the store_cost * (only relevant if use_stepfunction = false) */ public double c_s /** * c_a is the factor of the acc_cost for physical stored attributes 70 B.3 Java und JDBC Programme */ public double c_a /** * c_c is the factor of the avg_conv_time */ public double c_c /** * p is the minimal number of requests for an * attribut that should be relevant for the optimization */ public int p /** * q is the maximal number of optimization runs for * each entry in the query_profile */ public int q /** * if use_total_access = false than the average access rate * is the weight of the access costs * else the total number of accesses is used */ public boolean use_total_access /** * if use_total_store = true the total used storage of * all physical saved attributes is relevant, * else the optimization algorithm uses just * the average used storage of each attribute */ public boolean use_total_store /** * if use_stepfunction = true then the parameters * hd_size and hd_cost are used else the paramter * c_s is used */ public boolean use_stepfunction /** * hd_size are the sizes (MB) of the hard disks * (only used if use_stepfunction = true) */ public int ] hd_size /** * hd_cost are the costs for each hd_disk * (only used if use_stepfunction = true) */ public int ] hd_cost // variables for the static attribut private String static_format 71 B.3 Java und JDBC Programme private int static_quality = 100 private int static_acc_cost // number of images private int num // variables for the costs private int cost_pre_opt, cost_post_opt, cost_save_all, cost_save_no private int store_cost_pre_opt, store_cost_post_opt private int store_cost_save_all, store_cost_save_no private int acc_cost_pre_opt, acc_cost_post_opt private int acc_cost_save_all, acc_cost_save_no // variable for the optimization time (ms) private int comp_time // variable for the total time (including image conversion) private int total_time // list for the attributs private Vector attribut_list = new Vector() // list for A_phys private Vector a_phys_list = new Vector() // strings for error messages and result private String error = "", result static { try { Class.forName("COM.ibm.db2.jdbc.app.DB2Driver") } catch ( ClassNotFoundException x ) { System.out.println("\nERROR loading DB2-Driver") x.printStackTrace() } } /** * this is a constructor for Optimization objects, * it's used by the class Opti */ public Optimization(double z1, double c_s1, double c_a1, double c_c1, int min, int max, int ] hs, int ] hc, boolean total, boolean use_hd, boolean total_acc) { z = z1 c_s = c_s1 c_a = c_a1 c_c = c_c1 p = min 72 B.3 Java und JDBC Programme q = max hd_size = hs hd_cost = hc use_total_store = total use_stepfunction = use_hd use_total_access = total_acc } /* * this method prepares the statistical data and * runs the optimization algorithm */ public String start(Opti caller) { Connection con try { con = DriverManager.getConnection("jdbc:db2:stefandb") // preparing ... caller.output.setText("preparing data ... ") total_time = (int)System.currentTimeMillis() get_static_attribut(con) update_conversion1(con) get_attributs(con) update_attributs(con) update_query_profile(con) caller.output.appendText("done\n") con.close() }catch(SQLException x) { error += "\nERROR(method start): getConnection to stefandb \n"+ x.getMessage() } // computing ... comp_time = (int)System.currentTimeMillis() caller.output.appendText("computing ... ") optimization_algorithm() caller.output.appendText("done") comp_time = (int)System.currentTimeMillis() - comp_time result="\nresult:\n=======\n\nacc_cost_pre_opt: "+acc_cost_pre_opt+ "\nstore_cost_pre_opt: "+store_cost_pre_opt+"\ncost_pre_opt: "+ cost_pre_opt+ "\n\nacc_cost_save_all: "+acc_cost_save_all+ "\nstore_cost_save_all: "+store_cost_save_all+"\ncost_save_all: "+ cost_save_all+ "\n\nacc_cost_save_no: "+acc_cost_save_no+ "\nstore_cost_save_no: "+store_cost_save_no+"\ncost_save_no: "+ cost_save_no+ "\n\nacc_cost_post_opt: "+acc_cost_post_opt+ "\nstore_cost_post_opt: "+store_cost_post_opt+"\ncost_post_opt: "+ cost_post_opt+"\n\n" int i = 0 while(i < attribut_list.size()) 73 B.3 Java und JDBC Programme { Attribut a = (Attribut)attribut_list.elementAt(i) result += "\n"+a.format+a.quality+" is_saved: "+a.bit_best i++ } total_time = (int)System.currentTimeMillis() - total_time if(error.compareTo("") == 0) return result else return error } // end of method start /** * this method updates the database, e.g. * converting pictures, deleting attributs, ... */ public String update_database(Opti caller) { Connection con try { total_time = total_time - (int)System.currentTimeMillis() con = DriverManager.getConnection("jdbc:db2:stefandb") caller.output.setText("\ndeleting images ... ") delete_raw_image(con) caller.output.appendText("done\ninserting pictures ... ") insert_raw_image(con, caller) caller.output.appendText("done\nupdating table conversion ... ") update_conversion2(con) caller.output.appendText("done\n") total_time = (int)System.currentTimeMillis() + total_time // store the optimization-log in the database save_log(con) con.close() }catch(SQLException x) { error = "\nERROR (method update database): getConnection to stefandb\n"+ x.getMessage() } if(error.compareTo("") != 0) return error else return "Everything ok!" } // end of method update_database // get static_format and static_acc_cost private void get_static_attribut(Connection con) { String sql = "SELECT mmdbsys.format(ext_image),mmdbsys.size(ext_image) "+ "FROM raw_image WHERE static=1" try { Statement stmt = con.createStatement() ResultSet rs = stmt.executeQuery(sql) 74 B.3 Java und JDBC Programme num = 0 static_acc_cost = 0 while(rs.next()) { static_format = rs.getString(1) static_acc_cost += rs.getInt(2) num++ } static_acc_cost = (int)(c_a*(static_acc_cost/num)) rs.close() stmt.close() }catch(SQLException x) { error += "\nERROR (method get_static_attribut: "+ "SELECT ... static_acc_cost \n"+ x.getMessage() } } // end of method get_static_attribut // update the conversion duration in the // table conversion private void update_conversion1(Connection con) { String sql = "SELECT source_format, source_quality, "+ "target_format, target_quality, "+ "AVG(conv_time) FROM query_profile "+ "WHERE age = 0 AND conv_time > 0 "+ "GROUP BY source_format, source_quality, "+ "target_format, target_quality " try { Statement stmt = con.createStatement() ResultSet rs = stmt.executeQuery(sql) while(rs.next()) { sql = "UPDATE conversion SET "+ "avg_conv_time = CAST((z_hist * avg_conv_time) + "+ "((1 - z_hist) * "+rs.getInt(5)+") AS INTEGER)"+ "WHERE source_format = '"+rs.getString(1)+"' "+ "AND source_quality = "+rs.getInt(2)+" "+ "AND target_format = '"+rs.getString(3)+"' "+ "AND target_quality = "+rs.getInt(4) try { Statement stmt2 = con.createStatement() stmt2.executeUpdate(sql) stmt2.close() }catch(SQLException x) { error += "\nERROR (method update_conversion1: "+ "UPDATE on conversion \n"+ x.getMessage() 75 B.3 Java und JDBC Programme } } // end of while(rs.next()) rs.close() stmt.close() }catch(SQLException x) { error += "\nERROR (method update_conversion1: "+ "SELECT on query_profile \n"+ x.getMessage() } } // end of method update_conversion1 // get the used attributs from the table query_profile private void get_attributs(Connection con) { int acc_sum = 0 try { Statement stmt = con.createStatement() String sql = "SELECT target_format, target_quality, "+ "AVG(target_image_sz), count(*) "+ "FROM query_profile "+ "WHERE age < "+q+" "+ "GROUP BY target_format,target_quality "+ "HAVING count(*) >= " + p ResultSet rs = stmt.executeQuery(sql) while(rs.next()) { String format = rs.getString(1) int quality = rs.getInt(2) // don't take the static_format if((format.compareTo(static_format) != 0) || (quality != static_quality)) { Attribut a = new Attribut(format, quality, rs.getInt(3), (double)rs.getInt(4)) attribut_list.addElement(a) acc_sum += a.avg_acc } } rs.close() stmt.close() }catch(SQLException x) { error += "\nERROR (method get_attributs): "+ "SELECT on query_profile \n"+ x.getMessage() } if(!(use_total_access)) { int i = 0 76 B.3 Java und JDBC Programme while(i < attribut_list.size()) { Attribut a = (Attribut)attribut_list.elementAt(i) a.avg_acc /= acc_sum i++ } } } // end of method get_attributs // get converting times and avg_image_size private void update_attributs(Connection con) { int i = 0 while(i < attribut_list.size()) { Attribut a = (Attribut)attribut_list.elementAt(i) String sql = "SELECT avg_conv_time FROM conversion "+ "WHERE target_format='"+a.format+"' "+ "AND target_quality="+a.quality+" "+ "AND source_format='"+static_format+"' "+ "AND source_quality="+static_quality try { Statement stmt = con.createStatement() ResultSet rs = stmt.executeQuery(sql) rs.next() a.avg_conv_time 0] = rs.getInt(1) rs.close() stmt.close() }catch(SQLException x) { error += "\nERROR (method update_attributs): "+ "SELECT on conversion (1)\n"+ x.getMessage() } sql = "SELECT avg_conv_time, source_quality "+ "FROM conversion "+ "WHERE target_format='"+a.format+"' "+ "AND target_quality="+a.quality+" "+ "AND source_format='"+a.format+"' "+ "AND source_quality>"+a.quality+" "+ "ORDER BY source_quality DESC" try { Statement stmt = con.createStatement() ResultSet rs = stmt.executeQuery(sql) int j = 1 while(rs.next()) { a.avg_conv_time j] = rs.getInt(1) j++ } rs.close() 77 B.3 Java und JDBC Programme stmt.close() }catch(SQLException x) { error += "\nERROR (method update_attributs): "+ "SELECT on conversion (2)\n"+ x.getMessage() } i++ } // end of while(i < attribut_list.size()) String sql = "SELECT DISTINCT mmdbsys.format(ext_image), "+ "quality FROM raw_image WHERE static = 0" try { Statement stmt = con.createStatement() ResultSet rs = stmt.executeQuery(sql) while(rs.next()) { String f = rs.getString(1) int q = rs.getInt(2) Attribut a = new Attribut(f,q,0,0) a_phys_list.addElement(a) i = 0 while(i < attribut_list.size()) { Attribut b = (Attribut)attribut_list.elementAt(i) if(((b.format).compareTo(f) == 0) && (b.quality == q)) { sql = "SELECT AVG(mmdbsys.size(ext_image)) "+ "FROM raw_image "+ "WHERE mmdbsys.format(ext_image)='"+ b.format+"' AND quality="+b.quality try { Statement stmt2 = con.createStatement() ResultSet rs2 = stmt2.executeQuery(sql) rs2.next() b.avg_image_size = (int)rs2.getDouble(1) rs2.close() stmt2.close() b.bit_used = 1 }catch(SQLException x) { error += "\nERROR (method update_attributs): "+ "SELECT AVG on raw_image \n"+ x.getMessage() } } i++ } // end of while(i < attribut_list.size()) } // end of while(rs.next()) rs.close() stmt.close() 78 B.3 Java und JDBC Programme }catch(SQLException x) { error += "\nERROR (method update_attributs): "+ "SELECT on raw_image \n"+ x.getMessage() } } // end of method update_attributs // set age = age + 1 for each row in the query_profile // and delete querys older than q private void update_query_profile(Connection con) { String sql = "UPDATE query_profile SET age = age + 1" Statement stmt try { stmt = con.createStatement() stmt.executeUpdate(sql) stmt.close() }catch(SQLException x) { error += "\nERROR (method update_query_profile): "+ "UPDATE on query_profile \n"+ x.getMessage() } sql = "DELETE FROM query_profile "+ "WHERE age >= "+q try { stmt = con.createStatement() stmt.executeUpdate(sql) stmt.close() }catch(SQLException x) { error += "\nERROR (method update_query_profile): "+ "DELETE on query_profile \n"+ x.getMessage() } } // end of method update_query_profile // get each subset of the attributs private boolean increment_attribut_list_bit_used() { int i = 0 int j = 0 try { while(i < attribut_list.size()) { j = ((Attribut)attribut_list.elementAt(i)).bit_used %2 79 B.3 Java und JDBC Programme ((Attribut)attribut_list.elementAt(i)).bit_used = (j+1)%2 if(j == 0) break i++ } } catch (Exception x) { error += "\nERROR (method increment_attribut...): "+ "increment_attribut_list_bit_used \n"+ x.getMessage() } if(i == attribut_list.size()) return false else return true } // end of increment_attribut_list_bit_used // compute the storage_cost private double compute_store_cost() { int i = 0 double s_cost = 0 int hd_c = 0 try { while(i < attribut_list.size()) { if(((Attribut)attribut_list.elementAt(i)).bit_used == 1) { if(use_total_store) s_cost += num* ((Attribut)attribut_list.elementAt(i)).avg_image_size else s_cost += ((Attribut)attribut_list.elementAt(i)).avg_image_size } i++ } if(use_stepfunction) { double size_mb = s_cost / 1000000 hd_c = hd_cost 0] i = 0 while(true) { if(size_mb > hd_size i]) { size_mb -= hd_size i] if(hd_size i+1] > 0) i++ hd_c += hd_cost i] } else break } if(s_cost == 0) hd_c = 0 } }catch(Exception x) { 80 B.3 Java und JDBC Programme error += "\nERROR (method compute_store_cost): "+ "compute_store_cost \n"+ x.getMessage() } if(use_stepfunction) return(hd_c) else return (c_s*s_cost) } // end of method compute_store_cost // compute the access_cost private double compute_access_cost() { double a_cost = 0 try { // compute acc_cost(A), A is in A_phys int i = 0 while(i < attribut_list.size()) { Attribut a = (Attribut)attribut_list.elementAt(i) a.acc_cost = a.bit_used * c_a * a.avg_image_size i++ } // compute acc_cost(A), A is in A_comp i = 0 while(i < attribut_list.size()) { Attribut a = (Attribut)attribut_list.elementAt(i) if(a.bit_used == 0) { int j = 0,k = 0 String form = static_format int qual = static_quality while(j < attribut_list.size()) { Attribut b = (Attribut)attribut_list.elementAt(j) if((b.bit_used == 1) && ((b.format).compareTo(a.format) == 0) && (b.quality <= qual) && (b.quality > a.quality)) { form = b.format qual = b.quality k = j } j++ } if((form.compareTo(static_format) == 0) || ((a.format).compareTo("eps") == 0) || ((a.format).compareTo("ep2") == 0) || ((a.format).compareTo("ps") == 0) || ((a.format).compareTo("psc") == 0) || ((a.format).compareTo("ps2") == 0)) j = 0 else if(qual == 100) j = 1 81 B.3 Java und JDBC Programme else if(qual == 75) j = 2 else if(qual == 50) j = 3 Attribut b = (Attribut)attribut_list.elementAt(k) if(j == 0) a.acc_cost = static_acc_cost + c_c * a.avg_conv_time j] else a.acc_cost = b.acc_cost + c_c * a.avg_conv_time j] } i++ } // end of while(i < attribut_list.size()) // compute the acc_cost of all attributes i = 0 while(i < attribut_list.size()) { Attribut a = (Attribut)attribut_list.elementAt(i) a_cost += a.acc_cost * a.avg_acc i++ } } catch(Exception x) { error += "\nERROR (method compute_access_cost): "+ "compute_acc_cost \n"+ x.getMessage() } return a_cost } // end of method compute_access_cost // the real optimization ... private void optimization_algorithm() { try { // pre optimization costs store_cost_pre_opt = (int)compute_store_cost() acc_cost_pre_opt = (int)compute_access_cost() cost_pre_opt = (int)((1-z)*compute_store_cost() + z*compute_access_cost()) int i = 0 while(i < attribut_list.size()) { ((Attribut)attribut_list.elementAt(i)).bit_used = 0 i++ } // no attributs are saved store_cost_save_no = (int)compute_store_cost() acc_cost_save_no = (int)compute_access_cost() cost_save_no = (int)((1-z)*store_cost_save_no+ z*acc_cost_save_no) store_cost_post_opt = store_cost_save_no acc_cost_post_opt = acc_cost_save_no cost_post_opt = cost_save_no // compute the best subset of physical stored attributs while(increment_attribut_list_bit_used()) { store_cost_save_all = (int)compute_store_cost() 82 B.3 Java und JDBC Programme acc_cost_save_all = (int)compute_access_cost() cost_save_all = (int)((1-z)*compute_store_cost() + z*compute_access_cost()) if(cost_save_all < cost_post_opt) { store_cost_post_opt = store_cost_save_all acc_cost_post_opt = acc_cost_save_all cost_post_opt = cost_save_all int j = 0 while(j < attribut_list.size()) { ((Attribut)attribut_list.elementAt(j)).bit_best =((Attribut)attribut_list.elementAt(j)).bit_used j++ } } } }catch(Exception x) { error += "\nERROR (method optimization_algorithm): "+ "optimization_algorithm \n"+ x.getMessage() } } // End of optimization_algorithm private void delete_raw_image(Connection con) { String sql = "SELECT DISTINCT mmdbsys.format(ext_image), quality "+ "FROM raw_image WHERE static = 0" try { Statement stmt = con.createStatement() ResultSet rs = stmt.executeQuery(sql) while(rs.next()) { String f = rs.getString(1) int q = rs.getInt(2) int i = 0 while(i < attribut_list.size()) { Attribut a = (Attribut)attribut_list.elementAt(i) if(((a.format).compareTo(f) == 0) && (a.quality == q) && (a.bit_best == 1)) break i++ } if(i == attribut_list.size()) { String filename = "/home/db2inst4/DA/image/raw_image/" String suffix = "" if(q == 100) suffix="s1." else if(q == 75) 83 B.3 Java und JDBC Programme suffix="s2." else if(q == 50) suffix="s3." else suffix="s4." sql = "DELETE FROM raw_image WHERE "+ "(mmdbsys.format(ext_image)= '"+f+"')"+ " AND (quality= "+q+") AND (static=0)" try { Statement stmt2 = con.createStatement() stmt2.executeUpdate(sql) stmt2.close() }catch(SQLException x) { error += "\nERROR (method delete_raw_image): "+ "DELETE on raw_image \n"+ x.getMessage() } // Delete also files containing the pictures File f1 = new File(filename) String ] list = f1.list() String name = suffix + f int k = 0 while(k < list.length) { if(list k].endsWith(name)) { File f2 = new File(filename + list k]) f2.delete() } k++ } k = 0 while(k < a_phys_list.size()) { Attribut a = (Attribut)a_phys_list.elementAt(k) if(((a.format).compareTo(f) == 0) && (a.quality == q)) a_phys_list.removeElementAt(k) k++ } } // end of if(i = attribut_list.size()) } // end of while(rs.next()) } catch (SQLException x) { error += "\nERROR (method delete_raw_image): "+ "SELECT on raw_image \n"+ x.getMessage() } } // end of method delete_raw_image private void insert_raw_image(Connection con, Opti caller) { 84 B.3 Java und JDBC Programme int i = 0 while(i < attribut_list.size()) { Attribut a = (Attribut)attribut_list.elementAt(i) // target should be saved in raw_image if(a.bit_best == 1) { int j = 0 // is target already in raw_image? while(j < a_phys_list.size()) { Attribut b = (Attribut)a_phys_list.elementAt(j) if(a.equals(b)) break j++ } if(j >= a_phys_list.size()) { String suffix String option if(a.quality==100) { suffix = "s1." option = "-s 1" } else if(a.quality==75) { suffix = "s2." option = "-s 0.75" } else if(a.quality==50) { suffix = "s3." option = "-s 0.5" } else { suffix = "s4." option = "-s 0.25" } suffix = suffix.concat(a.format) // get the static_raw_images String sql = "SELECT name,mmdbsys.filename(ext_image) "+ "FROM raw_image WHERE static=1" try { caller.output.append("\n"+a.format+a.quality+": ") Statement stmt = con.createStatement() ResultSet rs = stmt.executeQuery(sql) // convert each image while(rs.next()) { caller.output.append(".") String name = rs.getString(1) String filename = rs.getString(2) String filename_new = 85 B.3 Java und JDBC Programme "/home/db2inst4/DA/image/raw_image/" filename_new = filename_new.concat(name) filename_new = filename_new.concat(suffix) // DB2Image-UDFs need casting! // writing converted picture into // the .../raw_image directory if(static_format.compareTo(a.format)==0) { String tmpfile = "/home/db2inst4/DA/tmp/tmp" sql = "SELECT mmdbsys.content(ext_image,CAST('"+tmpfile+ "' AS LONG VARCHAR),1, CAST('"+static_format+ "' AS VARCHAR(8)), CAST('"+option+ "' AS VARCHAR(100))) "+ "FROM raw_image "+ "WHERE static=1 AND quality = 100 AND "+ "name = '"+name+"'" Statement stmt3 = con.createStatement() ResultSet rs2 = stmt3.executeQuery(sql) rs2.next() rs2.close() stmt3.close() filename = tmpfile sql = "INSERT INTO raw_image VALUES("+ "mmdbsys.DB2Image(CURRENT SERVER," + "CAST('"+filename+"' AS LONG VARCHAR),"+ "CAST('"+static_format+"' AS VARCHAR(8)),"+ "CAST('"+a.format+"' AS VARCHAR(8)),"+ "CAST('"+filename_new+"' AS LONG VARCHAR)"+ ",' '),'"+name+"',"+a.quality+",0)" } else { sql = "INSERT INTO raw_image VALUES("+ "mmdbsys.DB2Image(CURRENT SERVER," + "CAST('"+filename+"' AS LONG VARCHAR),"+ "CAST('"+static_format+"' AS VARCHAR(8)),"+ "CAST('"+a.format+"' AS VARCHAR(8)),"+ "CAST('"+option+"' AS VARCHAR(100)),"+ "CAST('"+filename_new+"' AS LONG VARCHAR)"+ ",' '),'"+name+"',"+a.quality+",0)" } try { Statement stmt2 = con.createStatement() stmt2.executeUpdate(sql) stmt2.close() }catch(SQLException x) { error += "\nERROR (method insert_raw_image): "+ "INSERT on raw_image \n"+ x.getMessage() } } // end of while(rs.next()) 86 B.3 Java und JDBC Programme rs.close() stmt.close() }catch(SQLException x) { error += "\nERROR (method insert_raw_image): "+ "SELECT on raw_image \n"+ x.getMessage() } // add target to A_phys Attribut b = new Attribut(a.format,a.quality,0,0) a_phys_list.addElement(b) } // end of if(j >= attribut_list.size()) } // end of if(a.bit_best == 1) i++ } // end of while(i < attribut_list.size()) } // end of method insert_raw_image // update the table conversion private void update_conversion2(Connection con) { String sql = "UPDATE conversion SET is_allowed=0" Statement stmt try { // first set is_allowed=0 for all conversions stmt = con.createStatement() stmt.executeUpdate(sql) stmt.close() }catch(SQLException x) { error += "\nERROR (method update_conversion2): "+ "UPDATE on conversion (1) \n"+ x.getMessage() } int i = 0 while(i < a_phys_list.size()) { Attribut a = (Attribut)a_phys_list.elementAt(i) int j = 0 int min = 0 while(j < a_phys_list.size()) { Attribut b = (Attribut)a_phys_list.elementAt(j) if(((a.format).compareTo(b.format)==0) && (b.quality>min) && (b.quality < a.quality)) min = b.quality j++ } sql = "UPDATE conversion SET is_allowed=1 WHERE "+ "(source_format = '"+a.format+ "') AND (source_quality = "+a.quality+")"+ 87 B.3 Java und JDBC Programme " AND (target_format = '"+a.format+ "') AND (target_quality <= "+a.quality+ ") AND (target_quality > "+min+ ") AND NOT ((source_format = 'eps' OR "+ "source_format = 'ep2' OR source_format = 'ps' OR "+ "source_format = 'psc' OR source_format = 'ps2') AND "+ "source_quality != target_quality)" try { stmt = con.createStatement() stmt.executeUpdate(sql) stmt.close() }catch(SQLException x) { error += "\nERROR (method update_conversion2): "+ "UPDATE on conversion (2) \n"+ x.getMessage() } i++ } // end of while(i < attribut_list.size()) sql = "SELECT target_format,target_quality FROM conversion "+ "GROUP BY target_format,target_quality "+ "HAVING max(is_allowed)=0" try { stmt = con.createStatement() ResultSet rs = stmt.executeQuery(sql) while(rs.next()) { sql = "UPDATE conversion SET is_allowed=1 WHERE "+ "(source_format='"+static_format+ "') AND (source_quality="+static_quality+ ") AND (target_format='"+rs.getString(1)+ "') AND (target_quality="+rs.getInt(2)+")" try { Statement stmt2 = con.createStatement() stmt2.executeUpdate(sql) stmt2.close() }catch(SQLException x) { error += "\nERROR (method update_conversion2): "+ "UPDATE on conversion (3) \n"+ x.getMessage() } } // end of while(rs.next()) rs.close() stmt.close() }catch(SQLException x) { error += "\nERROR (method update_conversion2): "+ 88 B.3 Java und JDBC Programme "SELECT on conversion \n"+ x.getMessage() } } // end of method update_conversion2 private void save_log(Connection con) { String hd = "", hc = "" int i = 0 while(i < hd_size.length) { hd += hd_size i] + " " hc += hd_cost i] + " " i++ } String a_phys = "" i = 0 while(i < a_phys_list.size()) { Attribut a = (Attribut)a_phys_list.elementAt(i) a_phys += a.format + a.quality + " " i++ } String sql = "INSERT INTO opti_log VALUES("+ "CURRENT TIMESTAMP,'"+ static_format+"',"+ z+","+ c_s+","+ c_a+","+ c_c+","+ p+","+ q+","+ num+",'"+ hd+"','"+ hc+"',"+ comp_time+","+ total_time+","+ acc_cost_pre_opt+","+ store_cost_pre_opt+","+ acc_cost_save_all+","+ store_cost_save_all+","+ acc_cost_save_no+","+ store_cost_save_no+","+ acc_cost_post_opt+","+ store_cost_post_opt+",'"+ a_phys+"')" try { Statement stmt = con.createStatement() stmt.executeUpdate(sql) stmt.close() } catch (SQLException x) { error += "\nERROR (method save_log): "+ 89 B.3 Java und JDBC Programme "INSERT on opti_log \n"+ x.getMessage() } } // end of method save_log } // end of class Optimization 90 Literaturverzeichnis BB99] Jon Bosak und Tim Bray. Mehr Tempo auf der Datenautobahn. Neue Web-Sprache XML. Spektrum der Wissenschaft, Seiten 74 { 79, 7/99. Cha96] Don Chamberlin. Using the new DB2. Morgan Kaufmann Publishers, 1996. Com] Command Reference. http://www.software.ibm.com/cgibin/db2www/library/document.d2w/report?fn=db2n003.htm. CW97] Mary Campione und Kathy Walrath. Das Java Tutorial. AddisonWesley, 1997. Ext] DB2 Universal Database Image, Audio, and Video Extenders Administration and Programming. http://www.software.ibm.com/cgibin/db2www/library/document.d2w/report?fn=dmba5m03.htm. KEUB+ 98] Werner Kieling, Katharina Erber-Urch, Wolf-Tilo Balke, Thomas Birke und Matthias Wagner. The HERON Project | Multimedia Database Support for History and Human Sciences. In: Rudolf Kruse (Herausgeber): 28. Annual Conference of the German Computer Society (GI): INFORMATIK98, LNCS, Seiten 309{318, Magdeburg, Germany, September 1998. Springer Verlag Heidelberg. KK98] Werner Kieling und Gerhard Kostler. Multimedia-Kurs Datenbanksysteme. Springer-Verlag, 1998. KKK97] Gerhard Kostler, Wolfgang Kowarschick und Werner Kieling. Client-Server Optimization for Multimedia Document Exchange. In: Proceedings of the Fifth International Conference on Database Systems for Advanced Applications, Seiten 135{144, Melbourne, Australia, April 1997. Mo98] Bernhard Moller. Skript zur Vorlesung Informatik II. Institut fur Informatik, Universitat Augsburg, 1998. MS93] Jim Melton und Alan R. Simon. Understanding the new SQL: A complete guide. Morgan Kaufmann Publishers, 1993. Literaturverzeichnis Rie97] Sie56] 92 Peter Rieger. Implementierung einer Client-Server-Optimierung fur den Austausch von Multimedia-Dokumenten. Diplomarbeit, Universitat Augsburg, 1997. Johann Siebmacher. Siebmachers groes Wappenbuch. Bauer & Raspe, 1856.