J'ai toujours trouvé l'excellent tableau d'Itzik Ben-Gan sur le traitement SQL logique extrêmement utile pour raisonner sur les performances d'interrogation. Même si le graphique a été créé pour SQL Server, il s'applique toujours à tout moteur de base de données conforme à la norme SQL, qui inclut également le moteur de base de données Access. Bien que nous aimions utiliser les bases de données SQL Server, nous avons occasionnellement des bases de données Access ou des applications Access qui nécessitent l'utilisation de requêtes Access (par exemple, des tables temporaires pour les rapports). L'accès n'est pas fourni avec des outils de profilage fantaisistes, alors que devons-nous faire ?
Jerry-rigging notre propre utilitaire de trace
Cela m'a amené à me demander - pourrait-on déterminer quand une clause d'une requête SQL est exécutée et à quelle fréquence? L'accès a un moyen d'afficher les plans d'exécution, mais il n'entre pas dans les détails de comment et quand les détails sont traités. Il existe un moyen détourné de déduire le physique ordre de traitement utilisé par le moteur de base de données Access :une fonction VBA personnalisée !
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 =TrueEnd FunctionCela peut être enregistré dans un module standard. On peut alors mettre en place un tableau simple :
Tracer les clauses d'une requête Access
Avec cette configuration, nous pouvons créer une requête Access et saupoudrer le
Trace
dans différentes parties de la requête Access. Voici un exemple :SELECT c1.ColorID, Trace("SELECT") AS Ignored1, Trace("SELECT",c1.Color) AS Ignored2FROM tblColor AS c1 WHERE Trace("WHERE") <> 0 AND Trace("WHERE", c1 .Couleur) <> 0ORDER BY Trace("ORDER BY"), Trace("ORDER BY", c1.Color);Si vous ouvrez ensuite la requête en mode feuille de données, puis passez à la fenêtre immédiate du VBIDE, vous devriez voir la sortie comme ceci :
WHERE #Aucune valeur#ORDER BY #Aucune valeur#SELECT #Aucune valeur#WHERE RougeORDER BY RougeWHERE VertORDER BY VertWHERE BleuORDER BY BleuSELECT BleuSELECT VertSELECT RougeCela nous donne un aperçu de la façon dont Access résout la requête, ce qui peut être utile lorsque vous devez optimiser une requête peu performante. Voyons ce que nous pouvons apprendre :
- Nous pouvons voir que s'il n'y a pas de références de colonne, la fonction VBA est appelée le plus tôt possible car Access reconnaît qu'elle ne peut avoir qu'une seule valeur pour l'ensemble du résultat, il est donc inutile d'appeler la fonction encore et encore uniquement pour obtenir la même réponse. Vous pouvez voir que le
Trace
les invocations sans le 2e argument facultatif ont été évaluées en premier avant toutes les autres invocations contenant une référence de colonne dans le 2e argument facultatif. - En corollaire du point précédent, si l'invocation contient une référence de colonne, elle doit alors être évaluée au moins une fois pour chaque ligne. Vous pouvez voir que nous passons en revue chaque valeur de couleur lors de l'évaluation de la clause.
- Nous voyons que l'ordre est généralement similaire à ce que nous voyons dans le tableau d'Itzik Ben-Gan ;
WHERE
est évalué le plus tôt possible,ORDER BY
est évalué après avoir éliminé toutes les lignes non éligibles, puis tout ce qui reste,SELECT
est ensuite évalué. - Bien que nous nous attendions à ce que le tri soit appliqué après avoir filtré les lignes non qualifiantes, il semble qu'Access préfère essayer de trier la sortie dès que possible, peut-être parce qu'il est moins coûteux d'insérer une nouvelle ligne dans un fichier trié list sur le tri de l'ensemble.
Expériences et conclusions supplémentaires
Vous pouvez expérimenter un peu avec une requête différente. Par exemple, vous pouvez savoir quand/souvent Access traite GROUP BY
, en utilisant une requête similaire à celle-ci :
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 ].[Couleur]) <> 0GROUP BY c1.ColorID, Trace("GROUP BY", c1.Color)ORDER BY c1.ColorID ;
Vous pouvez ensuite l'utiliser en conjonction avec JetShowPlan pour en savoir plus sur ce que fait réellement le moteur de base de données. J'espère que cela vous aidera à mieux comprendre comment vous pouvez améliorer les performances de votre requête Access. En tant que défi, vous pourriez expliquer pourquoi Access exécute le GROUP BY
la façon dont il le fait. Je vous encourage également à expérimenter l'ouverture d'une fiche technique et le défilement. Vous découvrirez alors que le SELECT
est réévalué à la suite de la navigation.
Je dois souligner que la technique ci-dessus nous donne un aperçu de la physique plan de traitement, plutôt que l'ordre de traitement logique tel que décrit dans le tableau. En conséquence, nous devrions nous attendre à ce que le plan soit différent pour différents volumes de données ou pour différentes requêtes. Nous devons également considérer que l'ajout de la Trace
la fonction peut influencer le plan. Cependant, je dirais que si vous êtes si préoccupé par ces considérations, il est probablement préférable de déplacer cette requête et ses données sous-jacentes vers une base de données SQL Server où vous avez beaucoup plus d'options pour optimiser les performances de la requête.
Amusez-vous !
Besoin d'aide avec les requêtes Microsoft Access ? Appelez Access Experts au (773) 809 5456 ou envoyez un e-mail à l'équipe dès aujourd'hui.