Jeg har altid fundet Itzik Ben-Gans fremragende diagram over den logiske SQL-bearbejdning uhyre nyttig til at ræsonnere om forespørgselsydeevnen. Selvom diagrammet blev lavet til SQL Server, er det stadig anvendeligt til enhver databasemotor, der følger SQL Standard, som også inkluderer Access-databasemotor. Selvom vi elsker at bruge SQL Server-databaser, har vi lejlighedsvise Access-databaser eller Access-applikationer, der kræver brug af Access-forespørgsler (f.eks. midlertidige tabeller til rapportering). Access kommer ikke med fancy-pants profileringsværktøjer, så hvad skal vi gøre?
Jerryrigger vores eget sporingsværktøj
Det fik mig til at spekulere - kunne man bestemme, hvornår en klausul i en SQL-forespørgsel bliver udført og hvor ofte? Access har et middel til at vise udførelsesplaner, men det kommer ikke ind i detaljerne om, hvordan og hvornår oplysningerne bliver behandlet. Der er en omvej at udlede det fysiske behandlingsrækkefølge brugt af Access-databasemotor:en tilpasset VBA-funktion!
Public Function Trace(Begivenhedsnavn som streng, valgfri værdi som variant) Som Boolean If IsMissing(Value) Så Debug.Print EventName, "#No Value#" Ellers Debug.Print EventName, Value End If Trace =TrueEnd Function før>Dette kan gemmes i et standardmodul. Vi kan derefter oprette en simpel tabel:
Sporing af klausulerne i en Access-forespørgsel
Med den opsætning kan vi oprette en Access-forespørgsel og drysse
Trace
i forskellige dele af Access-forespørgsel. Her er et eksempel:SELECT c1.ColorID, Trace("SELECT") AS Ignored1, Trace("SELECT",c1.Color) AS Ignored2FROM tblColor AS c1 WHERE Trace("WHERE") <> 0 OG Trace("WHERE", c1 .Color) <> 0ORDER BY Trace("ORDER BY"), Trace("ORDER BY", c1.Color);Hvis du derefter åbner forespørgslen i dataarkvisning, og derefter går over til VBIDE's umiddelbare vindue, bør du se output som dette:
WHERE #Ingen værdi#ORDER BY #No Value#SELECT #Ingen værdi#WHERE RedORDER BY RedWHERE GreenORDER BY GreenWHERE BlueORDER BY BlueSELECT BlueSELECT GreenSELECT RedDette giver os nogle indsigter i, hvordan Access løser forespørgslen, hvilket kan være nyttigt, når du skal optimere en dårligt ydende forespørgsel. Lad os se, hvad vi kan lære:
- Vi kan se, at hvis der ikke er kolonnereferencer, kaldes VBA-funktionen så tidligt som muligt, da Access genkender, at de kun kan have én værdi for hele resultatsættet, så det nytter ikke at kalde funktionen igen og igen. for at få det samme svar. Du kan se, at
Trace
invokationer uden det 2. valgfrie argument blev evalueret først før alle andre kald, der indeholder en kolonnehenvisning i det 2. valgfrie argument. - Som en konsekvens af det foregående punkt, hvis invokationen indeholder en kolonnehenvisning, skal den derefter evalueres mindst én gang for hver række. Du kan se, at vi gennemgår hver farveværdi, når vi evaluerer klausulen.
- Vi ser, at rækkefølgen generelt ligner den, vi ser i Itzik Ben-Gans diagram;
WHERE
evalueres så tidligt som muligt,ORDER BY
evalueres, efter at vi har elimineret alle ikke-kvalificerende rækker, derefter hvad der er tilbage,SELECT
evalueres derefter. - Selvom vi ville forvente, at sortering blev anvendt, efter at vi har filtreret ikke-kvalificerende rækker fra, ser det ud til, at Access foretrækker at prøve at sortere output så hurtigt som muligt, muligvis fordi det er billigere at indsætte en ny række i en sorteret liste over sortering af hele sættet.
Yderligere eksperimenter og konklusioner
Du kan eksperimentere lidt med en anden forespørgsel. For eksempel kan du få et indblik i, hvornår/ofte Access-processer GROUP BY
, ved at bruge en forespørgsel, der ligner denne:
SELECT c1.ColorID, Trace("SELECT") AS Ignored1FROM tblColor AS c1 INNER JOIN tblColor AS c2 ON c1.ColorID =c2.ColorIDWHERE Trace("WHERE") <> 0 OG Trace("WHERE", [c1 ].[Farve]) <> 0GROUP BY c1.ColorID, Trace("GROUP BY", c1.Color)ORDER BY c1.ColorID;
Du kan derefter bruge dette sammen med JetShowPlan for at lære mere om, hvad databasemotoren rent faktisk laver. Forhåbentlig kan du finde det nyttigt at få indsigt i, hvordan du kan forbedre ydeevnen af din Access-forespørgsel. Som en udfordring kan du tænke på, hvorfor Access udfører GROUP BY
måden det gør. Jeg opfordrer dig også til at eksperimentere med at åbne et dataark og rulle. Du vil derefter opdage, at SELECT
bliver revurderet som et resultat af at navigere rundt.
Jeg skal påpege, at teknikken ovenfor giver os indsigt i det fysiske behandlingsplan, snarere end den logiske behandlingsrækkefølge som beskrevet i diagrammet. Derfor bør vi forvente, at planen er anderledes for forskellige mængder af data eller for forskellige forespørgsler. Vi skal også overveje at tilføje Trace
funktion kan påvirke planen. Jeg vil dog påstå, at hvis du er så bekymret over disse overvejelser, er det sandsynligvis bedre at flytte den forespørgsel og dens underliggende data til en SQL Server-database, hvor du har langt flere muligheder for at optimere forespørgslens ydeevne.
God fornøjelse!
Har du brug for hjælp til Microsoft Access-forespørgsler? Ring til Access Experts på (773) 809 5456, eller send holdet en e-mail i dag.