Access
 sql >> Database >  >> RDS >> Access

Valutazione quando viene valutata un'espressione in una query

Ho sempre trovato l'eccellente grafico di Itzik Ben-Gan sull'elaborazione logica SQL immensamente utile per ragionare sulle prestazioni di query. Anche se il grafico è stato creato per SQL Server, è ancora applicabile a qualsiasi motore di database che segue SQL Standard, che include anche il motore di database di Access. Sebbene amiamo usare i database di SQL Server, abbiamo occasionali database di Access o applicazioni di Access che richiedono l'uso di query di Access (ad es. tabelle temporanee per la creazione di report). L'accesso non viene fornito con strumenti di profilazione fantasiosi, quindi cosa dobbiamo fare?

Jerry-rigging la nostra utilità di traccia

Questo mi ha portato a chiedermi:si potrebbe determinare quando una clausola di una query SQL viene eseguita e con quale frequenza? Access ha un mezzo per mostrare i piani di esecuzione ma non entra nei dettagli di come e quando i dettagli vengono elaborati. C'è un modo indiretto per dedurre il fisico ordine di elaborazione utilizzato dal motore di database di Access:una funzione VBA personalizzata!

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

Questo può essere salvato in un modulo standard. Possiamo quindi impostare una semplice tabella:

Tracciamento delle clausole di una query di Access

Con questa configurazione, possiamo creare una query di Access e spruzzare il Trace in diverse parti della query di Access. Ecco un esempio:

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

Se quindi apri la query nella visualizzazione foglio dati, quindi vai alla finestra immediata di VBIDE, dovresti vedere l'output in questo modo:

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

Questo ci fornisce alcune informazioni su come Access risolve la query che può essere utile quando è necessario ottimizzare una query con prestazioni scadenti. Vediamo cosa possiamo imparare:

  • Possiamo vedere che se non ci sono riferimenti di colonna, la funzione VBA viene chiamata il prima possibile poiché Access riconosce che possono avere un solo valore per l'intero set di risultati, quindi non ha senso chiamare la funzione ancora e ancora solo per ottenere la stessa risposta. Puoi vedere che il Trace le chiamate senza il 2° argomento facoltativo sono state valutate prima di tutte le altre chiamate contenenti un riferimento a una colonna nel 2° argomento facoltativo.
  • Come corollario del punto precedente, se l'invocazione contiene un riferimento di colonna, deve essere valutato almeno una volta per ogni riga. Puoi vedere che esaminiamo ogni valore di colore quando valutiamo la clausola.
  • Vediamo che l'ordine è generalmente simile a quello che vediamo nel grafico di Itzik Ben-Gan; WHERE viene valutato il prima possibile, ORDER BY viene valutato dopo aver eliminato tutte le righe non qualificanti, quindi tutto ciò che rimane, SELECT viene quindi valutato.
  • Sebbene ci si aspetterebbe che l'ordinamento venga applicato dopo aver filtrato le righe non qualificanti, sembra che Access preferisca provare a ordinare l'output il prima possibile, probabilmente perché è più economico inserire una nuova riga in un ordine elenco sull'ordinamento dell'intero set.

Ulteriori esperimenti e conclusioni

Puoi sperimentare un po' con una query diversa. Ad esempio, puoi ottenere informazioni dettagliate su quando/spesso Accede ai processi GROUP BY , utilizzando una query simile a questa:

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;

È quindi possibile utilizzarlo insieme a JetShowPlan per ulteriori informazioni sulle operazioni effettivamente eseguite dal motore di database. Si spera che possa essere utile per ottenere informazioni dettagliate su come migliorare le prestazioni della query di Access. Come sfida, potresti spiegare perché Access esegue il GROUP BY il modo in cui lo fa. Ti incoraggio anche a sperimentare l'apertura di un foglio dati e lo scorrimento. Scoprirai quindi che il SELECT viene rivalutato a seguito della navigazione.

Vorrei sottolineare che la tecnica sopra ci fornisce informazioni sul fisico piano di elaborazione, piuttosto che l'ordine di elaborazione logico come descritto nel grafico. Di conseguenza, dovremmo aspettarci che il piano sia diverso per diversi volumi di dati o per query diverse. Dobbiamo anche considerare che aggiungendo il Trace funzione può influenzare il piano. Tuttavia, direi che se sei così preoccupato per queste considerazioni, probabilmente è meglio spostare quella query e i suoi dati sottostanti in un database di SQL Server in cui hai molte più opzioni per ottimizzare le prestazioni della query.

Buon divertimento!

Hai bisogno di aiuto con le query di Microsoft Access? Chiama gli esperti di accesso al numero (773) 809 5456 o invia un'email al team oggi stesso.