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

 

Nutzbare Bedingungen durch Prädikat-Inferenz suchen

Eine effiziente Zugriffsstrategie für fast alle Abfragen stützt sich auf die Anwesenheit von Sargable-Bedingungen in den WHERE-, ON- und HAVING-Klauseln. Abrufe mit Index sind nur dann möglich, wenn sargable-Bedingungen als übereinstimmende Prädikate genutzt werden. Außerdem können Hash- und Merge-Joins sowie Joins mit verschachteltem Block und verschachtelten Schleifen (Block-Nested-Loops Joins) nur dann eingesetzt werden, wenn eine Equi-Join-Bedingung vorhanden ist. Aus diesen Gründen führt SQL Anywhere eine detaillierte Analyse der Suchbedingungen im ursprünglichen Abfragetext durch, um vereinfachte oder implizierte Bedingungen zu entdecken, die vom Optimierer genutzt werden können.

Als Vorverarbeitungsschritt werden in der ursprünglichen Anweisung Prädikate vereinfacht, nachdem Ansichtserweiterung und Zusammenführung ausgeführt wurden. Zum Beispiel:

  • X = X wird zu X IS NOT NULL umgeschrieben, falls X nullwertfähig ist. Andernfalls wird das Prädikat entfernt.

  • ISNULL(X,X) wird zu X umgeschrieben.

  • X+0 wird zu X umgeschrieben, falls X eine nummerische Spalte ist.

  • AND 1=1 wird entfernt.

  • OR 1=0 wird entfernt.

  • IN-List-Prädikate, die aus einem einzelnen Element bestehen, werden zu einfachen Gleichheitsbedingungen konvertiert.

Nach diesem Vorverarbeitungsschritt versucht SQL Anywhere, die ursprüngliche Suchbedingung in konjunktiver Normalform (CNF - conjunctive normal form) zu normalisieren. Damit ein Ausdruck der CNF entspricht, müssen die einzelnen Begriffe im Ausdruck mit AND verbunden sein. Die Ausdrücke bestehen entweder aus einzelnen atomaren Bedingungen oder aus einer mit OR verbundenen Gruppe von Bedingungen.

Eine beliebige Bedingung in CNF zu konvertieren kann zu einem Ausdruck mit ähnlicher Komplexität führen, jedoch mit einer wesentlich größeren Gruppe von Bedingungen. SQL Anywhere erkennt diese Situation und konvertiert die Bedingung nicht einfach in CNF. Stattdessen analysiert SQL Anywhere den ursprünglichen Ausdruck auf nützliche Prädikate, die von der ursprünglichen Suchbedingung impliziert werden, und verbindet diese abgeleiteten Bedingungen mit AND in der Abfrage. Die vollständige Normalisierung wird ebenfalls vermieden, wenn dies die Duplizierung kostenträchtiger Prädikate zur Folge hätte (z.B. ein quantifiziertes Unterabfrage-Prädikat). Der Algorithmus führt jedoch die IN-Listen-Prädikate zusammen, sofern dies möglich ist.

Nachdem die Suchbedingung entweder vollständig normalisiert oder die nützlichen Bedingungen ermittelt wurden, führt der Optimierer eine Transitivitätsanalyse durch, um transitive Gleichheitsbedingungen, primär transitive Bedingungen und Bedingungen mit Konstanten, ausfindig zu machen. Auf diese Weise erhöht der Optimierer seinen Spielraum zum Aufstellen der Join-Liste während der kostenbasierten Optimierungsphase, da die Möglichkeit besteht, dass diese transitiven Bedingungen zusätzliche alternative Join-Folgen zulassen.

Beispiel

Angenommen, die Abfrage lautet folgendermaßen:

SELECT e.Surname, s.ID, s.OrderDate
FROM SalesOrders s, Employees e
WHERE 
  ( e.EmployeeID = s.SalesRepresentative AND
    ( s.SalesRepresentative = 142 OR 
      s.SalesRepresentative = 1596 )
  ) OR (
     e.EmployeeID = s.SalesRepresentative AND 
     s.CustomerID = 667 );

Diese Abfrage enthält keine konjunktive Equi-Join-Bedingung und ohne detaillierte Prädikat-Analyse könnte der Optimierer keinen effizienten Zugriffsplan ermitteln. SQL Anywhere ist jedoch in der Lage, den gesamten Ausdruck in CNF zu konvertieren. Dies führt zur folgenden äquivalenten Abfrage:

SELECT e.Surname, s.ID, s.OrderDate
FROM SalesOrders s, Employees e
WHERE 
   e.EmployeeID = s.SalesRepresentative AND
   ( s.SalesRepresentative = 142 OR 
     s.SalesRepresentative = 1596 OR 
     s.CustomerID = 667 );

Diese Abfrage kann jetzt auf effiziente Weise als Inner-Join-Abfrage optimiert werden.