Ho scritto brevemente su JetShowPlan nel mio articolo sull'ottimizzazione delle prestazioni delle query di accesso. Come ho scritto in quell'articolo, SQL è un linguaggio dichiarativo. Quando scrivi una query, stai dicendo al motore di database cosa tu vuoi. Il motore di database decide come meglio farlo per te. Questo è generalmente positivo, perché l'ottimizzazione delle operazioni basate sui set è difficile e lasciare che il motore di database lo faccia per te ti consente di sfruttare la conoscenza di coloro che dedicano la propria vita a quel problema specifico.
Lo svantaggio è che il come diventa una scatola nera. Inserisci un po' di SQL nella scatola nera e ne esce un set di risultati con un mucchio di dati. Il motore di database è estremamente affidabile nel fornirti esattamente i dati richiesti. Il problema è che le prestazioni del recupero dei dati possono essere ovunque. Per essere chiari, le scarse prestazioni non sono quasi mai imputabili al motore di database. Di solito, il problema è che ci manca un indice o un filtro sul risultato di una funzione VBA o ci uniamo su due tabelle collegate che sono archiviate in posizioni fisicamente separate.
Quando si verifica questo problema, abbiamo bisogno di un modo per risolverlo. Entra in JetShowPlan. Pensa a questo come a un cacciavite speciale che ci consente di smontare la scatola nera e di sbirciare all'interno per vedere come il motore di database sta implementando i comandi SQL che gli forniamo. Con questa conoscenza, possiamo modificare l'SQL, aggiungere un indice o affrontare in altro modo l'origine del nostro collo di bottiglia delle prestazioni.
Iniziamo.
Chiave del registro
JetShowPlan funziona scrivendo il piano di query (cioè il contenuto della scatola nera) in un file di testo ogni volta che il motore di database ACE/Jet esegue qualsiasi interrogazione. Questo file di testo si riempie velocemente. La creazione del file di testo richiede risorse che riducono ulteriormente le prestazioni della query. Pertanto, vogliamo abilitare questa funzione solo quando stiamo attivamente risolvendo un problema.
Poiché si tratta di uno strumento per utenti avanzati, non è presente alcuna impostazione nell'interfaccia utente di Access per abilitare questa modalità. L'unico modo per attivarlo o disattivarlo è impostare un valore nel registro. Il valore del registro si adatta al seguente schema (il testo tra parentesi graffe funge da segnaposto):
[HKEY_LOCAL_MACHINE\SOFTWARE{\Wow6432Node}\Microsoft\Office\{xx}.0\Access Connectivity Engine\Engines\Debug]
"JETSHOWPLAN"="ON"
Considerazioni su versione e bitness
Il modello di valore del registro che ho mostrato sopra utilizza del testo segnaposto per tenere conto delle differenze tra gli ambienti di Access. Il testo del numero di versione \{xx}.0\
deve essere sostituito con il numero di versione che corrisponde alla versione di Access installata sulla tua macchina:
12.0
:Accesso 200713.0
:saltato per evitare di innescare triskaidekaphobes14.0
:Accesso 201015.0
:Accesso 201316.0
:Accesso 2016 e 2019
Il \Wow6432Node
("Wow" sta per "Windows 32-bit su Windows 64-bit") è richiesto solo se si esegue una versione a 32 bit di Microsoft Access su una versione a 64 bit di Windows. Se Access e Windows sono entrambi a 32 bit o entrambi a 64 bit, quella "cartella" (o "chiave" nel gergo del registro) non è necessaria.
In forma VBA:
If Is32BitAccess Xor Is32BitWindows Then
IncludeWow6432Key = True
Else
IncludeWow6432Key = False
End If
Ad esempio, un'installazione a 32 bit di Access 2010 in esecuzione su Windows a 64 bit richiede la seguente voce di registro:
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Office\14.0\Access Connectivity Engine\Engines\Debug]
"JETSHOWPLAN"="ON"
Allo stesso modo, un'installazione a 64 bit di Access 2019 su Windows a 64 bit richiede:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\16.0\Access Connectivity Engine\Engines\Debug]
"JETSHOWPLAN"="ON"
Dovrei anche notare che la prima volta che crei questa voce, probabilmente dovrai aggiungere la chiave "Debug" (cartella) e il nome e i dati del valore JETSHOWPLAN.
Ecco i passaggi per farlo:
- Esegui regedit come amministratore
- Vai al tasto "\Engines" seguendo le note sopra
- Fai clic con il pulsante destro del mouse su "\Motori" e scegli Nuovo -> Chiave
- Rinomina la chiave da "Nuova chiave n. 1" a "Debug"
Quindi, dovrai aggiungere il valore della stringa "JETSHOWPLAN" con i dati "ON " per abilitare l'aggiunta a showplan.out file o "OFF " per interrompere l'aggiunta al file.
- Fai clic con il tasto destro del mouse sul tasto "\Debug" e scegli Nuovo -> Valore stringa
- Rinomina il valore da "Nuovo valore n. 1" a "JETSHOWPLAN"
- Fai clic con il pulsante destro del mouse sul nome del valore "JETSHOWPLAN" e scegli Modifica...
- Imposta i dati del valore su ON quindi fare clic sul pulsante [OK]
La prossima volta che avvii una nuova istanza di Access, questa inizierà ad aggiungere dati al file Showplan.out. Eventuali istanze di Access già in esecuzione quando apporti le modifiche precedenti non saranno interessate. Lo stesso vale quando disattivi l'impostazione OFF . Le modifiche non hanno effetto finché non avvii un nuovo msaccess.exe esempio. Non è necessario chiudere le istanze esistenti di Access; è possibile avere un'istanza aperta di Access che sta scrivendo attivamente su showplan.out mentre un'istanza diversa di Access non lo è.
Script di hotkey automatico
Non ho intenzione di mentire; saltando su regedit ogni volta che voglio attivare o disattivare JetShowPlan è fastidioso. Se dovessi farlo, difficilmente mi preoccuperei. Ma non devo farlo! Ho creato un tasto di scelta rapida in Autohotkey che attiva e disattiva JetShowPlan.
^#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
Ora, quando voglio ottimizzare le mie query, premo [Ctl] + [Win] + [Q] e vedo una finestra di messaggio che dice "JetShowPlan impostato su ON". Quando ho finito, chiudo Access, premo [Ctl] + [Win] + [Q] e vedo "JetShowPlan impostato su OFF".
Regolazione delle autorizzazioni
Ho due account utente Windows diversi:uno con autorizzazioni standard che utilizzo per il lavoro quotidiano e un altro con autorizzazioni di amministratore per l'installazione di software e così via. Questa è una procedura consigliata per la sicurezza comune.
Il problema è che la chiave di registro di JetShowPlan si trova nell'hive HKLM. Per impostazione predefinita, solo gli amministratori possono apportare modifiche ai valori in quell'hive. Questo è fastidioso perché quando provo a eseguire il mio script Autohotkey ricevo il seguente messaggio di errore:
Non preoccuparti, però. Come suggerisce il messaggio sopra, possiamo risolvere questo problema. La parte migliore è che possiamo renderlo conveniente senza ridurre la nostra posizione di sicurezza. Ecco il trucco.
- Apri regedit come amministratore
- Vai a \Debug chiave
- Fai clic con il pulsante destro del mouse su \Debug chiave e scegli Autorizzazioni...
- Fai clic sul pulsante [Aggiungi...]
- Inserisci il nome utente dalla finestra di messaggio sopra ("Mike"), fai clic su [Controlla nomi], quindi fai clic su [OK]
- Consenti [√] "Controllo completo" per l'utente
- Fai clic su [OK] per salvare le modifiche
Ora quando premo [Ctl] + [Win] + [Q] si attiva e disattiva JetShowPlan, aggiornando automaticamente il registro.
Alla ricerca di Showplan.out
L'accesso non avviserà la posizione in cui il motore di database Jet/ACE aggiunge le informazioni sul piano di query quando JetShowPlan è abilitato. Ho passato più tempo di quanto mi interessa ammettere alla ricerca di una copia canaglia di showplan.out . Questa sezione ti salverà dal condividere quel destino.
Posizione predefinita
Il primo posto in cui cercare è nella cartella Documenti dell'utente corrente. Ad esempio, il mio nome utente di Windows è "Mike", quindi il primo posto in cui mi aspetto di trovare il file è:C:\Users\Mike\Documents\showplan.out
.
Utilizzo di CurDir()
Tecnicamente parlando, lo showplan.out il file viene creato nella directory di lavoro corrente. Di solito è la cartella Documenti dell'utente corrente, ma non sempre. Il modo infallibile per trovare la posizione del file è utilizzare CurDir() funzione.
Puoi copiare, incollare ed eseguire la seguente riga di codice nella finestra immediata dell'IDE VBA per aprire il file showplan.out (supponendo che tu abbia abilitato JetShowPlan nel registro):
Shell "notepad """ & CurDir & "\showplan.out""", vbNormalFocus
Modifica della posizione di output tramite ChDir()
Se per qualche motivo desideri specificare una posizione diversa per showplan.out file, puoi farlo usando la funzione ChDir(). Quella funzione cambia la directory di lavoro corrente. E, come ho detto prima, la directory corrente è dove si trova showplan.out il file risiede. Non appena si modifica la directory di lavoro corrente, JetShowPlan inizia a scrivere nella nuova cartella; non è necessario chiudere e riaprire Access.
Perché potresti volerlo fare? Supponiamo che tu voglia confrontare tre diversi approcci per recuperare gli stessi dati. Scrivi tre diverse query per vedere in che modo le modifiche apportate influiscono sul piano delle query. Da showplan.out è così dettagliato, sarebbe bello avere ogni piano di query nel proprio file. Ciò renderà più facile confrontare i piani di query. Ecco come potrei farlo. Il primo passo è assicurarsi che ciascuna di queste cartelle esista. Quindi, esegui le seguenti righe di codice:
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"
Usa-tutto quello che hai (o scaricalo se non non ce l'ho ancora)
Mentre CurDir() ti darà una posizione definitiva per le modifiche più recenti a showplan.out file, non può dirti quali fossero le precedenti directory di lavoro. E, se hai chiuso l'istanza di Access che ha creato showplan.out file, non vi è alcuna garanzia che la prossima istanza di Access che apri abbia la stessa directory corrente.
Di recente mi sono imbattuto in una piccola utility a portata di mano chiamata "Tutto". È un piccolo eseguibile che indicizza l'intero disco rigido in pochi secondi. Una volta completata l'indicizzazione, puoi cercare istantaneamente file o cartelle in qualsiasi punto del tuo disco.
Puoi scaricare Tutto da qui o tramite Chocolatey:choco install everything
. Apri Tutto , cerca showplan.out
e in meno di un secondo vedrai ogni istanza di showplan.out sul tuo computer insieme alla data dell'ultima modifica. Vorrei avere questo strumento anni fa.
Dare un senso a Showplan.out
La prima volta che apri un showplan.out file, aspettati di essere sconcertato. C'è molto testo e molto di esso è rumore. Ecco un estratto da un file generato quando ho aperto il database di esempio Northwind:
Le query che iniziano con una tilde (~
) rappresentano l'SQL non elaborato che viene salvato nella finestra delle proprietà di un modulo o report e non viene salvato come oggetto QueryDef permanente. I principali punti di interesse sono i passaggi numerati per ogni query:01)
, 02)
, 03)
, ecc. Vuoi seguire questi passaggi alla ricerca di segnali positivi e negativi che potrebbero suggerire dove ci sono problemi.
A mia conoscenza, non esiste alcuna documentazione ufficiale per la formattazione e il contenuto di showplan.out file. Va bene, però, perché non ci faremo prendere dalle minuzie. Il nostro obiettivo principale è identificare problemi palesemente ovvi e affrontarli. Qui si applica la regola 80/20. La maggior parte dei guadagni in termini di prestazioni proverrà da una o due semplici modifiche alle nostre query.
Segnali positivi
Si tratta di indici. Vogliamo che il piano di query utilizzi indici, in particolare nei passaggi iniziali di una query a più passaggi. Due diverse parole chiave indicano che sono in uso gli indici:index
e rushmore
. Rushmore è il nome in codice della tecnologia di ottimizzazione delle query originariamente sviluppata da Fox Software all'inizio degli anni '80. Microsoft ha acquistato l'azienda nel 1992 e ha incorporato la tecnologia nel motore di database Jet.
Le query che utilizzano la tecnologia Rushmore per elaborare gli indici vengono eseguite più velocemente di quelle che utilizzano gli indici in modo più tradizionale. La tecnologia Rushmore può essere utilizzata solo con le tabelle di Access (sia locali che collegate), insieme alle tabelle FoxPro e dBASE collegate. In particolare, Rushmore non può essere utilizzato con tabelle SQL Server collegate. Per aumentare le prestazioni delle tabelle collegate di SQL Server, spesso è meglio scrivere query pass-through, ma questo esula dallo scopo di questo articolo.
Cattivi segnali
Ci sono alcuni segnali negativi a cui prestare attenzione in showplan.out file. La semplice presenza di questi segni non significa necessariamente che ci sia un problema. Detto questo, se stai risolvendo una query con prestazioni scarse, puoi pensare a queste parole come flag di avviso per potenziali problemi:X-Prod
, scanning
, temp
, temporary
.
L'X-Prod viene visualizzata quando si ha una query con un join cartesiano (noto anche come cross join o cross product). Questo di solito accade per errore quando ci si dimentica di unire due tabelle nell'editor Query-by-Example (QBE). Il risultato è che ogni record nella tabella 1 viene confrontato con ogni record nella tabella 2. Il numero totale di record è il prodotto dei due conteggi della tabella. Quindi, se la tabella 1 ha 7 record e la tabella 2 ha 9 record, il cross join delle due tabelle restituisce 63 record. Puoi immaginare il problema se entrambe le tabelle hanno migliaia di record o più.
01) Inner Join table 'Table1' to table 'Table2'
using X-Prod join
La prossima parola chiave da tenere d'occhio è scansione . Se il motore di database non può utilizzare un indice per filtrare i risultati, ricorre alla scansione. Ciò significa che deve esaminare ogni riga singolarmente per vedere se soddisfa i criteri della query. Quando vedi questa parola in un showplan.out file, spesso significa che è necessario aggiungere un indice alla colonna da scansionare. Ma non sempre! Per colonne con cardinalità bassa (solo pochi valori univoci, come una colonna di stato), di solito c'è poco vantaggio nell'aggiunta di un indice. Una volta aggiunto, l'indice deve essere mantenuto. Questo rallenta gli inserimenti e occupa spazio su disco. Inoltre, se le prestazioni della query sono accettabili sui dati di produzione, l'aggiunta di un indice alla colonna scansionata è un'ottimizzazione prematura (che dovresti evitare).
Infine, ci sono le temp e temporaneo parole chiave. Questi indicano che il motore di database ha dovuto eseguire una sorta di operazione su base temporanea. Quando creiamo e salviamo una querydef, quell'oggetto viene salvato con determinati metadati per ottimizzare l'esecuzione ripetuta. Ovviamente, tali metadati vengono persi quando gli indici oi join temporanei escono dall'ambito. Queste parole chiave di solito possono essere ignorate, ma potrebbero indirizzarti nella giusta direzione se rimani perplesso su una query con scarso rendimento senza altri difetti più evidenti.
Per ricapitolare in termini eccessivamente semplificati:
BUONO > > > > > CATTIVO:
Rushmore> indici> temporanei/temporanei> scansione> X-Prod
Lingua personalizzata di Notepad++
Se hai letto i miei altri lavori, sai che ho forti sentimenti sull'aumento del rapporto segnale/rumore nella programmazione (e nella vita in generale). A tal fine, ho creato un file "linguaggio definito dall'utente" in Notepad++ per aggiungere l'evidenziazione della sintassi a showplan.out File. Ora, quando apro showplan.out file, assomigliano allo screenshot qui sotto. Le parole chiave "GOOD" sono colorate in blu e le parole chiave "BAD" sono colorate in rosso. Questo è un esempio di come far sembrare sbagliato il codice sbagliato.
Per configurarlo, segui questi passaggi:
- Apri Blocco note++
- Lingua -> Lingua definita dall'utente -> Definisci la tua lingua...
- Fai clic su [Crea nuovo...]
- Inserisci il nome:showplan.out
- Fai clic su [OK]
- Vai a _| Cartella e Predefinito|_ scheda
- In "Stile pieghevole in codice 2" inserisci
Inputs
per Apri eEnd inputs
per Chiudi - Vai alla scheda _|Elenco parole chiave|_
- Fai clic su [Styler] sotto il 1° gruppo e imposta il colore di primo piano su rosso
- Inserisci le seguenti parole chiave "BAD" nel 1° gruppo:
temp temporary scanning X-Prod
- Fai clic su [Styler] sotto il 2° gruppo e imposta il colore di primo piano su blu
- Inserisci le seguenti parole chiave "BUONE" nel 2° gruppo:
rushmore index
- Inserisci est.:fuori
Pensieri finali
A differenza di SQL Server, il motore di database Jet/ACE non consente di modificare direttamente i piani di esecuzione delle query. Ciò significa che possiamo guardare all'interno della scatola nera con JetShowPlan, ma non possiamo ricablarla per fare ciò che vogliamo. Invece, dobbiamo concentrarci su ciò che possiamo controllare:l'SQL esatto che gli alimentiamo e gli indici e le relazioni tra le tabelle coinvolte.
L'utilizzo di JetShowPlan offre vantaggi sia a breve che a lungo termine. A breve termine, la funzione ti consente di correggere i colli di bottiglia nelle tue applicazioni di Access. A lungo termine, acquisirai informazioni dettagliate sul funzionamento interno di Access che ti aiuta a evitare i colli di bottiglia in primo luogo.