sql >> Database >  >> RDS >> Access

JetShowPlan:een primeur

Ik schreef kort over JetShowPlan in mijn artikel over Tuning Access Query Performance. Zoals ik in dat artikel schreef, is SQL een declaratieve taal. Wanneer u een query schrijft, vertelt u de database-engine wat jij wil. De database-engine beslist hoe het beste om dat voor je te doen. Dit is over het algemeen goed, want het optimaliseren van op sets gebaseerde bewerkingen is moeilijk en als u de database-engine het voor u laat doen, kunt u gebruikmaken van de kennis van degenen die hun leven aan dat specifieke probleem wijden.

Het nadeel is dat de hoe wordt een zwarte doos. Je voert wat SQL in de zwarte doos en er komt een resultatenset uit met een heleboel gegevens. De database-engine is uiterst betrouwbaar in het verstrekken van precies de door u gevraagde gegevens. Het probleem is dat de prestaties van het ophalen van gegevens overal kunnen zijn. Voor alle duidelijkheid:de slechte prestaties zijn bijna nooit de schuld van de database-engine. Meestal is het probleem dat we een index of filtering missen op het resultaat van een VBA-functie of samenvoegen op twee gekoppelde tabellen die op fysiek gescheiden locaties zijn opgeslagen.

Wanneer dit probleem zich voordoet, hebben we een manier nodig om het op te lossen. Voer JetShowPlan in. Zie dit als een speciale schroevendraaier waarmee we de zwarte doos uit elkaar kunnen halen en naar binnen kunnen kijken om te zien hoe de database-engine implementeert de SQL-opdrachten die we eraan geven. Met deze kennis kunnen we de SQL aanpassen, een index toevoegen of op een andere manier de bron van onze prestatieknelpunten aanpakken.

Laten we beginnen.

Registersleutel

JetShowPlan werkt door het queryplan (d.w.z. de inhoud van de zwarte doos) naar een tekstbestand te schrijven wanneer de ACE/Jet-database-engine elke uitvoert vraag. Dit tekstbestand is snel vol. Voor het maken van het tekstbestand zijn bronnen nodig die verder afbreuk doen aan de queryprestaties. We willen deze functie dus alleen inschakelen wanneer we actief bezig zijn met het oplossen van een probleem.

Aangezien dit een hulpmiddel is voor gevorderde gebruikers, is er geen instelling in de gebruikersinterface van Access om deze modus in te schakelen. De enige manier om het in of uit te schakelen is door een waarde in het register in te stellen. De registerwaarde past in het volgende patroon (de tekst tussen accolades dient als tijdelijke aanduiding):

[HKEY_LOCAL_MACHINE\SOFTWARE{\Wow6432Node}\Microsoft\Office\{xx}.0\Access Connectivity Engine\Engines\Debug]
"JETSHOWPLAN"="ON"

Overwegingen voor versie en bitness

Het patroon van de registerwaarde dat ik hierboven heb laten zien, maakt gebruik van tijdelijke tekst om rekening te houden met de verschillen tussen Access-omgevingen. De versienummertekst \{xx}.0\ moet worden vervangen door het versienummer dat overeenkomt met de versie van Access die op uw computer is geïnstalleerd:

  • 12.0 :Toegang 2007
  • 13.0 :overgeslagen om triskaidekaphobes te voorkomen
  • 14.0 :Toegang 2010
  • 15.0 :Toegang 2013
  • 16.0 :Toegang 2016 &2019

De \Wow6432Node ('Wow' staat voor "Windows 32-bit op Windows 64-bit") is alleen vereist als u een 32-bits versie van Microsoft Access op een 64-bits versie van Windows gebruikt. Als Access en Windows beide 32-bits of beide 64-bits zijn, is die "map" (of "sleutel" in registerjargon) niet nodig.

In VBA-vorm:

    If Is32BitAccess Xor Is32BitWindows Then
        IncludeWow6432Key = True
    Else
        IncludeWow6432Key = False
    End If

Voor een 32-bits installatie van Access 2010 op 64-bits Windows is bijvoorbeeld de volgende registervermelding vereist:

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Office\14.0\Access Connectivity Engine\Engines\Debug]
"JETSHOWPLAN"="ON"

Evenzo zou een 64-bits installatie van Access 2019 op 64-bits Windows het volgende vereisen:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\16.0\Access Connectivity Engine\Engines\Debug]
"JETSHOWPLAN"="ON"

