DBII-Klausur 18.1.2002 Aufgabe 1) a) Erläutern Sie die wesentlichen Schritte, die eine relationale Datenbank bei der Ausführung einer SQL-Anweisung durchführt. • • • • • Parsen Zerlegung in Tokens und Transformation in Ausdrucksbaum auf Basis der SQL-Grammatik Validieren Überprüfung der Gültigkeit der Relations-, Attributnamen und Korrektheit von Typen durch Systemkatalog Initialen Plan erzeugen Transformation des Ausdrucks in einen Ausdrucksbaum der Relationenalgebra Anfrage restrukturieren Algebraische Umformungen nach gewissen heuristischen Prinzipien (Pushdown Selektion/Projektion; Natural- statt Crossjoin etc.) Ausführbaren Plan erzeugen Kostenschätzung; Entscheidung über Zugriffsmechanismen und –algorithmen; Transformation des Zugriffsplans in binäre Struktur b) Erklären Sie den Unterschied zwischen statischem und dynamischem SQL. • • Statisches SQL: Statement steht zur Übersetzungszeit fest (nur Parameter änderbar, die durch Hostvariablen übergeben werden) Dynamisches SQL: Anweisungen können zur Laufzeit konstruiert werden (Anweisungsstrings werden erst zur Laufzeit von der Anwendung zur Datenbank übergeben) c) Weshalb gibt es zwei Formen von dynamischem SQL, die Form execute immediate und die Form prepare/execute? Möchte man dieselbe Anweisung mit verschiedenen Suchkriterien mehrmals verwenden, würde bei execute immediate derselbe Zugriffsplan immer wieder neu erzeugt. Bei prepare/execute geschieht dies in 2 Schritten: Erst wird der Zugriffsplan zur Laufzeit erzeugt, dann wird er verwendet (auch mehrfach). Aufgabe 2) a) strcpy(search_pattern, „A%“); exec sql select custid, cname into :kundennr, :name from customer where cname like :search_pattern; erlaubt; statisches SQL. Es werden nur SQL-Parameter verändert, die durch Hostvariablen übergeben werden. Zugriffsplan wird erstellt; nur die Filterbedingung wird zur Laufzeit eingefügt. b) kundennr = 145; strcpy(update_table, „customer“); exec sql update :update_table set name = ‘Schneider’ where custid = :kundennr; nicht erlaubt; kein Zugriffsplan erzeugbar. Dies ist statisches SQL und da muss die SQL-Anweisung zur Compilezeit feststehen. Wie soll das gehen ohne dass der Tabellenname bekannt ist? Die Validierung schlägt fehl. c) strcpy(update_table, „customer“); sprintf (statement, „update %s set name = ‚Schneider’ where custid = 145”, update_table); exec sql execute immediate :statement; erlaubt; das ist dynamisches SQL. Es wird sowieso alles zur Laufzeit entschieden. Aufgabe 3) Sie haben ein Client/Server-Programm erstellt, das mit der Datenbank A des Herstellers A arbeitet. Das Management entscheidet nun, die Datenbank B des Herstellers B einzusetzen. Idealerweise haben Sie sich in der Programmierung strikt an den SQL-Standard gehalten und auch die beiden Datenbank-Hersteller erfüllen den Standard vorbildlich. Die Abteilung „Datenbank-Administration“ hat den Datenbankserver auf das neue Produkt B bereits umgestellt. Ihre Aufgabe ist es, die Umstellung der Clients (die unter Windows laufen) vorzunehmen. Kreuzen Sie in folgender Tabelle diejenigen Schritte an, die Sie durchführen müssen, je nachdem, ob das Programm mit embedded SQL oder mit ODBC entwickelt wurde. Tätigkeit Client-Software von Hersteller B installieren Programm auf neue DB anpassen Bisherige Programmquellen neu übersetzen Übersetzten Programmcode mit neuen DB-Bibliotheken linken In der Systemsteuerung den Verweis der Datenquelle des Programms Von DB A auf DB B ändern Das bisherige Programm aufrufen und ausführen eSQL ODBC ja * nein ja ja ** ja *** ja * Voraussetzung: Zugangsdaten sind gleich geblieben (Bei ODBC erübrigt sich’s, da die Zugangsdaten in der Systemsteuerung in der registrierten Datenquelle mit hinterlegt sind) ** Es gibt keinen Verweis in der Systemsteuerung *** das neu kompilierte und gelinkte Programm ist nicht das bisherige… Aufgabe 4) In JDBC kann man eine Datenquelle beim Verbindungsaufbau direkt im Quellcode angeben, z. B. durch folgende Anweisung: Connection con = DriverManager.getConnection(„jdbc:odbc:azamon“, „dba“, „sql“); Stattdessen hat man aber auch die Möglichkeit, eine DataSource zu registrieren, die unter einem frei wählbaren Namen ansprechbar ist. Die Registrierung geschieht beim Java Naming and Directory Interface (JNDI). Im Programm kann man dann JNDI verwenden, um eine Datenquelle über den gewählten Namen zu ermitteln und eine Connection herzustellen. Warum wird in der Spezifikation von JDBC empfohlen, die zweite Technik für den Verbindungsaufbau zur Datenbank zu verwenden? (Hinweis: Welche Kopplung zwischen Programm und DB ergibt sich aus der 1. Technik?) Es wird ein logischer Name für die Datenquellen verwendet. Durch den Namendienst, der auf die JDBC-Datenquellen verweist, müssen nicht auf jedem Client die Datenquellen eingetragen bzw. geändert werden. Darüber hinaus bieten DataSource-Objekte Unterstützung verteilter Transaktionen. Aufgabe 5) Folgendes Programm in JDBC wird von javac anstandslos übersetzt. Wenn man es startet, erhält man jedoch eine Exception und eine kryptische Meldung, in der irgendwas über Invalid descriptor index steht. Wo liegt der Fehler? Erläutern Sie ihn und korrigieren Sie den Code. public class falsch{ class. Forname(„sun.jdbc.odbc.JdbcOdbcDriver“); Connection con = DriverManager.getConnection (“jdbc:odbc:azamon”, “dba”, “sql”); Statement stmt = con. createStatement(); ResultSet rs = stmt.executeQuery (“select count(*) from Books”); rs.next(); System.out.println(“Anzahl der Bücher:“+rs.getString(0)); stmt.close(); con.close(); } Spaltennummerierung beginnt bei JDBC bei 1. Korrektur: rs.getString(1); Aufgabe 6) Skizzieren Sie, wie man in JDBC volldynamische Zugriffe auf eine DB programmiert. Wir möchten die SQL-Anweisung select * from customer durchführen, wissen jedoch nicht, wie die Tabelle customer aufgebaut ist. Die Ergebnismenge soll ausgegeben werden; dabei sollen die Spalten Überschriften tragen, nämlich gerade die Namen der jeweiligen Spalte in der Tabelle. Schreiben Sie Pseudocode, der angibt, welche Schritte zu tun sind. Sie können voraussetzen, dass bereits eine Connection zur DB besteht. (Es kommt nicht darauf an, dass Sie die Namen von Methoden oder Klassen exakt wiedergeben, sondern dass die notwendigen Schritte richtig angegeben sind.) Metainfos über Aufbau der Ergebnismenge holen o ResultSet rs = execQuery(select * from customer); o Rs.next() //Spaltenanzahl ermitteln int anzcols = rs.getNumberOfCols(); //Spaltenüberschriften ausgeben for(i = 1, i<=anzcols; i++){ print rs.col.name(); } o do{ // restliche Zeilen anzeigen for(i = 1, i<=anzcols; i++){ print rs.col.inhalt(); } }while(rs.next()); Aufgabe 7) In einer verteilten DB sei die globale Relation Abt( AbtNr, Name, Bereich, ManagerPersNr, Budget ) Horizontal fragmentiert, so dass die Tabelle Abt1, gespeichert auf Site 1, alle Zeilen mit Bereich <= 50 und die Tabelle Abt2, gespeichert auf Site 2, alle Zeilen im Bereich > 50 enthält. Bsp. Für die Durchführung von Anweisungen: Die Anweisung select Name from Abt wird zerlegt in die beiden Anweisungen select Name from Abt1 und select Name from Abt2. Die union der Anweisungen ergibt das Ergebnis. Erläutern Sie, wie folgende Anweisungen durchgeführt werden können: a) update Abt set Name = ‚Verkauf’ where AbtNr = 50 update Abt1 set Name = ‘Verkauf’ where AbtNr = 50; update Abt2 set Name = ‘Verkauf’ where AbtNr = 50; 2 Queries erforderlich, da Fragmentierung nicht nach Selektionsbedingung b) update Abt set Budget = Budget * 1.05 where Bereich = 12 update Abt1 set Budget = Budget * 1.05 where Bereich = 12; Nur 1 Query erforderlich, da Fragmentierung nach Selektionsbedingung c) update Abt set Bereich = 2 where Bereich = 99 Begin Transaction Insert into Abt1 (select AbtNr, Name, 2 , ManagerPersNr, Budget from Abt2 where Bereich = 99) Delete from Abt2 where Bereich = 99; End Transaction Tricky tricky... Selektionsbedingung entspricht Fragmentierung und genau dieses Attribut wird verändert. Der Datensatz läge nach der Änderung also auf der falschen Site. Daher erst auf richtige Site einfügen, auf falscher löschen. (An sich: Update auf 2. Site, in 1. einfügen, auf 2. löschen) d) select sum( Budget ) from Abt select sum1+sum2 from select sum(Budget) as sum1 from Abt1, select sum(Budget) as sum2 from Abt2 Auf beiden Sites parallel Summe bilden, dann Summe aus beiden Summen e) delete from Abt where Bereich < 12 delete from Abt1 where Bereich < 12; Aufgabe 8) Erläutern Sie, was man in einer verteilten DB unter horizontaler und vertikaler Fragmentierung versteht. Stellen Sie außerdem für jeden Typ dar, wie man die jeweilige Fragmentierung einer Tabelle durch relationale Operationen erreichen kann, und wie man die Daten wieder zusammenführt. a) Horizontale Fragmentierung Tabellen werden anhand eines Selektionskriteriums zeilenweise auf verschiedene Sites aufgeteilt. Aufteilung durch Selektion; Zusammenführung durch union. b) Vertikale Fragmentierung Tabellen werden spaltenweise durch Projektion auf verschiedene Sites aufgeteilt. Auf allen Sites muss ein gemeinsamer Key vorhanden sein, damit Zusammenführung über verlustfreien (Natural) Join möglich ist. Aufgabe 9) Erläutern Sie die Begriffe synchrone und asynchrone Replikation und nennen Sie Gründe, weshalb in der Regel in verteilten DB heute die asynchrone Replikation verwendet wird. Geben Sie jeweils zwei Techniken der Synchronisation an. a) Synchrone Replikation Alle Kopien werden gleichzeitig aktualisiert und sind auf aktuellem Stand. ROWA (Read-one-Write-all): Lesetransaktion auf eine Kopie, geschrieben wird auf allen gleichzeitig. Problem: Schreibzugriffsgeschwindigkeit richtet sich nach der langsamsten Kopie Abstimmverfahren: Transaktion beendet wenn Mehrheit der Kopien aktualisiert. Problem: Lesen aufwändiger, da auch 1 mehr als die Anzahl der Minderheit gelesen werden muss, um anhand des Zeitstempels rauszufinden welche die aktuellste ist. b) Asynchrone Replikation Masterkopie: Updatetransaktionen nur an Masterkopie (später Weitergabe an Kopien), Lesetransaktion egal wo. Problem: Je nachdem wie groß Aktualisierungsintervall ist, können inaktuelle Daten gelesen werden Peer-to-Peer: Updatetransaktionen auf jedes Exemplar möglich, Lesen auch Problem: Weiterleitungsverfahren erforderlich und Priorisierung (Konfliktlösungsstrategie): Es könnten ja 2 Änderung am gleichen Datensatz, aber auf verschiedenen Exemplaren erfolgen c) Gründe für Bevorzugung asynchroner Replikation • • Kostenersparnis Ermöglichung mobiler DB, die nicht immer online und damit aktuell sein können (und müssen) Aufgabe 10) In folgender Situation soll ein verteilter Join durchgeführt werden. Sie entscheiden sich für einen Semijoin, den Sie in Hamburg durchführen. Beschreiben Sie das Vorgehen, insbesondere, welche und wie viele Daten von Hamburg nach München und dann von München nach Hamburg übertragen werden müssen. Tabelle Kunde ( KNr char(8), Name, Vorname, Firmensitz, …) Tabelle Angebot ( ANr, Knr char(8), Datum, …) Tabelle Kunde ist in HH gespeichert; sie enthält 1000 Datensätze, davon 100 Kunden mit Firmensitz in Lübeck. Die KNr dieser Kunden beginnen mit einer 2. Tabelle Angebot ist in München gespeichert; sie hat 10000 Datensätze à 1024 Bytes, davon 1000, bei denen die KNr mit einer 2 beginnt. Select * from Kunde, Angebot where Kunde.KNr = Angebot.KNr and Firmensitz = ‚Lübeck’ • • • HH: 100 Kundennummern à 8 Byte = 800 Byte nach M schicken (Alle Kunden mit Firmensitz Lübeck) M: hier Join => max. 1024 * 1000 (Datensatzgröße * passende Datensätze) = 1024000 nach HH (Alle Datensätze aus Angebot gesamt, die Join-Bedingung Kunde.Knr = Angebot.KNr erfüllen) HH: Join über diese Daten und Tabelle Kunde