L'un des défis les plus difficiles de SQL Server consiste à résoudre les problèmes de sensibilité des paramètres ou d'estimation de la cardinalité qui entraînent une dégradation des performances d'une charge de travail. Généralement, vous aurez besoin du plan d'exécution réel de l'instruction en cours d'exécution pour pouvoir déterminer la cause de la dégradation des performances. Dans SQL Server 2012, l'événement étendu query_post_execution_showplan permet de capturer le plan d'exécution réel des instructions. Cependant, aussi utile que cela puisse paraître, cet événement ne peut pas être utilisé sans impact significatif sur les performances de la charge de travail exécutée sur le serveur.
Dans mon article Mesurer la « surcharge de l'observateur » de SQL Trace par rapport aux événements étendus, j'ai montré une comparaison de l'impact sur les performances de SQL Trace par rapport à une configuration identique à l'aide d'événements étendus dans SQL Server 2012. À l'époque, j'avais initialement effectué les tests pour cet article. J'ai également effectué de nombreux tests de l'événement query_post_execution_showplan dans SQL Server 2012. Cet événement a été introduit pour la première fois dans SQL Server 2012 CTP1 lorsque de nombreux événements de trace ont été transférés vers des événements étendus pour assurer la parité avec SQL Trace. À ce moment-là, l'événement n'avait qu'un sous-ensemble des colonnes incluses dans le RTM final de SQL Server 2012.
Au cours de CTP1, j'ai soumis un élément Connect demandant qu'une action soit créée pour permettre la collecte du plan d'exécution réel avec des événements dans SQL Server 2012. L'objectif était de pouvoir utiliser les événements module_end ou sql_statement_completed pour identifier quand l'exécution d'une procédure ou déclaration dépasse sa durée normale. Par exemple, dans le scénario de sensibilité des paramètres, où un plan moins idéal est généré pour les valeurs de paramètre normales, l'événement peut être utilisé pour collecter le plan d'exécution réel pour cette instruction via une action. En réponse, l'équipe SQL Server a ajouté les colonnes duration et cpu_time à l'événement query_post_execution_showplan pour permettre aux définitions de prédicat de ne collecter cet événement que pour ces scénarios.
Malheureusement, cela n'a pas les mêmes avantages qu'une implémentation en tant qu'action aurait eu sur les performances. Dans la suite de cet article, je vais vous expliquer pourquoi.
Impact sur les performances
Au moment où j'ai fait les tests pour mon article précédent, j'ai également testé la surcharge associée à l'événement query_post_execution_showplan, principalement parce que j'étais vraiment intéressé à l'utiliser dans quelques systèmes de production clients et avant de le faire, j'avais besoin de comprendre ce que genre d'impact que l'événement aurait sur leur charge de travail. J'ai été vraiment consterné par les résultats que j'ai obtenus de mes tests d'origine, et après avoir fait valider mes résultats par Aaron Bertrand à l'aide du harnais de test interne de SQL Sentry, j'ai déposé un autre élément Connect signalant les problèmes de performances qui a ensuite été fermé comme "By Design" .
Pour tester l'impact sur les performances, la même charge de travail et la même configuration de relecture distribuée que celles de l'article Mesure de la « surcharge de l'observateur » de SQL Trace par rapport aux événements étendus ont été utilisées. La seule différence pour les résultats des tests présentés dans cet article est qu'un système hôte plus récent et plus puissant a été utilisé pour l'environnement VM. Les machines virtuelles utilisées étaient exactement les mêmes, sans modification de leur configuration, et elles ont simplement été copiées sur le nouveau système, c'est pourquoi la charge de travail de base a pu effectuer la relecture plus rapidement avec une moyenne plus élevée de requêtes par lots/s. Les résultats de base ont été capturés à l'aide d'une installation standard de SQL Server 2012 avec uniquement la session d'événements system_health par défaut exécutée sur le serveur.
Pour la comparaison de l'impact sur les performances de query_post_execution_showplan
événement, la définition de session d'événement suivante a été utilisée.
CREATE EVENT SESSION [query_post_execution_showplan Overhead] ON SERVER ADD EVENT sqlserver.query_post_execution_showplan( WHERE ([duration]=(5000000))); GO
Cette session ne collecte pas réellement les données d'événement à l'aide d'une cible et utilise un prédicat sur la durée pour que la durée de l'événement soit égale à 5000000 microsecondes, soit une durée de cinq secondes. Pour la charge de travail de relecture, aucune instruction ne s'exécute pendant exactement cinq secondes, de sorte que l'événement query_post_execution_showplan ne se déclenche jamais réellement sur le serveur, et toute dégradation des performances est strictement le résultat de la collecte des données d'événement, puis de l'évaluation du prédicat. Les résultats des tests sont présentés dans le tableau 1 et représentés dans le graphique 2.
Tableau 1 – surcharge de l'événement query_post_execution
Graphique 2 – surcharge de l'événement query_post_execution
Pour cette série de tests, les performances de la charge de travail se dégradent d'environ 30 % simplement en activant cet événement dans une session d'événements, même s'il ne se déclenche pour aucun des événements qui sont relus sur le serveur. La dégradation globale dépendra de la charge de travail réelle du serveur, et il est important de noter que cette série de tests reflète davantage le pire scénario puisque la relecture distribuée a été exécutée en mode stress et que l'utilisation du processeur sur le serveur SQL a été indexée. à 94% en moyenne lors des tests.
Comprendre l'impact sur les performances
La raison pour laquelle cet événement impose une charge aussi importante sur les performances peut être expliquée à partir du cycle de vie de l'événement dans les événements étendus. Lorsqu'un point critique dans le code SQL Server associé à un événement est rencontré lors de l'exécution, le code effectue une vérification booléenne très rapide pour déterminer si l'événement est activé dans une session d'événement active sur le serveur. Si l'événement est activé pour une session d'événement active, toutes les colonnes de données associées à l'événement sont collectées, y compris toutes les colonnes personnalisables qui ont été activées. À ce stade, l'événement évalue tous les prédicats des sessions d'événements actives qui collectent l'événement pour déterminer si l'événement se déclenchera réellement complètement.
Pour l'événement query_post_exection_showplan, tout l'impact sur les performances provient de la surcharge associée à la collecte de données. Même dans le cas où il existe un prédicat d'une durée égale à cinq secondes, simplement en activant l'événement dans une session d'événements, il doit collecter le Showplan XML pour chaque instruction qui s'exécute sur le serveur juste pour pouvoir évaluer le prédicat puis déterminez que l'événement ne se déclenchera pas. Pour cette raison, l'événement query_post_execution_showplan doit être évité pour les charges de travail de production. Pour la charge de travail de relecture de test, l'événement a dû être évalué environ 440 000 fois, même s'il ne se déclenche pas réellement pour la charge de travail et la session d'événements testés, car aucun des événements de relecture n'a une durée d'exactement cinq secondes. Les informations sur le nombre d'événements ont été collectées en ajoutant la cible event_counter à la session d'événements et en supprimant le prédicat de durée, puis en retestant la charge de travail de relecture avec la définition de session suivante.
CREATE EVENT SESSION [query_post_execution_showplan Overhead] ON SERVER ADD EVENT sqlserver.query_post_execution_showplan ADD TARGET package0.event_counter; GO
Comparaison avec les événements à déclenchement rapide
Pour fournir un cadre de référence pour cet impact sur les performances, nous pouvons examiner la surcharge liée à l'activation d'un ensemble d'événements s'exécutant fréquemment sur le serveur et à l'exécution de la même charge de travail de relecture. Deux des événements les plus fréquemment exécutés dans SQL Server sont les événements lock_acquired et lock_released. Pour comparer la surcharge de ces deux événements, la session d'événements suivante peut être utilisée, qui collecte les événements sans prédicat afin que chaque exécution soit collectée et compte la fréquence à laquelle ils se déclenchent à l'aide de la cible event_counter.
CREATE EVENT SESSION [locking Overhead] ON SERVER ADD EVENT sqlserver.lock_acquired, ADD EVENT sqlserver.lock_released ADD TARGET package0.event_counter; GO
Pour notre charge de travail de relecture, ces deux événements se déclenchent environ 111 180 000 fois. Les frais généraux associés à la collecte de ces événements peuvent être consultés dans le tableau 3 et le graphique 4.
Tableau 3 – Comparaison de surcharge de verrouillage
Graphique 4 – Comparaison de la surcharge des événements de verrouillage
Comme vous pouvez le voir à partir des données, l'effet sur les performances de ces événements est nettement inférieur à celui de query_post_execution_showplan, même si la définition de la session d'événements de verrouillage a été configurée pour permettre à tous les événements de se déclencher sur le serveur, la surcharge totale était inférieure à 1 % dans l'ensemble. . Gardez à l'esprit que la session d'événements de verrouillage a évalué l'équivalent de 500 fois plus d'événements, et dans ce cas, tous les événements ont dû se déclencher pour la session d'événements, où l'événement query_post_execution_showplan n'a pas eu à se déclencher après avoir été évalué.
Résumé
Alors que l'événement query_post_execution_showplan offre la possibilité de collecter le plan de requête réel pour une instruction qui s'exécute, l'impact sur les performances de la collecte de données juste pour évaluer l'événement en fait quelque chose qui n'est pas viable pour une utilisation en production. Au minimum, la surcharge doit être prise en compte avant d'utiliser cet événement sur une charge de travail de production. Même la description de l'événement fournie par Microsoft reconnaît que l'événement peut avoir un impact significatif sur les performances (mon surlignage) :
Se produit après l'exécution d'une instruction SQL. Cet événement renvoie une représentation XML du plan de requête réel. L'utilisation de cet événement peut entraîner une surcharge de performances significative. Il ne doit donc être utilisé que lors du dépannage ou de la surveillance de problèmes spécifiques pendant de brèves périodes.La description de l'événement se trouve dans la colonne de description de la vue du catalogue sys.dm_xe_objects ou dans l'interface utilisateur de la nouvelle session, comme illustré à la figure 5 (ma mise en surbrillance) :
Figure 5 – Description de l'événement de l'interface utilisateur de la nouvelle session
Je recommanderais de comparer les performances de tout événement avec cet avertissement dans la description avant de l'utiliser réellement dans un environnement de production.