Ik moet er ook rekening mee houden dat de eerste keer dat u dit item maakt, u waarschijnlijk de "Debug"-sleutel (map) en de JETSHOWPLAN-waardenaam en -gegevens moet toevoegen.

Dit zijn de stappen om dit te doen:

  1. Voer regedit uit als beheerder
  2. Navigeer naar de toets "\Engines" volgens de bovenstaande opmerkingen
  3. Klik met de rechtermuisknop op "\Engines" en kies Nieuw -> Sleutel
  4. Hernoem de sleutel van "Nieuwe sleutel #1" in "Debug"

Vervolgens moet u de tekenreekswaarde "JETSHOWPLAN" toevoegen met de gegevens "AAN " om toevoegen aan de showplan.out . in te schakelen bestand of "UIT " om te stoppen met toevoegen aan het bestand.

  1. Klik met de rechtermuisknop op de toets "\Debug" en kies Nieuw -> Tekenreekswaarde
  2. Hernoem de waarde van "Nieuwe waarde #1" in "JETSHOWPLAN"
  3. Klik met de rechtermuisknop op de waardenaam "JETSHOWPLAN" en kies Wijzigen...
  4. Stel de waardegegevens in op AAN klik vervolgens op de [OK]-knop

De volgende keer dat u een nieuw exemplaar van Access start, begint het met het toevoegen van gegevens aan het Showplan.out-bestand. Alle instanties van Access die al actief zijn wanneer u de bovenstaande wijzigingen aanbrengt, worden niet beïnvloed. Hetzelfde geldt voor wanneer u de instelling UIT . zet . De wijzigingen worden pas van kracht nadat u een nieuwe msaccess.exe . start voorbeeld. Het is niet nodig om bestaande exemplaren van Access te sluiten; het is mogelijk om één open exemplaar van Access te hebben die actief naar showplan.out schrijft, terwijl een ander exemplaar van Access dat niet is.

Autohotkey-script

Ik ga niet liegen; springen in regedit elke keer dat ik JetShowPlan AAN of UIT wil zetten is vervelend. Als ik dat zou moeten doen, zou ik me er nauwelijks druk om maken. Maar dat hoef ik niet te doen! Ik heb een sneltoets gemaakt in Autohotkey die JetShowPlan AAN en UIT zet.

^#q:: ; Ctl + Win + Q  (feel free to use your own key combination)
    ;--== Toggle JETSHOWPLAN ==--
    
    ;----- BEGIN CONFIGURATION (make all changes here) -------------
    ShowPlanRegView = 64   ; set to 32 for 32-bit Access
    ShowPlanKey = SOFTWARE\Microsoft\Office\16.0\Access Connectivity Engine\Engines\Debug  ; change 16.0 to match Access version
    ;----- END CONFIGURATION ---------------------------------------
    
    SetRegView %ShowPlanRegView%
    RegRead ShowPlanSetting, HKEY_LOCAL_MACHINE\%ShowPlanKey%, JETSHOWPLAN
    If ( ShowPlanSetting = "OFF" ) {
            RegWrite REG_SZ, HKEY_LOCAL_MACHINE\%ShowPlanKey%, JETSHOWPLAN, ON
            If ErrorLevel
                MsgBox Error enabling JetShowPlan. Check permissions on:`n`nHKLM\%ShowPlanKey%`n`nfor user '%A_UserName%'
            Else
                MsgBox JetShowPlan set to ON
    } Else {
            RegWrite REG_SZ, HKEY_LOCAL_MACHINE\%ShowPlanKey%, JETSHOWPLAN, OFF
            If ErrorLevel
                MsgBox Error disabling JetShowPlan. Check permissions on:`n`nHKLM\%ShowPlanKey%`n`nfor user '%A_UserName%'
            Else
                MsgBox JetShowPlan set to OFF
    }
    SetRegView Default
    Return

Als ik nu mijn zoekopdrachten wil afstemmen, druk ik op [Ctl] + [Win] + [Q] en ik zie een berichtvenster met de tekst "JetShowPlan ingesteld op AAN". Als ik klaar ben, sluit ik Toegang, druk op [Ctl] + [Win] + [Q] en ik zie "JetShowPlan ingesteld op UIT".

Rechten aanpassen

Ik heb twee verschillende Windows-gebruikersaccounts:een met standaardrechten die ik gebruik voor dagelijks werk en een andere met beheerdersrechten voor het installeren van software, enz.  Dit is een gebruikelijke best practice voor beveiliging.

