Ik heb de uitstekende grafiek van Itzik Ben-Gan op de logische SQL-verwerking altijd enorm nuttig gevonden bij het redeneren over de queryprestaties. Hoewel het diagram is gemaakt voor SQL Server, is het nog steeds van toepassing op elke database-engine die de SQL-standaard volgt, waaronder ook de Access-database-engine. Hoewel we graag SQL Server-databases gebruiken, hebben we af en toe Access-databases of Access-toepassingen die het gebruik van Access-query's vereisen (bijvoorbeeld tijdelijke tabellen voor rapportage). Access komt niet met fancy-pant profileringstools, dus wat moeten we doen?
Jerry-rigging ons eigen traceerhulpprogramma
Dat zette me aan het denken:kan iemand bepalen wanneer een clausule van een SQL-query wordt uitgevoerd en hoe vaak? Access heeft een middel om uitvoeringsplannen te tonen, maar het gaat niet in op de details van hoe en wanneer de details worden verwerkt. Er is een omweg om de fysieke . af te leiden verwerkingsvolgorde gebruikt door Access-database-engine:een aangepaste VBA-functie!
Public Function 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 = True End Function
Dit kan worden opgeslagen in een standaard module. We kunnen dan een eenvoudige tabel opzetten:
De clausules van een Access-query traceren
Met die instelling kunnen we een Access-query maken en de Trace
. sprenkelen in verschillende delen van Access-query. Hier is een voorbeeld:
SELECT c1.ColorID, Trace("SELECT") AS Ignored1, Trace("SELECT",c1.Color) AS Ignored2 FROM tblColor AS c1 WHERE Trace("WHERE") <> 0 AND Trace("WHERE", c1.Color) <> 0 ORDER BY Trace("ORDER BY"), Trace("ORDER BY", c1.Color);
Als u de query vervolgens opent in de gegevensbladweergave en vervolgens naar het directe venster van de VBIDE gaat, zou u de uitvoer als volgt moeten zien:
WHERE #No Value# ORDER BY #No Value# SELECT #No Value# WHERE Red ORDER BY Red WHERE Green ORDER BY Green WHERE Blue ORDER BY Blue SELECT Blue SELECT Green SELECT Red
Dit geeft ons enig inzicht in hoe Access de query oplost, wat handig kan zijn wanneer u een slecht presterende query moet optimaliseren. Laten we eens kijken wat we kunnen leren:
- We kunnen zien dat als er geen kolomverwijzingen zijn, de VBA-functie zo vroeg mogelijk wordt aangeroepen, omdat Access erkent dat ze maar één waarde kunnen hebben voor de hele resultaatset, dus het heeft geen zin om de functie steeds maar opnieuw aan te roepen hetzelfde antwoord te krijgen. U kunt zien dat de
Trace
aanroepen zonder het 2e optionele argument werden eerst geëvalueerd voordat alle andere aanroepen die een kolomverwijzing bevatten in het 2e optionele argument. - Als een uitvloeisel van het vorige punt, als de aanroep een kolomverwijzing bevat, moet deze vervolgens voor elke rij ten minste één keer worden geëvalueerd. Je kunt zien dat we elke kleurwaarde doornemen bij het evalueren van de clausule.
- We zien dat de volgorde over het algemeen vergelijkbaar is met wat we zien in de kaart van Itzik Ben-Gan;
WHERE
wordt zo vroeg mogelijk geëvalueerd,ORDER BY
wordt geëvalueerd nadat we alle niet-kwalificerende rijen hebben geëlimineerd, en wat er dan nog over is,SELECT
wordt vervolgens geëvalueerd. - Hoewel we verwachten dat sortering wordt toegepast nadat we niet-kwalificerende rijen hebben uitgefilterd, lijkt het erop dat Access er de voorkeur aan geeft de uitvoer zo snel mogelijk te sorteren, mogelijk omdat het goedkoper is om een nieuwe rij in te voegen in een gesorteerde lijst over het sorteren van de hele set.
Aanvullende experimenten en conclusies
Je kunt een beetje experimenteren met een andere query. U kunt bijvoorbeeld inzicht krijgen in wanneer/vaak Access processen GROUP BY
, door een soortgelijke zoekopdracht te gebruiken:
SELECT c1.ColorID, Trace("SELECT") AS Ignored1 FROM tblColor AS c1 INNER JOIN tblColor AS c2 ON c1.ColorID = c2.ColorID WHERE Trace("WHERE") <> 0 AND Trace("WHERE", [c1].[Color]) <> 0 GROUP BY c1.ColorID, Trace("GROUP BY", c1.Color) ORDER BY c1.ColorID;
U kunt dit dan gebruiken in combinatie met het JetShowPlan om meer te weten te komen over wat de database-engine eigenlijk doet. Hopelijk vindt u het nuttig om inzicht te krijgen in hoe u de prestaties van uw Access-query kunt verbeteren. Als uitdaging zou je kunnen redeneren waarom Access de GROUP BY
. uitvoert de manier waarop het gaat. Ik moedig je ook aan om te experimenteren met het openen van een datasheet en scrollen. U zult dan ontdekken dat de SELECT
wordt opnieuw geëvalueerd als resultaat van het navigeren.
Ik moet erop wijzen dat de bovenstaande techniek ons inzicht geeft in de fysieke verwerkingsplan, in plaats van de logische verwerkingsvolgorde zoals beschreven in de grafiek. Dienovereenkomstig moeten we verwachten dat het plan anders is voor verschillende gegevensvolumes of voor verschillende zoekopdrachten. We moeten er ook rekening mee houden dat het toevoegen van de Trace
functie kan het plan beïnvloeden. Ik zou echter willen beweren dat als u zich zo zorgen maakt over die overwegingen, het waarschijnlijk beter is om die query en de onderliggende gegevens te verplaatsen naar een SQL Server-database, waar u veel meer opties hebt om de prestaties van de query te optimaliseren.
Veel plezier!
Hulp nodig bij Microsoft Access-query's? Bel Access Experts op (773) 809 5456 of stuur het team vandaag nog een e-mail.