Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 11.0.1 (Deutsch) » SQL Anywhere Server - SQL-Benutzerhandbuch » Abfrageverarbeitung » Abfragen optimieren und ausführen » Semantische Abfragentransformation

 

Outer-Joins in Inner-Joins konvertieren

Der Optimizer generiert eine links-tiefe Prozessverarbeitungsstruktur für die Zugriffspläne. Die einzige Ausnahme bei dieser Regel ist das Vorhandensein eines Ausdrucks mit einem rechts-tiefen verschachtelten Outer-Join. Für die Algorithmen der Abfrageausführungs-Engine zum Berechnen der Left- oder Right-Outer-Joins müssen in einer Join-Strategie bewahrende Tabellen vor Nullwert-liefernden Tabellen stehen. Daher sucht der Optimierer nach Möglichkeiten, die Left- oder Right-Outer-Joins, sofern möglich, in Inner-Joins zu konvertieren, da Inner-Joins umwandelbar sind und dem Optimierer mehr Freiheit lassen, wenn die Join-Enumeration durchgeführt wird.

Ein Left- oder Right-Outer-Join wird zu einem Inner-Join konvertiert, wenn eine der folgenden Bedingungen wahr ist:

Diese Neuschreibungsoptimierung kann für eine Outer-Join -Abfrage gelten, wenn die Abfrage eine oder mehrere Ansichten referenziert, die unter Verwendung von Outer-Joins geschrieben wurden. Die WHERE-Klausel der Abfrage kann Bedingungen umfassen, die die Ausgabe so einschränken, dass alle Nullwert-liefernden Zeilen aus einem oder mehreren Tabellenausdrücken entfernt werden, und so die Optimierung anwendbar machen.

Beispiel 1

Bei der unten stehenden Abfrage gibt es für jede Zeile der SalesOrderItems-Tabelle genau eine Zeile, die der Products-Tabelle entspricht, weil die ProductID-Spalte als NOT NULL deklariert wurde und die SalesOrderItems-Tabelle den folgenden Fremdschlüssel hat: "FK_ProductID_ID" ("ProductID") REFERENCING "Products" ("ID")

Die folgenden SELECT-Anweisungen zeigen, wie die Abfrage nach einer Neuschreibungsoptimierung umgeschrieben wird:

SELECT * FROM SalesOrderItems s LEFT OUTER JOIN Products p ON (p.ID = s.ProductID);
SELECT * FROM SalesOrderItems s JOIN Products p ON (p.ID = s.ProductID);
Beispiel 2

Die folgende Abfrage listet Produkte und ihre zugeordneten Bestellungen für größere Mengen auf, wobei der Left-Outer-Join sicherstellt, dass alle Produkte aufgelistet werden, selbst wenn sie keine Bestellungen aufweisen:

SELECT *
FROM Products p KEY LEFT OUTER JOIN SalesOrderItems s
WHERE s.Quantity > 15;

Das Problem bei dieser Abfrage ist, dass das Prädikat in der WHERE-Klausel alle Produkte aus dem Ergebnis entfernt, für die keine Aufträge vorliegen, weil das Prädikat s.Quantity > 15 als FALSE interpretiert wird, wenn s.Quantity gleich NULL ist. Die Abfrage ist semantisch gleichwertig mit:

SELECT *
FROM Products p KEY JOIN SalesOrderItems s
WHERE s.Quantity > 15;

Diese umgeschriebene Form ist die Abfrage, die vom Datenbankserver optimiert wird.

In diesem Beispiel ist die Abfrage mit großer Wahrscheinlichkeit falsch geschrieben. Sie müsste stattdessen lauten:

SELECT *
FROM Products p
    KEY LEFT OUTER JOIN SalesOrderItems s
          ON s.Quantity > 15;

Auf diese Weise ist der Mengentest Teil der Outer-Join-Bedingung. Sie können den Unterschied der beiden Abfragen verdeutlichen, indem Sie einige neue Produkte, für die keine Bestellungen vorliegen, in die Produkttabelle einfügen und dann die Abfragen erneut ausführen.

INSERT INTO Products
SELECT ID + 10, Name, Description,
        'Extra large', Color, 50, UnitPrice, Photo
FROM Products
WHERE Name = 'Tee Shirt';