Access
 sql >> Datenbank >  >> RDS >> Access

Auswerten, wenn ein Ausdruck in einer Abfrage ausgewertet wird

Ich fand das ausgezeichnete Diagramm von Itzik Ben-Gan zur logischen SQL-Verarbeitung immer sehr hilfreich, um über die Abfrageleistung nachzudenken. Obwohl das Diagramm für SQL Server erstellt wurde, ist es dennoch auf jede Datenbank-Engine anwendbar, die dem SQL-Standard folgt, was auch die Access-Datenbank-Engine umfasst. Obwohl wir gerne SQL Server-Datenbanken verwenden, haben wir gelegentlich Access-Datenbanken oder Access-Anwendungen, die die Verwendung von Access-Abfragen erfordern (z. B. temporäre Tabellen für die Berichterstellung). Access kommt nicht mit ausgefallenen Profiling-Tools, also was sollen wir tun?

Jerry-Manipulation unseres eigenen Trace-Dienstprogramms

Das hat mich zu der Frage veranlasst, ob man feststellen kann, wann und wie oft eine Klausel einer SQL-Abfrage ausgeführt wird? Access hat zwar eine Möglichkeit, Ausführungspläne anzuzeigen, geht aber nicht auf die Details ein, wie und wann die Einzelheiten verarbeitet werden. Es gibt einen Umweg, um auf das Physische zu schließen Verarbeitungsreihenfolge, die von der Access-Datenbank-Engine verwendet wird:eine benutzerdefinierte VBA-Funktion!

Öffentliche Funktion Trace(EventName As String, Optional Value As Variant) As Boolean If IsMissing(Value) Then Debug.Print EventName, "#No Value#" Else Debug.Print EventName, Value End If Trace =TrueEnd Function 

Dies kann in einem Standardmodul gespeichert werden. Wir können dann eine einfache Tabelle erstellen:

Verfolgung der Klauseln einer Access-Abfrage

Mit dieser Einrichtung können wir eine Access-Abfrage erstellen und den Trace sprengen in verschiedenen Teilen der Access-Abfrage. Hier ist ein Beispiel:

SELECT c1.ColorID, Trace("SELECT") AS Ignored1, Trace("SELECT",c1.Color) AS Ignored2FROM tblColor AS c1 WHERE Trace("WHERE") <> 0 AND Trace("WHERE", c1 .Color) <> 0ORDER BY Trace("ORDER BY"), Trace("ORDER BY", c1.Color);

Wenn Sie die Abfrage dann in der Datenblattansicht öffnen und dann zum Direktfenster von VBIDE wechseln, sollten Sie die Ausgabe wie folgt sehen:

WHERE #Kein Wert#ORDER BY #Kein Wert#SELECT #Kein Wert#WHERE RotORDER BY RotWHERE GrünORDER BY GrünWHERE BlauORDER BY BlauSELECT BlauSELECT GrünSELECT Rot

Dadurch erhalten wir einige Erkenntnisse darüber, wie Access die Abfrage auflöst, was hilfreich sein kann, wenn Sie eine Abfrage mit schlechter Leistung optimieren müssen. Mal sehen, was wir lernen können:

  • Wir können sehen, dass die VBA-Funktion ohne Spaltenreferenzen so früh wie möglich aufgerufen wird, da Access erkennt, dass sie nur einen Wert für die gesamte Ergebnismenge haben können, sodass es keinen Sinn macht, die Funktion nur immer wieder aufzurufen dieselbe Antwort zu bekommen. Das sieht man am Trace Aufrufe ohne das 2. optionale Argument wurden zuerst vor allen anderen Aufrufen ausgewertet, die eine Spaltenreferenz im 2. optionalen Argument enthalten.
  • Als Folgerung zum vorherigen Punkt muss der Aufruf, wenn er eine Spaltenreferenz enthält, mindestens einmal für jede Zeile ausgewertet werden. Sie können sehen, dass wir bei der Auswertung der Klausel jeden Farbwert durchgehen.
  • Wir sehen, dass die Reihenfolge im Allgemeinen der ähnelt, die wir in Itzik Ben-Gans Diagramm sehen; WHERE wird so früh wie möglich ausgewertet, ORDER BY wird ausgewertet, nachdem wir alle nicht qualifizierenden Zeilen eliminiert haben, dann was übrig bleibt, SELECT wird dann ausgewertet.
  • Obwohl wir erwarten würden, dass die Sortierung angewendet wird, nachdem wir nicht qualifizierte Zeilen herausgefiltert haben, scheint Access es vorzuziehen, die Ausgabe so schnell wie möglich zu sortieren, möglicherweise weil es billiger ist, eine neue Zeile in eine sortierte Zeile einzufügen Liste über das Sortieren des gesamten Satzes.

Zusätzliche Experimente und Schlussfolgerungen

Sie können ein wenig mit einer anderen Abfrage experimentieren. Beispielsweise können Sie einen Einblick erhalten, wann/oft Access GROUP BY verarbeitet , indem Sie eine ähnliche Abfrage wie diese verwenden:

SELECT c1.ColorID, Trace("SELECT") AS Ignored1FROM tblColor AS c1 INNER JOIN tblColor AS c2 ON c1.ColorID =c2.ColorIDWHERE Trace("WHERE") <> 0 AND Trace("WHERE", [c1 ].[Farbe]) <> 0GROUP BY c1.ColorID, Trace("GROUP BY", c1.Color)ORDER BY c1.ColorID;

Sie können dies dann in Verbindung mit dem JetShowPlan verwenden, um mehr darüber zu erfahren, was die Datenbank-Engine tatsächlich tut. Hoffentlich finden Sie es hilfreich, um Erkenntnisse darüber zu gewinnen, wie Sie die Leistung Ihrer Access-Abfrage verbessern können. Als Herausforderung könnten Sie überlegen, warum Access GROUP BY ausführt so wie es geht. Ich ermutige Sie auch, zu experimentieren, ein Datenblatt zu öffnen und zu scrollen. Sie werden dann feststellen, dass der SELECT wird als Ergebnis der Navigation neu bewertet.

Ich sollte darauf hinweisen, dass uns die obige Technik einen Einblick in das Physische gibt Verarbeitungsplan und nicht die logische Verarbeitungsreihenfolge, wie in der Tabelle beschrieben. Dementsprechend sollten wir erwarten, dass der Plan für unterschiedliche Datenmengen oder für unterschiedliche Abfragen unterschiedlich ist. Wir müssen auch berücksichtigen, dass das Hinzufügen des Trace Funktion kann den Plan beeinflussen. Ich würde jedoch argumentieren, dass es wahrscheinlich besser ist, diese Abfrage und die zugrunde liegenden Daten in eine SQL Server-Datenbank zu verschieben, wenn Sie sich über diese Überlegungen Gedanken machen, wo Sie weitaus mehr Optionen zur Optimierung der Leistung der Abfrage haben.

Viel Spaß!

Benötigen Sie Hilfe bei Microsoft Access-Abfragen? Rufen Sie Access Experts unter (773) 809 5456 an oder senden Sie dem Team noch heute eine E-Mail.