Dalitz Datenbanken Hochschule Niederrhein Erforderliche Vorkenntnisse für Elektrotechnik-Studenten für das Fach “Datenbanksysteme” bei Prof. Dalitz Stand: 3. April 2013 1 Algorithmus und Turing-Vollständigkeit Ein Algorithmus ist eine Folge von Handlungsanweisungen, mit denen aus einer Eingabe in endlich vielen Schritten ein Ausgabe erzeugt wird. Diese Definition ist unklar, solange nicht gesagt wird, worauf sich die Handlungsanweisungen beziehen. Üblicherweise wird diese Definition auf TuringMaschinen bezogen, die ein einfaches Modell für einen Computer sind [1]. Wenn ein Problem nicht durch einen Algorithmus gelöst werden kann, dann heißt dieses Problem nicht berechenbar. Ein Beispiel dafür aus dem Bereich der Datenbanksysteme ist das Problem, bei einer beliebigen gegebenen Definition von Triggern zu entscheiden, ob die ausgelöste Triggerfolge terminiert. Dies bedeutet, dass es keinen allgemeinen Algorithmus gibt der diese Antwort automatisch für jede beliebige Triggerdefinition ausspuckt. Im Einzelfall kann es natürlich sein, dass diese Frage entschieden werden kann. Das berühmteste unentscheidbare Problem ist das Halteproblem [1]. Eine Programmiersprache, mit der alle Turing-Maschinen Algorithmen formulierbar sind, heißt Turingvollständig. Die Programmiersprachen C, C++ oder Python sind alle Turing-vollständig, SQL jedoch nicht. 2 Laufzeitkomplexität Die Laufzeit eines Programms ist die Anzahl der benötigten Rechenschritte. Offensichtlich hängt sie von der Länge n des Inputs ab: Das Sortieren von 200 Datensätzen wird in der Regel länger dauern als das Sortieren von 20 Datensätzen. Da die Laufzeit auch bei gegebener Inputlänge n noch von der konkreten Eingabe abhängt, betrachtet man die worst case Laufzeit, also die maximale Laufzeit bei fester Inputgröße n. Üblicherweise interessiert nicht die genaue Laufzeit eines Algorithmus (z.B. 7n2 + 3n − 1) sondern nur der führende Term der Laufzeit (z.B. n2 ). Formalisiert wird die Laufzeitabschätzung durch die Landau-Symbole, von denen wir nur die Abschätzung nach oben (“Groß-O”) benötigen: f (n) ∈ O(g(n)) ⇐⇒ f (n) <∞ g(n) n→∞ lim sup So ist z.B. die Laufzeit 7n2 + 3n − 1 in O(n2 ). Bemerkungen: a) In der Analysis wird meist ein anderes Landau-Symbol verwendet (z.B. beim Restglied der Taylorreihe): das “Klein-O”. Dieses bedeutet etwas anderes, so dass es nicht mit “Groß-O” verwechselt werden sollte. Dalitz Datenbanken Hochschule Niederrhein b) Machen Sie sich anhand der Definition klar, dass sowohl 5n2 ∈ O(7n2 ) ist, als auch 7n2 ∈ O(5n2 ). Mit anderen Worten: konstante Vorfaktoren spielen bei der “Groß-O”-Notation keine Rolle. 3 Regular Expressions Ein regulärer Ausdruck (regular expression, “regexp”) ist eine Zeichenfolge, die für eine Menge von Strings steht, z.B. ba* = {b, ba, baa, baa, . . .} Die meisten Zeichen stehen für sich selbst, aber ein paar Zeichen haben eine Sonderbedeutung: mit runden Klammern können Gruppen gebildet werden, “*” bedeutet “keinmal oder beliebig häufige Wiederholung”, “ε” ist der Leerstring, “|” steht für “oder”. Beispiel: (a|b)(cd)* = {a, b, acd, bcd, acdcd, bcdcd, . . .} Anwendungsprogramme und Programmierbibliotheken orientieren sich üblicherweise am Standard POSIX 1003.2, der folgende Notationen definiert [2]: . [ ] ( ) | * + ? {n,m} ˆ $ einzelnes Zeichen alternative Zeichen, Bereich mit [a-z], Negierung mit [ˆa-z] Gruppierung “oder”-Alternative Sternoperator (beliebig häufige Wiederholung) mindestens einfache Wiederholung einmal oder keinmal n- bis m-fache Wiederholung, auch {n,} oder {n} oder {,m} spezielle Anker für String- bzw. Zeilen-Anfang und -Ende Die Sonderzeichen können mit dem Backslash (“\”) escaped werden. Der Leerstring ist in POSIX nicht “ε” sondern “()”. 4 Wichtige Algorithmen Wichtige Datenbank-Probleme sind das Suchen und Sortieren. Wenn auf n Objekten eine Ordnung definiert ist und die Objekte sortiert sind, dann kann ein Objekt in der Laufzeit O(log(n)) mittels binärer Suche gefunden werden. Für das vergleichsbasierte Sortieren kann man allgemein zeigen, dass es keinen Algorithmus mit einer worst-case Laufzeit besser als O(n log n) geben kann. Tatsächlich gibt es Algorithmen, die diese untere Schranke annehmen, z.B. Heap-Sort oder Merge-Sort. Der meist verwendete Algorithmus Quicksort hat nur eine mittlere Laufzeit O(n log n), aber eine worst-case Laufzeit O(n2 ) [3] Bemerkung: die Einschränkung “vergleichsbasiertes Sortieren” ist deshalb wichtig, weil man auch schneller sortieren kann, wenn man schon weiß welche Werte vorkommen (z.B. natürliche Zahlen in einem beschränkten Wertebereich): dann kann man in linearer Zeit, also O(n) sortieren [3]. Dalitz 5 Datenbanken Hochschule Niederrhein Graphen Ein Graph ist eine Menge von Knoten und Kanten, die die Knoten verbinden. Bei einem gerichteten Graphen können Kanten nur in eine Richtung gegangen werden, bei ungerichteten Graphen in beide. Ist jeder Kante ein Kostenwert (“Gewicht”) zugewiesen, so heißt der Graph gewichtet. Literatur [1] Asteroth, Baier: Theoretische Informatik. Pearson Studium, 2002 [2] Peek, O’Reilly, Loukides: Unix Power Tools. O’Reilly, 1993 [3] Ottmann, Widmayer: Algorithmen und Datenstrukturen. Spektrum Akademischer Verlag, 4. Auflage, 2002