sql >> Database >  >> RDS >> Access

Evalueren wanneer een expressie in een query wordt geëvalueerd

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.


  1. Python en MySQL gebruiken in het ETL-proces:Python en SQLAlchemy gebruiken

  2. PostgreSQL 12-prestaties bewaken met OmniDB - deel 2

  3. Een lijst met tabellen retourneren van een gekoppelde server in SQL Server (T-SQL-voorbeelden)

  4. Een goede gewoonte om verbindingen in een asp.net-toepassing te openen/sluiten?