Het probleem is dat de JetShowPlan-registersleutel zich in de HKLM-korf bevindt. Standaard kunnen alleen beheerders wijzigingen aanbrengen in de waarden in die component. Dit is vervelend, want als ik mijn Autohotkey-script probeer uit te voeren, krijg ik de volgende foutmelding:

Maak je echter geen zorgen. Zoals het bericht hierboven suggereert, kunnen we dit oplossen. Het beste is dat we het gemakkelijk kunnen maken zonder onze beveiligingshouding te verminderen. Hier is de truc.

  1. Open regedit als beheerder
  2. Navigeer naar de \Debug sleutel
  3. Klik met de rechtermuisknop op de \Debug toets en kies Machtigingen...
  4. Klik op de knop [Toevoegen...]
  5. Voer de gebruikersnaam in uit het bovenstaande berichtvenster ('Mike'), klik op [Namen controleren] en klik vervolgens op [OK]
  6. Sta [√] "Volledige controle" toe aan de gebruiker
  7. Klik op [OK] om de wijzigingen op te slaan

Als ik nu op [Ctl] + [Win] + [Q] druk, wordt JetShowPlan AAN en UIT gezet, waardoor het register automatisch wordt bijgewerkt.

Showplan.out vinden

Access waarschuwt u niet waar de Jet/ACE-database-engine queryplaninformatie toevoegt wanneer JetShowPlan is ingeschakeld. Ik heb meer tijd besteed aan het zoeken naar een malafide exemplaar van showplan.out dan ik wil toegeven . Deze sectie zal je behoeden voor het delen van dat lot.

Standaardlocatie

De eerste plaats om te zoeken is in de map Documenten van de huidige gebruiker. Mijn Windows-gebruikersnaam is bijvoorbeeld "Mike", dus de eerste plaats waar ik het bestand zou verwachten is:C:\Users\Mike\Documents\showplan.out .

CurDir() gebruiken

Technisch gezien is de showplan.out bestand wordt aangemaakt in de huidige werkdirectory. Dat is meestal de map Documenten van de huidige gebruiker, maar niet altijd. De veilige manier om de locatie van het bestand te vinden, is door de CurDir() . te gebruiken functie.

U kunt de volgende regel code kopiëren, plakken en uitvoeren in het VBA IDE-onmiddellijke venster om het showplan.out-bestand te openen (ervan uitgaande dat u JetShowPlan in het register hebt ingeschakeld):

Shell "notepad """ & CurDir & "\showplan.out""", vbNormalFocus

De output-locatie wijzigen via ChDir()

Als je om wat voor reden dan ook een andere locatie wilt specificeren voor de showplan.out bestand, kunt u dat doen met de functie ChDir(). Die functie verandert de huidige werkdirectory. En, zoals ik eerder al zei, de huidige map is waar de showplan.out bestand verblijft. Zodra u de huidige werkdirectory wijzigt, begint JetShowPlan naar de nieuwe map te schrijven; het is niet nodig om Access te sluiten en opnieuw te openen.

Waarom zou je dit willen doen? Stel dat u drie verschillende benaderingen voor het ophalen van dezelfde gegevens wilt vergelijken. U schrijft drie verschillende query's om te zien hoe de wijzigingen die u aanbrengt van invloed zijn op het queryplan. Sinds showplan.out is zo uitgebreid, het zou leuk zijn om elk queryplan in zijn eigen bestand te hebben. Dit maakt de queryplannen gemakkelijker te vergelijken. Hier is hoe ik dat zou kunnen doen. De eerste stap is om ervoor te zorgen dat elk van deze mappen bestaat. Voer vervolgens de volgende regels code uit:

ChDir "C:\Users\Mike\Documents\Showplan\A"
DoCmd.OpenQuery "CollectTax1"
ChDir "C:\Users\Mike\Documents\Showplan\B"
DoCmd.OpenQuery "CollectTax2"
ChDir "C:\Users\Mike\Documents\Showplan\C"
DoCmd.OpenQuery "CollectTax3"
ChDir "C:\Users\Mike\Documents"

Gebruik alles wat je hebt (of download het als je heb het nog niet)

Terwijl CurDir() u een definitieve locatie geeft voor de meest recente wijzigingen aan de showplan.out bestand, kan het u niet vertellen wat de vorige werkmappen waren. En als u de instantie van Access die de showplan.out heeft gemaakt, heeft gesloten bestand, is er geen garantie dat het volgende exemplaar van Access dat u opent dezelfde huidige map zal hebben.

