sql >> Databasteknik >  >> RDS >> Access

Utvärdera när ett uttryck i en fråga utvärderas

Jag har alltid tyckt att Itzik Ben-Gans utmärkta diagram över den logiska SQL-bearbetningen är oerhört hjälpsam för att resonera om frågeprestanda. Även om diagrammet gjordes för SQL Server, är det fortfarande tillämpligt på alla databasmotorer som följer SQL Standard, som även inkluderar Access-databasmotor. Även om vi älskar att använda SQL Server-databaser, har vi enstaka Access-databaser eller Access-applikationer som kräver användning av Access-frågor (t.ex. tillfälliga tabeller för rapportering). Access kommer inte med snygga profileringsverktyg så vad ska vi göra?

Jerryriggar vårt eget spårningsverktyg

Det fick mig att undra - kan man avgöra när en klausul i en SQL-fråga exekveras och hur ofta? Access har ett sätt att visa utförandeplaner men det går inte in på detaljerna om hur och när uppgifterna behandlas. Det finns ett omvägande sätt att sluta sig till det fysiska bearbetningsordning som används av Access-databasmotorn:en anpassad VBA-funktion!

Public Function Trace(Händelsenamn Som String, Valfritt Värde Som Variant) Som Boolean If IsMissing(Value) Sedan Debug.Print EventName, "#No Value#" Annars Debug.Print EventName, Value End If Trace =TrueEnd Function 

Detta kan sparas i en standardmodul. Vi kan sedan sätta upp en enkel tabell:

Spåra klausulerna i en Access-fråga

Med den inställningen kan vi skapa en Access-fråga och strö Trace i olika delar av Access-frågan. Här är ett exempel:

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);

Om du sedan öppnar frågan i databladsvyn och sedan går över till VBIDE:s omedelbara fönster, bör du se utdata så här:

WHERE #No Value#ORDER BY #No Value#SELECT #Inget värde#WHERE RedORDER BY RedWHERE GreenORDER BY GreenWHERE BlueORDER BY BlueSELECT BlueSELECT GreenSELECT Red

Detta ger oss en del insikter i hur Access löser frågan, vilket kan vara till hjälp när du behöver optimera en fråga med dåligt resultat. Låt oss se vad vi kan lära oss:

  • Vi kan se att om det inte finns några kolumnreferenser anropas VBA-funktionen så tidigt som möjligt eftersom Access känner igen att de bara kan ha ett värde för hela resultatuppsättningen, så det är ingen idé att bara anropa funktionen om och om igen för att få samma svar. Du kan se att Trace anrop utan det andra valfria argumentet utvärderades först före alla andra anrop som innehåller en kolumnreferens i det andra valfria argumentet.
  • Som en följd av föregående punkt, om anropet innehåller en kolumnreferens, måste den sedan utvärderas minst en gång för varje rad. Du kan se att vi går igenom varje färgvärde när vi utvärderar klausulen.
  • Vi ser att ordningen i allmänhet liknar den vi ser i Itzik Ben-Gans diagram; WHERE utvärderas så tidigt som möjligt, ORDER BY utvärderas efter att vi har eliminerat alla icke-kvalificerande rader, sedan vad som är kvar, SELECT utvärderas sedan.
  • Även om vi förväntar oss att sortering kommer att tillämpas efter att vi har filtrerat bort icke-kvalificerande rader, verkar det som att Access föredrar att försöka sortera utdata så snart som möjligt, möjligen för att det är billigare att infoga en ny rad i en sorterad lista över att sortera hela uppsättningen.

Ytterligare experiment och slutsatser

Du kan experimentera lite med en annan fråga. Du kan till exempel få en inblick i när/ofta Access-processer GROUP BY , genom att använda en fråga som liknar denna:

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 ].[Color]) <> 0GROUP BY c1.ColorID, Trace("GROUP BY", c1.Color)ORDER BY c1.ColorID;

Du kan sedan använda detta tillsammans med JetShowPlan för att lära dig mer om vad databasmotorn faktiskt gör. Förhoppningsvis kan du ha nytta av det för att få insikter om hur du kan förbättra prestandan för din Access-fråga. Som en utmaning kan du resonera om varför Access kör GROUP BY som det gör. Jag uppmuntrar dig också att experimentera med att öppna ett datablad och rulla. Du kommer då att upptäcka att SELECT blir omvärderad som ett resultat av att navigera runt.

Jag bör påpeka att tekniken ovan ger oss insikt i det fysiska bearbetningsplan, snarare än den logiska bearbetningsordningen som beskrivs i diagrammet. Följaktligen bör vi förvänta oss att planen är annorlunda för olika datavolymer eller för olika frågor. Vi måste också tänka på att lägga till Trace funktion kan påverka planen. Men jag skulle hävda att om du är så oroad över dessa överväganden, är det förmodligen bättre att flytta den frågan och dess underliggande data till en SQL Server-databas där du har mycket fler alternativ för att optimera frågans prestanda.

Ha kul!

Behöver du hjälp med Microsoft Access-frågor? Ring Access Experts på (773) 809 5456 eller skicka ett e-postmeddelande till teamet idag.


  1. Hur man hittar när MySQL/MariaDB-servern startades

  2. MySQL ISNULL() Förklarat

  3. Få poster med maxvärde för varje grupp av grupperade SQL-resultat

  4. Använda utökade händelser för att logga föråldrade funktioner som används i en SQL Server-instans (T-SQL-exempel)