Der SQL-Compiler schreibt Abfragen um, um Abfrageoperationen zu verschieben und die Abfrage dadurch so umzustrukturieren, daß die Anzahl der Operationen und Vergleichselemente minimiert wird. Die folgenden Beispiele zeigen einige der Operationen, die vom SQL-Compiler verschoben werden können:
Während des Umschreibens kann das Optimierungsprogramm die Operation DISTINCT dahin verschieben, wo sie am günstigsten ausgeführt werden kann. In dem gezeigten Beispiel wird die Operation DISTINCT vollständig entfernt.
Während des Umschreibens kann die Reihenfolge der Vergleichselemente, die angewendet werden, geändert werden, so daß die Vergleichselemente, die die Auswahl in größerem Maße einschränken, zum frühstmöglichen Zeitpunkt berücksichtigt werden.
Wenn in einer partitionierten Datenbankumgebung für das Verschieben von Ergebnismengen zwischen den Datenbankpartitionen ein hoher Aufwand erforderlich ist. Den Umfang des Rundsendebetriebs an andere Datenbankpartitionen und/oder die Anzahl der Rundsendevorgänge zu reduzieren ist eines der Ziele beim Umschreiben von Abfragen.
Für das folgende Abfragebeispiel wird angenommen, daß die Spalte EMPNO als Primärschlüssel der Tabelle EMPLOYEE definiert wurde:
SELECT DISTINCT EMPNO, FIRSTNME, LASTNAME FROM EMPLOYEE
Diese Abfrage würde so umgeschrieben, daß die Klausel DISTINCT entfernt wird:
SELECT EMPNO, FIRSTNME, LASTNAME FROM EMPLOYEE
Da hier der Primärschlüssel ausgewählt wird, weiß der SQL-Compiler, daß jede zurückgelieferte Zeile bereits eindeutig ist. In diesem Fall wird das Schlüsselwort DISTINCT nicht benötigt. Wenn die Abfrage nicht umgeschrieben wird, erstellt das Optimierungsprogramm einen Plan, der die nötigen Verarbeitungsschritte (z. B. einen Sortiervorgang) enthält, um sicherzustellen, daß die Spalten eindeutig sind.
Durch das Ändern der Ebene, auf der Vergleichselemente normalerweise angewendet werden, läßt sich eventuell eine Leistungsverbesserung erreichen. Zum Beispiel sei die folgende Sicht gegeben, die eine Liste aller Mitarbeiter der Abteilung "D11" zusammenstellt:
CREATE VIEW D11_EMPLOYEE (EMPNO, FIRSTNME, LASTNAME, PHONENO, SALARY, BONUS, COMM) AS SELECT EMPNO, FIRSTNME, LASTNAME, PHONENO, SALARY, BONUS, COMM FROM EMPLOYEE WHERE WORKDEPT = 'D11'
Es wird nun die folgende Abfrage aufgesetzt:
SELECT FIRSTNME, PHONENO FROM D11_EMPLOYEE WHERE LASTNAME = 'BROWN'
In der Phase des Umschreibens verschiebt der Compiler das Vergleichselement LASTNAME = 'BROWN' nach unten in die Sicht D11_EMPLOYEE. Dadurch kann das Vergleichselement früher und möglicherweise effektiver angewendet werden. Die tatsächliche Abfrage, die in diesem Beispiel zur Ausführung kommen könnte, lautet folgendermaßen:
SELECT FIRSTNME, PHONENO FROM EMPLOYEE WHERE LASTNAME = 'BROWN' AND WORKDEPT = 'D11'
Das Verschieben von Vergleichselementen ist nicht auf Sichten beschränkt. Beispiele anderer Situationen, in denen Vergleichselemente verschoben werden können, sind Klauseln UNION, GROUP BY und abgeleitete Tabellen (verschachtelte Tabellenausdrücke oder allgemeine Tabellenausdrücke).
In einer partitionierten Datenbankumgebung kann der SQL-Compiler die folgende Abfrage umschreiben:
Lokalisieren aller Mitarbeiter, die in der Programmierung arbeiten und unterbezahlt sind.
SELECT P.PROJNO, E.EMPNO, E.LASTNAME, E.FIRSTNAME, E.SALARY+E.BONUS+E.COMM AS COMPENSATION FROM EMPLOYEE E, PROJECT P WHERE P.EMPNO = E.EMPNO AND P.PROJNAME LIKE '%PROGRAMMING%' AND E.SALARY+E.BONUS+E.COMM < (SELECT AVG(E1.SALARY+E1.BONUS+E1.COMM) FROM EMPLOYEE E1, PROJECT P1 WHERE P1.PROJNAME LIKE '%PROGRAMMING%' AND P1.PROJNO = A.PROJNO AND E1.EMPNO = P1.EMPNO)
Da die Abfrage korreliert ist und wahrscheinlich weder PROJECT noch EMPLOYEE über die Spalte PROJNO partitioniert sind, wird möglicherweise jedes Projekt im Rundsendebetrieb an jede Datenbankpartition übermittelt. Außerdem müßte die Unterabfrage viele Male ausgewertet werden.
Der SQL-Compiler kann die Abfrage wie folgt umschreiben:
WITH DIST_PROJS(PROJNO, EMPNO) AS (SELECT DISTINCT PROJNO, EMPNO FROM PROJECT P1 WHERE P1.PROJNAME LIKE '%PROGRAMMING%')
AVG_PER_PROJ(PROJNO, AVG_COMP) AS (SELECT P2.PROJNO, AVG(E1.SALARY+E1.BONUS+E1.COMM) FROM EMPLOYEE E1, DIST_PROJS P2 WHERE E1.EMPNO = P2.EMPNO GROUP BY P2.PROJNO)
SELECT P.PROJNO, E.EMPNO, E.LASTNAME, E.FIRSTNAME, E.SALARY+E.BONUS+E.COMM AS COMPENSATION FROM PROJECT P, EMPLOYEE E, AVG_PER_PROG A WHERE P.EMPNO = E.EMPNO AND P.PROJNAME LIKE '%PROGRAMMING%' AND P.PROJNO = A.PROJNO AND E.SALARY+E.BONUS+E.COMM < A.AVG_COMP
Die umgeschriebene SQL-Abfrage berechnet AVG_COMP je Projekt (AVG_PRE_PROJ) und kann das Ergebnis an alle Datenbankpartitionen übermitteln, in denen die Tabelle EMPLOYEE enthalten ist.