Ik kwam onlangs een handig klein hulpprogramma tegen met de naam "Alles". Het is een klein uitvoerbaar bestand dat uw hele harde schijf in slechts een paar seconden indexeert. Zodra het indexeren is voltooid, kunt u direct overal op uw schijf naar bestanden of mappen zoeken.

Je kunt Alles downloaden vanaf hier of via Chocolatey:choco install everything . Alles openen , zoek naar showplan.out , en in minder dan een seconde ziet u elk exemplaar van showplan.out op uw computer samen met de laatste wijzigingsdatum. Ik wou dat ik deze tool jaren geleden had.

Showplan.out begrijpen

De eerste keer dat u een showplan.out . opent bestand, verwacht verbijsterd te zijn. Er is veel tekst en veel daarvan is ruis. Hier is een fragment uit een bestand dat werd gegenereerd toen ik de voorbeelddatabase van Northwind opende:

De zoekopdrachten die beginnen met een tilde (~ ) staat voor onbewerkte SQL die is opgeslagen in het eigenschappenblad van een formulier of rapport en niet is opgeslagen als een permanent QueryDef-object. De belangrijkste aandachtspunten zijn de genummerde stappen voor elke zoekopdracht:01) , 02) , 03) , enz.  U wilt deze stappen volgen om te zoeken naar goede tekens en slechte tekens die kunnen wijzen op problemen.

Voor zover ik weet, is er geen officiële documentatie voor de opmaak en inhoud van de showplan.out het dossier. Maar dat is niet erg, want we gaan niet in de details verstrikt raken. Ons belangrijkste doel is om overduidelijke problemen te identificeren en aan te pakken. Hier geldt de 80/20 regel. De meeste prestatieverbeteringen komen van een of twee eenvoudige aanpassingen aan onze vragen.

Goede tekenen

Dit gaat allemaal over indexen. We willen dat het queryplan indexen gebruikt, vooral in de beginstappen van een query met meerdere stappen. Twee verschillende sleutelwoorden geven aan dat er indexen worden gebruikt:index en rushmore . Rushmore is de codenaam voor de technologie voor het optimaliseren van zoekopdrachten die oorspronkelijk in het begin van de jaren '80 door Fox Software werd ontwikkeld. Microsoft kocht het bedrijf in 1992 en integreerde de technologie in de Jet-database-engine.

Query's die Rushmore-technologie gebruiken om indexen te verwerken, worden sneller uitgevoerd dan die waarbij indexen op een meer traditionele manier worden gebruikt. Rushmore-technologie kan alleen worden gebruikt met Access-tabellen (zowel lokaal als gekoppeld), samen met gekoppelde FoxPro- en dBASE-tabellen. Rushmore kan met name niet worden gebruikt met gekoppelde SQL Server-tabellen. Om de prestaties van gekoppelde SQL Server-tabellen te verbeteren, kunt u vaak beter pass-through-query's schrijven, maar dat valt buiten het bestek van dit artikel.

Slechte tekens

Er zijn een paar slechte tekens om op te letten in de showplan.out het dossier. De simpele aanwezigheid van deze tekens betekent niet noodzakelijk dat er een probleem is. Dat gezegd hebbende, als u een query met slechte prestaties probeert op te lossen, kunt u deze woorden beschouwen als waarschuwingsvlaggen voor mogelijke problemen:X-Prod , scanning , temp , temporary .

De X-Prod trefwoord verschijnt wanneer u een zoekopdracht heeft met een cartesiaanse join (ook wel cross-join of cross-product genoemd). Dit gebeurt meestal per ongeluk wanneer u vergeet twee tabellen samen te voegen in de Query-by-Example (QBE)-editor. Het resultaat is dat elk record in tabel 1 overeenkomt met elk record in tabel 2.  Het totale aantal records is het product van de twee tabeltellingen. Dus als tabel 1 7 records heeft en tabel 2 9 records, levert de kruiskoppeling van de twee tabellen 63 records op. U kunt zich het probleem voorstellen als beide tabellen duizenden records of meer hebben.

01) Inner Join table 'Table1' to table 'Table2'
      using X-Prod join

Het volgende sleutelwoord om op te letten is scannen . Als de database-engine geen index kan gebruiken om resultaten te filteren, valt deze terug op scannen. Dit betekent dat het elke rij afzonderlijk moet onderzoeken om te zien of het voldoet aan de zoekcriteria. Wanneer je dit woord ziet in een showplan.out bestand, betekent dit vaak dat u een index moet toevoegen aan de kolom die wordt gescand. Maar niet altijd! Voor kolommen met een lage kardinaliteit (slechts een paar unieke waarden, zoals een statuskolom), heeft het toevoegen van een index meestal weinig voordelen. Eenmaal toegevoegd, moet de index worden onderhouden. Dit vertraagt ​​inserts en neemt schijfruimte in beslag. Als de queryprestaties acceptabel zijn voor productiegegevens, is het toevoegen van een index aan de gescande kolom een ​​voortijdige optimalisatie (die u moet vermijden).

Ten slotte zijn er de temp en tijdelijk trefwoorden. Deze geven aan dat de database-engine tijdelijk een soort bewerking heeft moeten uitvoeren. Wanneer we een querydef maken en opslaan, wordt dat object opgeslagen met bepaalde metadata om herhaalde uitvoering te optimaliseren. Het is duidelijk dat dergelijke metadata verloren gaan wanneer tijdelijke indexen of joins buiten het bereik vallen. Deze zoekwoorden kunnen meestal worden genegeerd, maar ze kunnen u mogelijk in de goede richting wijzen als u vastloopt op een slecht presterende zoekopdracht zonder andere meer voor de hand liggende gebreken.

Om in te vereenvoudigde bewoordingen samen te vatten:

      GOED  >  >  >  >  >  SLECHT:
Rushmore> indexen> tijdelijk/tijdelijk> scannen> X-Prod

Notepad++ aangepaste taal

Als je mijn andere werk hebt gelezen, weet je dat ik sterke gevoelens heb over het vergroten van de signaal-ruisverhouding bij programmeren (en het leven in het algemeen). Hiertoe heb ik een "Door de gebruiker gedefinieerde taal"-bestand gemaakt in Notepad++ om syntaxisaccentuering toe te voegen aan showplan.out bestanden. Als ik nu showplan.out open, bestanden, zien ze eruit als de onderstaande schermafbeelding. De "GOED" trefwoorden zijn gekleurd in blauwe tekst en de "SLECHT" trefwoorden zijn gekleurd in rode tekst. Dit is een voorbeeld van Maken Wrong Code Look Wrong.

Volg deze stappen om dit in te stellen:

  1. Open Kladblok++
  2. Taal -> Door gebruiker gedefinieerde taal -> Definieer uw taal...
  3. Klik op [Nieuw maken...]
  4. Voer naam in:showplan.out
  5. Klik op [OK]
  6. Ga naar de _| Map &Standaard|_ tabblad
  7. Voer onder "Vouwen in code 2-stijl" Inputs in voor Open en End inputs voor Sluiten
  8. Ga naar het tabblad _|Trefwoordenlijst|_
  9. Klik op [Styler] onder de 1e groep en zet de voorgrondkleur op rood
  10. Voer de volgende "SLECHTE" trefwoorden in de 1e groep in:
    temp temporary scanning X-Prod
  11. Klik op [Styler] onder de 2e groep en zet de voorgrondkleur op blauw
  12. Voer de volgende "GOED" trefwoorden in de 2e groep in:
    rushmore index
  13. Voer Ext. in:uit

Laatste gedachten

In tegenstelling tot SQL Server kunt u met de Jet/ACE-database-engine niet rechtstreeks plannen voor het uitvoeren van query's wijzigen. Dat betekent dat we met JetShowPlan in de zwarte doos kunnen kijken, maar het niet opnieuw kunnen bedraden om te doen wat we willen. In plaats daarvan moeten we ons concentreren op wat we kunnen controleren:de exacte SQL die we eraan geven en de indexen en relaties tussen de betrokken tabellen.

Het gebruik van JetShowPlan heeft zowel korte als lange termijn voordelen. Op korte termijn kunt u met deze functie de knelpunten in uw Access-toepassingen oplossen. Op de lange termijn krijg je inzicht in de innerlijke werking van Access, waardoor je de knelpunten in de eerste plaats kunt vermijden.


  1. JSON_ARRAYAGG() - Maak een JSON-array van de rijen van een query in MySQL

  2. MySQL #1093 - U kunt geen 'weggeefacties' voor de doeltabel specificeren voor update in de FROM-clausule

  3. MySQL:hoe beveilig je op rijniveau (zoals Oracle's Virtual Private Database)?

  4. Oracle:hoe voeg ik minuten toe aan een tijdstempel?