Comment obtenir un plan d'exécution de requête dans SQL Server?

338

Dans Microsoft SQL Server, comment puis-je obtenir un plan d'exécution de requête pour une requête / procédure stockée?

Justin
la source
2
Comment fermer l'onglet Plan d'exécution dans SQL Server Management Studio?
Paul McCarthy
2
@Paul Vous pouvez appuyer sur Ctrl + R pour cela. Il ferme toute la section des résultats - y compris les messages et le plan d'exécution.
Nisarg

Réponses:

502

Il existe un certain nombre de méthodes pour obtenir un plan d'exécution, laquelle à utiliser dépendra de votre situation. Habituellement, vous pouvez utiliser SQL Server Management Studio pour obtenir un plan, mais si, pour une raison quelconque, vous ne pouvez pas exécuter votre requête dans SQL Server Management Studio, il peut être utile de pouvoir obtenir un plan via SQL Server Profiler ou en inspectant le cache du plan.

Méthode 1 - Utilisation de SQL Server Management Studio

SQL Server est livré avec quelques fonctionnalités intéressantes qui facilitent la capture d'un plan d'exécution, assurez-vous simplement que l'élément de menu "Inclure le plan d'exécution réel" (situé sous le menu "Requête") est coché et exécutez votre requête normalement .

Inclure l'élément de menu Plan d'exécution des actions

Si vous essayez d'obtenir le plan d'exécution des instructions dans une procédure stockée, vous devez exécuter la procédure stockée, comme suit:

exec p_Example 42

Une fois votre requête terminée, un onglet supplémentaire intitulé "Plan d'exécution" devrait apparaître dans le volet des résultats. Si vous avez exécuté plusieurs instructions, vous pouvez voir de nombreux plans affichés dans cet onglet.

Capture d'écran d'un plan d'exécution

De là, vous pouvez inspecter le plan d'exécution dans SQL Server Management Studio, ou cliquer avec le bouton droit sur le plan et sélectionner "Enregistrer le plan d'exécution sous ..." pour enregistrer le plan dans un fichier au format XML.

Méthode 2 - Utilisation des options SHOWPLAN

Cette méthode est très similaire à la méthode 1 (en fait, c'est ce que fait SQL Server Management Studio en interne), mais je l'ai incluse pour être complet ou si vous n'avez pas SQL Server Management Studio disponible.

Avant d'exécuter votre requête, exécutez l' une des instructions suivantes. L'instruction doit être la seule instruction du lot, c'est-à-dire que vous ne pouvez pas exécuter une autre instruction en même temps:

SET SHOWPLAN_TEXT ON
SET SHOWPLAN_ALL ON
SET SHOWPLAN_XML ON
SET STATISTICS PROFILE ON
SET STATISTICS XML ON -- The is the recommended option to use

Ce sont des options de connexion et vous n'avez donc besoin de l'exécuter qu'une seule fois par connexion. À partir de ce moment, toutes les instructions exécutées seront accompagnées d'un jeu de résultats supplémentaire contenant votre plan d'exécution au format souhaité - exécutez simplement votre requête comme vous le feriez normalement pour voir le plan.

Une fois que vous avez terminé, vous pouvez désactiver cette option avec l'instruction suivante:

SET <<option>> OFF

Comparaison des formats de plan d'exécution

Sauf si vous avez une forte préférence, ma recommandation est d'utiliser l' STATISTICS XMLoption. Cette option est équivalente à l'option «Inclure le plan d'exécution réel» dans SQL Server Management Studio et fournit le plus d'informations dans le format le plus pratique.

  • SHOWPLAN_TEXT - Affiche un plan d'exécution estimé basé sur du texte de base, sans exécuter la requête
  • SHOWPLAN_ALL - Affiche un plan d'exécution estimé basé sur du texte avec des estimations de coûts, sans exécuter la requête
  • SHOWPLAN_XML- Affiche un plan d'exécution estimé basé sur XML avec des estimations de coûts, sans exécuter la requête. Cela équivaut à l'option "Afficher le plan d'exécution estimé ..." dans SQL Server Management Studio.
  • STATISTICS PROFILE - Exécute la requête et affiche un plan d'exécution réel basé sur du texte.
  • STATISTICS XML- Exécute la requête et affiche un plan d'exécution réel basé sur XML. Cela équivaut à l'option «Inclure le plan d'exécution réel» dans SQL Server Management Studio.

Méthode 3 - Utilisation de SQL Server Profiler

Si vous ne pouvez pas exécuter votre requête directement (ou si votre requête ne s'exécute pas lentement lorsque vous l'exécutez directement - n'oubliez pas que nous voulons que le plan de la requête fonctionne mal), vous pouvez capturer un plan à l'aide d'une trace de SQL Server Profiler. L'idée est d'exécuter votre requête pendant qu'une trace qui capture l'un des événements "Showplan" est en cours d'exécution.

Notez qu'en fonction de la charge, vous pouvez utiliser cette méthode dans un environnement de production, mais vous devez évidemment faire preuve de prudence. Les mécanismes de profilage SQL Server sont conçus pour minimiser l'impact sur la base de données, mais cela ne signifie pas qu'il n'y aura aucun impact sur les performances. Vous pouvez également rencontrer des problèmes pour filtrer et identifier le plan correct dans votre trace si votre base de données est fortement utilisée. Vous devriez évidemment vérifier auprès de votre DBA pour voir s'il est content que vous le fassiez sur sa précieuse base de données!

  1. Ouvrez SQL Server Profiler et créez une nouvelle trace se connectant à la base de données souhaitée sur laquelle vous souhaitez enregistrer la trace.
  2. Dans l'onglet "Sélection d'événements", cochez "Afficher tous les événements", cochez la ligne "Performances" -> "Showplan XML" et exécutez la trace.
  3. Pendant l'exécution de la trace, effectuez tout ce que vous devez faire pour exécuter la requête à exécution lente.
  4. Attendez que la requête se termine et arrêtez la trace.
  5. Pour enregistrer la trace, cliquez avec le bouton droit sur le plan xml dans SQL Server Profiler et sélectionnez "Extraire les données d'événement ..." pour enregistrer le plan dans un fichier au format XML.

Le plan que vous obtenez est équivalent à l'option «Inclure le plan d'exécution réel» dans SQL Server Management Studio.

Méthode 4 - Inspection du cache de requêtes

Si vous ne pouvez pas exécuter votre requête directement et que vous ne pouvez pas également capturer une trace de profileur, vous pouvez toujours obtenir un plan estimé en inspectant le cache du plan de requête SQL.

Nous inspectons le cache du plan en interrogeant les DMV SQL Server . Ce qui suit est une requête de base qui répertorie tous les plans de requête mis en cache (au format xml) avec leur texte SQL. Sur la plupart des bases de données, vous devrez également ajouter des clauses de filtrage supplémentaires pour filtrer les résultats jusqu'aux plans qui vous intéressent.

SELECT UseCounts, Cacheobjtype, Objtype, TEXT, query_plan
FROM sys.dm_exec_cached_plans 
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
CROSS APPLY sys.dm_exec_query_plan(plan_handle)

Exécutez cette requête et cliquez sur le plan XML pour ouvrir le plan dans une nouvelle fenêtre - faites un clic droit et sélectionnez "Enregistrer le plan d'exécution sous ..." pour enregistrer le plan dans un fichier au format XML.

Remarques:

Parce qu'il y a tellement de facteurs impliqués (allant du schéma de table et d'index jusqu'aux données stockées et aux statistiques de table), vous devriez toujours essayer d'obtenir un plan d'exécution à partir de la base de données qui vous intéresse (normalement celle qui connaît une performance problème).

Vous ne pouvez pas capturer un plan d'exécution pour des procédures stockées chiffrées.

Plans d'exécution "réels" vs "estimés"

Un plan d'exécution réel est celui où SQL Server exécute réellement la requête, tandis qu'un plan d'exécution estimé SQL Server détermine ce qu'il ferait sans exécuter la requête. Bien que logiquement équivalent, un plan d'exécution réel est beaucoup plus utile car il contient des détails et des statistiques supplémentaires sur ce qui s'est réellement passé lors de l'exécution de la requête. Cela est essentiel lors du diagnostic de problèmes lorsque les estimations des serveurs SQL sont désactivées (par exemple lorsque les statistiques sont obsolètes).

Comment interpréter un plan d'exécution de requête?

C'est un sujet assez digne pour un livre (gratuit) à part entière.

Voir également:

Justin
la source
8
Une note pour les futurs lecteurs: placez SET STATISTICS XML ONle début de la requête et SET STATISTICS XML OFF|ONles zones environnantes que vous ne voulez pas voir apparaître dans la sortie du plan: j'ai trouvé cela utile lorsque la requête contient une itération (TANT) que vous ne voulez pas / n'avez pas besoin à voir dans le plan d'exécution (sinon il serait trop lourd et long pour SQL SERVER de l'afficher).
Roimer
2
@MonsterMMORPG, vous pouvez utiliser la méthode 4, puis la sélectionner. Par exemple, en utilisant <a href=" github.com/StackExchange/dapper-dot-net"> Dapper.net </… > connection.Query <string> ("SELECT query_plan FROM sys.dm_exec_cached_plans CROSS APPLY sys.dm_exec_sql_text (plan_handle ) CROSS APPLY sys.dm_exec_query_plan (plan_handle) OERE LE TEXTE COMME N '% Votre requête d'origine va ici%' "); Les% sont si vous n'utilisez qu'un sous-ensemble de votre requête.
bmarks
2
@Justin la 2ème édition du livre auquel vous avez lié, pour interpréter un plan d'exécution de requête, date de 2009. Diriez-vous toujours que c'est une très bonne ressource à cet effet en 2016?
Abdul
3
@Abdul Le même auteur, Grant Fritchey, a un livre plus récent appelé SQL Server Query Performance Tuning qui couvre les nouvelles versions de SQL Server.
thelem
42

En plus de la réponse complète déjà publiée, il est parfois utile de pouvoir accéder au plan d'exécution par programme pour extraire des informations. Un exemple de code pour cela est ci-dessous.

DECLARE @TraceID INT
EXEC StartCapture @@SPID, @TraceID OUTPUT
EXEC sp_help 'sys.objects' /*<-- Call your stored proc of interest here.*/
EXEC StopCapture @TraceID

Exemple de StartCapturedéfinition

CREATE PROCEDURE StartCapture
@Spid INT,
@TraceID INT OUTPUT
AS
DECLARE @maxfilesize BIGINT = 5
DECLARE @filepath NVARCHAR(200) = N'C:\trace_' + LEFT(NEWID(),36)

EXEC sp_trace_create @TraceID OUTPUT, 0, @filepath, @maxfilesize, NULL 

exec sp_trace_setevent @TraceID, 122, 1, 1
exec sp_trace_setevent @TraceID, 122, 22, 1
exec sp_trace_setevent @TraceID, 122, 34, 1
exec sp_trace_setevent @TraceID, 122, 51, 1
exec sp_trace_setevent @TraceID, 122, 12, 1
-- filter for spid
EXEC sp_trace_setfilter @TraceID, 12, 0, 0, @Spid
-- start the trace
EXEC sp_trace_setstatus @TraceID, 1

Exemple de StopCapturedéfinition

CREATE  PROCEDURE StopCapture
@TraceID INT
AS
WITH  XMLNAMESPACES ('http://schemas.microsoft.com/sqlserver/2004/07/showplan' as sql), 
      CTE
     as (SELECT CAST(TextData AS VARCHAR(MAX)) AS TextData,
                ObjectID,
                ObjectName,
                EventSequence,
                /*costs accumulate up the tree so the MAX should be the root*/
                MAX(EstimatedTotalSubtreeCost) AS EstimatedTotalSubtreeCost
         FROM   fn_trace_getinfo(@TraceID) fn
                CROSS APPLY fn_trace_gettable(CAST(value AS NVARCHAR(200)), 1)
                CROSS APPLY (SELECT CAST(TextData AS XML) AS xPlan) x
                CROSS APPLY (SELECT T.relop.value('@EstimatedTotalSubtreeCost',
                                            'float') AS EstimatedTotalSubtreeCost
                             FROM   xPlan.nodes('//sql:RelOp') T(relop)) ca
         WHERE  property = 2
                AND TextData IS NOT NULL
                AND ObjectName not in ( 'StopCapture', 'fn_trace_getinfo' )
         GROUP  BY CAST(TextData AS VARCHAR(MAX)),
                   ObjectID,
                   ObjectName,
                   EventSequence)
SELECT ObjectName,
       SUM(EstimatedTotalSubtreeCost) AS EstimatedTotalSubtreeCost
FROM   CTE
GROUP  BY ObjectID,
          ObjectName  

-- Stop the trace
EXEC sp_trace_setstatus @TraceID, 0
-- Close and delete the trace
EXEC sp_trace_setstatus @TraceID, 2
GO
Martin Smith
la source
18

En supposant que vous utilisez Microsoft SQL Server Management Studio

  • Pour le plan de requête estimé, vous pouvez appuyer sur Ctrl + L ou sur le bouton suivant.

entrez la description de l'image ici

  • Pour le plan de requête réel , vous pouvez appuyer sur Ctrl + M ou sur le bouton suivant avant d'exécuter la requête.

entrez la description de l'image ici

  • Pour Live Query Plan , (uniquement dans SSMS 2016), utilisez le bouton suivant avant d'exécuter la requête.

entrez la description de l'image ici

Tigerjz32
la source
15

Outre les méthodes décrites dans les réponses précédentes, vous pouvez également utiliser un visualiseur de plan d'exécution gratuit et un outil d'optimisation de requête ApexSQL Plan (que j'ai récemment rencontré).

Vous pouvez installer et intégrer ApexSQL Plan dans SQL Server Management Studio, afin que les plans d'exécution puissent être affichés directement à partir de SSMS.

Affichage des plans d'exécution estimés dans ApexSQL Plan

  1. Cliquez sur le bouton Nouvelle requête dans SSMS et collez le texte de la requête dans la fenêtre de texte de la requête. Faites un clic droit et sélectionnez l'option «Afficher le plan d'exécution estimé» dans le menu contextuel.

Nouveau bouton de requête dans SSMS

  1. Les diagrammes du plan d'exécution seront affichés dans l'onglet Plan d'exécution dans la section des résultats. Cliquez ensuite avec le bouton droit sur le plan d'exécution et dans le menu contextuel, sélectionnez l'option «Ouvrir dans le plan ApexSQL».

Plan d'exécution

  1. Le plan d'exécution estimé sera ouvert dans ApexSQL Plan et pourra être analysé pour l'optimisation des requêtes.

Plan d'exécution estimé

Affichage des plans d'exécution réels dans le plan ApexSQL

Pour afficher le plan d'exécution réel d'une requête, poursuivez à partir de la 2e étape mentionnée précédemment, mais maintenant, une fois le plan estimé affiché, cliquez sur le bouton «Réel» dans la barre de ruban principale d'ApexSQL Plan.

cliquez sur le bouton "Réel" dans la barre de ruban principale

Une fois que vous avez cliqué sur le bouton «Réel», le plan d'exécution réel s'affiche avec un aperçu détaillé des paramètres de coût ainsi que d'autres données du plan d'exécution.

Plan d'exécution réel

Pour plus d'informations sur l'affichage des plans d'exécution, cliquez sur ce lien .

Marcin Czyz
la source
14

Mon outil préféré pour obtenir et analyser en profondeur les plans d'exécution des requêtes est SQL Sentry Plan Explorer . Il est beaucoup plus convivial, pratique et complet pour l'analyse détaillée et la visualisation des plans d'exécution que SSMS.

Voici un exemple de capture d'écran pour que vous ayez une idée des fonctionnalités offertes par l'outil:

Capture d'écran de la fenêtre de SQL Sentry Plan Explorer

Ce n'est qu'une des vues disponibles dans l'outil. Remarquez un ensemble d'onglets en bas de la fenêtre de l'application, qui vous permet d'obtenir également différents types de représentation de votre plan d'exécution et des informations supplémentaires utiles.

De plus, je n'ai remarqué aucune limitation de son édition gratuite qui empêche de l'utiliser quotidiennement ou vous oblige à acheter la version Pro à terme. Donc, si vous préférez vous en tenir à l'édition gratuite, rien ne vous en empêche.

MISE À JOUR: (Merci à Martin Smith ) Plan Explorer est maintenant gratuit! Voir http://www.sqlsentry.com/products/plan-explorer/sql-server-query-view pour plus de détails.

Alexander Abakumov
la source
1
Qui parlait d'outils tiers?
basher
12
@basher: OP n'a pas limité les moyens avec les outils MS ou autrement. Alors, qu'est-ce qui vous fait penser qu'une réponse impliquant un outil tiers est inappropriée?
Alexander Abakumov
3
Je plaisantais simplement avec la façon dont vous avez formulé le début de votre réponse Speaking of third-party toolslorsque personne n'a mentionné d'outils tiers.
basher
4
@basher: Oh, belle prise! Je vous remercie! J'ai réécrit ma réponse. N'hésitez pas à donner votre avis et / ou à voter si vous le souhaitez.
Alexander Abakumov
3
BTW il n'y a qu'une seule version maintenant sqlsentry.com/products/plan-explorer/sql-server-query-view
Martin Smith
7

Les plans de requête peuvent être obtenus à partir d'une session d'événements étendus via l' query_post_execution_showplanévénement. Voici un exemple de session XEvent:

/*
    Generated via "Query Detail Tracking" template.
*/
CREATE EVENT SESSION [GetExecutionPlan] ON SERVER 
ADD EVENT sqlserver.query_post_execution_showplan(
    ACTION(package0.event_sequence,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)),

/* Remove any of the following events (or include additional events) as desired. */
ADD EVENT sqlserver.error_reported(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.module_end(SET collect_statement=(1)
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.rpc_completed(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.sp_statement_completed(SET collect_object_name=(1)
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.sql_batch_completed(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.sql_statement_completed(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))) 
ADD TARGET package0.ring_buffer
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF)
GO

Après avoir créé la session, (dans SSMS), accédez à l'Explorateur d'objets et explorez Gestion | Événements prolongés | Sessions. Cliquez avec le bouton droit sur la session "GetExecutionPlan" et démarrez-la. Faites un clic droit dessus et sélectionnez "Regarder les données en direct".

Ensuite, ouvrez une nouvelle fenêtre de requête et exécutez une ou plusieurs requêtes. En voici un pour AdventureWorks:

USE AdventureWorks;
GO

SELECT p.Name AS ProductName, 
    NonDiscountSales = (OrderQty * UnitPrice),
    Discounts = ((OrderQty * UnitPrice) * UnitPriceDiscount)
FROM Production.Product AS p 
INNER JOIN Sales.SalesOrderDetail AS sod
    ON p.ProductID = sod.ProductID 
ORDER BY ProductName DESC;
GO

Après un moment ou deux, vous devriez voir des résultats dans l'onglet "GetExecutionPlan: Live Data". Cliquez sur l'un des événements query_post_execution_showplan dans la grille, puis cliquez sur l'onglet "Plan de requête" sous la grille. Il devrait ressembler à ceci:

entrez la description de l'image ici

EDIT : Le code XEvent et la capture d'écran ont été générés à partir de SQL / SSMS 2012 w / SP2. Si vous utilisez SQL 2008 / R2, vous pourrez peut- être modifier le script pour le faire fonctionner. Mais cette version n'a pas d'interface graphique, vous devez donc extraire le XML showplan, l'enregistrer en tant que fichier * .sqlplan et l'ouvrir dans SSMS. C'est lourd. XEvents n'existait pas dans SQL 2005 ou version antérieure. Donc, si vous n'êtes pas sur SQL 2012 ou version ultérieure, je suggère fortement l'une des autres réponses publiées ici.

Dave Mason
la source
5

À partir de SQL Server 2016+, la fonctionnalité Query Store a été introduite pour surveiller les performances. Il donne un aperçu du choix et des performances du plan de requête. Ce n'est pas un remplacement complet de la trace ou des événements étendus, mais comme il évolue d'une version à l'autre, nous pourrions obtenir un magasin de requêtes entièrement fonctionnel dans les futures versions de SQL Server. Le flux principal de Query Store

  1. Les composants existants de SQL Server interagissent avec le magasin de requêtes en utilisant Query Store Manager.
  2. Le gestionnaire de magasin de requêtes détermine le magasin à utiliser, puis passe l'exécution à ce magasin (statistiques de planification ou d'exécution ou statistiques d'attente de requête)
    • Plan Store - Persistance des informations du plan d'exécution
    • Runtime Stats Store - Persistance des informations sur les statistiques d'exécution
    • Query Wait Stats Store - Informations persistantes sur les statistiques d'attente.
  3. Plan, Runtime Stats et Wait Store utilise Query Store comme extension de SQL Server.

entrez la description de l'image ici

  1. Activation du magasin de requêtes : le magasin de requêtes fonctionne au niveau de la base de données sur le serveur.

    • Le magasin de requêtes n'est pas actif pour les nouvelles bases de données par défaut.
    • Vous ne pouvez pas activer le magasin de requêtes pour le maître ou la tempdbbase de données.
    • DMV disponible

      sys.database_query_store_options (Transact-SQL)

  2. Collecte d'informations dans le magasin de requêtes : Nous collectons toutes les informations disponibles dans les trois magasins à l'aide du magasin de requêtes DMV (vues de gestion des données).

    • Magasin de plan de requête: conserver les informations du plan d'exécution et il est responsable de la capture de toutes les informations liées à la compilation des requêtes.

      sys.query_store_query(Transact-SQL) sys.query_store_plan(Transact-SQL) sys.query_store_query_text(Transact-SQL)

    • Runtime Stats Store: Persistant les informations de statistiques d'exécution et c'est probablement le magasin le plus fréquemment mis à jour. Ces statistiques représentent les données d'exécution des requêtes.

      sys.query_store_runtime_stats (Transact-SQL)

    • Query Wait Stats Store: Persistance et capture des informations sur les statistiques d'attente.

      sys.query_store_wait_stats (Transact-SQL)

REMARQUE: Query Wait Stats Store est disponible uniquement dans SQL Server 2017+

vCillusion
la source
4

Comme avec SQL Server Management Studio (déjà expliqué), il est également possible avec Datagrip comme expliqué ici .

  1. Cliquez avec le bouton droit sur une instruction SQL et sélectionnez Expliquer le plan.
  2. Dans le volet Sortie, cliquez sur Plan.
  3. Par défaut, vous voyez l'arborescence de la requête. Pour voir le plan de requête, cliquez sur l'icône Afficher la visualisation ou appuyez sur Ctrl + Maj + Alt + U
Daan
la source
3

Voici une chose importante à savoir en plus de tout ce qui a été dit auparavant.

Les plans de requête sont souvent trop complexes pour être représentés par le type de colonne XML intégré qui a une limitation de 127 niveaux d'éléments imbriqués. C'est l'une des raisons pour lesquelles sys.dm_exec_query_plan peut retourner NULLou même renvoyer une erreur dans les versions antérieures de MS SQL, il est donc généralement plus sûr d'utiliser sys.dm_exec_text_query_plan à la place. Ce dernier a également une fonctionnalité bonus utile de sélectionner un plan pour une déclaration particulière plutôt que l'ensemble du lot. Voici comment vous l'utilisez pour afficher les plans des instructions en cours d'exécution:

SELECT p.query_plan
FROM sys.dm_exec_requests AS r
OUTER APPLY sys.dm_exec_text_query_plan(
                r.plan_handle,
                r.statement_start_offset,
                r.statement_end_offset) AS p

La colonne de texte du tableau résultant n'est cependant pas très pratique par rapport à une colonne XML. Pour pouvoir cliquer sur le résultat à ouvrir dans un onglet séparé sous forme de diagramme, sans avoir à enregistrer son contenu dans un fichier, vous pouvez utiliser une petite astuce (rappelez-vous que vous ne pouvez pas simplement utiliser CAST(... AS XML)), bien que cela ne fonctionne que pour un une seule ligne:

SELECT Tag = 1, Parent = NULL, [ShowPlanXML!1!!XMLTEXT] = query_plan
FROM sys.dm_exec_text_query_plan(
                -- set these variables or copy values
                -- from the results of the above query
                @plan_handle,
                @statement_start_offset,
                @statement_end_offset)
FOR XML EXPLICIT
alkoln
la source
3

Vous pouvez également le faire via PowerShell en utilisant SET STATISTICS XML ON pour obtenir le plan réel. Je l'ai écrit pour qu'il fusionne les plans à états multiples en un seul plan;

    ########## BEGIN : SCRIPT VARIABLES #####################
    [string]$server = '.\MySQLServer'
    [string]$database = 'MyDatabase'
    [string]$sqlCommand = 'EXEC sp_ExampleSproc'
    [string]$XMLOutputFileName = 'sp_ExampleSproc'
    [string]$XMLOutputPath = 'C:\SQLDumps\ActualPlans\'
    ########## END   : SCRIPT VARIABLES #####################

    #Set up connection
    $connectionString = "Persist Security Info=False;Integrated Security=true;Connection Timeout=0;Initial Catalog=$database;Server=$server"
    $connection = new-object system.data.SqlClient.SQLConnection($connectionString)

    #Set up commands
    $command = new-object system.data.sqlclient.sqlcommand($sqlCommand,$connection)
    $command.CommandTimeout = 0
    $commandXMLActPlanOn = new-object system.data.sqlclient.sqlcommand("SET STATISTICS XML ON",$connection)
    $commandXMLActPlanOff = new-object system.data.sqlclient.sqlcommand("SET STATISTICS XML OFF",$connection)

    $connection.Open()

    #Enable session XML plan
    $result = $commandXMLActPlanOn.ExecuteNonQuery()

    #Execute SP and return resultsets into a dataset
    $adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command
    $dataset = New-Object System.Data.DataSet
    $adapter.Fill($dataSet) | Out-Null

    #Set up output file name and path
    [string]$fileNameDateStamp = get-date -f yyyyMMdd_HHmmss
    [string]$XMLOutputFilePath = "$XMLOutputPath$XMLOutputFileName`_$fileNameDateStamp.sqlplan"

    #Pull XML plans out of dataset and merge into one multi-statement plan
    [int]$cntr = 1
    ForEach($table in $dataset.Tables)
    {
            if($table.Columns[0].ColumnName -eq "Microsoft SQL Server 2005 XML Showplan")
            {

                [string]$fullXMLPlan = $Table.rows[0]."Microsoft SQL Server 2005 XML Showplan"

                if($cntr -eq 1)
                    {

                    [regex]$rx = "\<ShowPlanXML xmlns\=.{1,}\<Statements\>"
                    [string]$startXMLPlan = $rx.Match($fullXMLPlan).Value
                    [regex]$rx = "\<\/Statements\>.{1,}\<\/ShowPlanXML\>"
                    [string]$endXMLPlan = $rx.Match($fullXMLPlan).Value

                    $startXMLPlan | out-file -Append -FilePath $XMLOutputFilePath

                    }

                [regex]$rx = "\<StmtSimple.{1,}\<\/StmtSimple\>"
                [string]$bodyXMLPlan = $rx.Match($fullXMLPlan).Value

                $bodyXMLPlan | out-file -Append -FilePath $XMLOutputFilePath

                $cntr += 1
            } 
    }

    $endXMLPlan | out-file -Append -FilePath $XMLOutputFilePath

    #Disable session XML plan
    $result = $commandXMLActPlanOff.ExecuteNonQuery()

    $connection.Close()
Guy Bishop
la source
2

Comme je l'ai expliqué dans cet article , il existe deux types de plan d'exécution que vous pouvez obtenir lorsque vous utilisez SQL Server.

Plan d'exécution estimé

Le plan d'exécution estimé est généré par l'Optimiseur sans exécuter la requête SQL.

Afin d'obtenir le plan d'exécution estimé, vous devez activer le SHOWPLAN_ALLparamètre avant d'exécuter la requête.

METTRE SHOWPLAN_ALL SUR

Maintenant, lors de l'exécution de la requête SQL suivante:

SELECT p.id
FROM post p
WHERE EXISTS (
  SELECT 1
  FROM post_comment pc
  WHERE
    pc.post_id = p.id AND
    pc.review = 'Bingo'
)
ORDER BY p.title
OFFSET 20 ROWS
FETCH NEXT 10 ROWS ONLY

SQL Server générera le plan d'exécution estimé suivant:

| NodeId | Parent | LogicalOp            | EstimateRows | EstimateIO  | EstimateCPU | AvgRowSize | TotalSubtreeCost | EstimateExecutions |
|--------|--------|----------------------|--------------|-------------|-------------|------------|------------------|--------------------|
| 1      | 0      | NULL                 | 10           | NULL        | NULL        | NULL       | 0.03374284       | NULL               |
| 2      | 1      | Top                  | 10           | 0           | 3.00E-06    | 15         | 0.03374284       | 1                  |
| 4      | 2      | Distinct Sort        | 30           | 0.01126126  | 0.000504114 | 146        | 0.03373984       | 1                  |
| 5      | 4      | Inner Join           | 46.698       | 0           | 0.00017974  | 146        | 0.02197446       | 1                  |
| 6      | 5      | Clustered Index Scan | 43           | 0.004606482 | 0.0007543   | 31         | 0.005360782      | 1                  |
| 7      | 5      | Clustered Index Seek | 1            | 0.003125    | 0.0001581   | 146        | 0.0161733        | 43                 |

Après avoir exécuté la requête, nous souhaitons obtenir le plan d'exécution estimé, vous devez désactiver le SHOWPLAN_ALLcar, sinon, la session de base de données actuelle ne générera que le plan d'exécution estimé au lieu d'exécuter les requêtes SQL fournies.

SET SHOWPLAN_ALL OFF

Plan estimé de SQL Server Management Studio

Dans l'application SQL Server Management Studio, vous pouvez facilement obtenir le plan d'exécution estimé pour n'importe quelle requête SQL en appuyant sur le CTRL+Lraccourci clavier.

entrez la description de l'image ici

Plan d'exécution réel

Le plan d'exécution SQL réel est généré par l'Optimiseur lors de l'exécution de la requête SQL. Si les statistiques du tableau de la base de données sont exactes, le plan réel ne doit pas différer de manière significative de celui estimé.

Pour obtenir le plan d'exécution réel sur SQL Server, vous devez activer les STATISTICS IO, TIME, PROFILEparamètres, comme illustré par la commande SQL suivante:

SET STATISTICS IO, TIME, PROFILE ON

Désormais, lors de l'exécution de la requête précédente, SQL Server va générer le plan d'exécution suivant:

| Rows | Executes | NodeId | Parent | LogicalOp            | EstimateRows | EstimateIO  | EstimateCPU | AvgRowSize | TotalSubtreeCost |
|------|----------|--------|--------|----------------------|--------------|-------------|-------------|------------|------------------|
| 10   | 1        | 1      | 0      | NULL                 | 10           | NULL        | NULL        | NULL       | 0.03338978       |
| 10   | 1        | 2      | 1      | Top                  | 1.00E+01     | 0           | 3.00E-06    | 15         | 0.03338978       |
| 30   | 1        | 4      | 2      | Distinct Sort        | 30           | 0.01126126  | 0.000478783 | 146        | 0.03338679       |
| 41   | 1        | 5      | 4      | Inner Join           | 44.362       | 0           | 0.00017138  | 146        | 0.02164674       |
| 41   | 1        | 6      | 5      | Clustered Index Scan | 41           | 0.004606482 | 0.0007521   | 31         | 0.005358581      |
| 41   | 41       | 7      | 5      | Clustered Index Seek | 1            | 0.003125    | 0.0001581   | 146        | 0.0158571        |

SQL Server parse and compile time:
   CPU time = 8 ms, elapsed time = 8 ms.

(10 row(s) affected)
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'post'. Scan count 0, logical reads 116, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'post_comment'. Scan count 1, logical reads 5, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(6 row(s) affected)

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 1 ms.

Après avoir exécuté la requête, nous souhaitons obtenir le plan d'exécution réel, vous devez désactiver les STATISTICS IO, TIME, PROFILE ONparamètres comme celui-ci:

SET STATISTICS IO, TIME, PROFILE OFF

Plan réel de SQL Server Management Studio

Dans l'application SQL Server Management Studio, vous pouvez facilement obtenir le plan d'exécution estimé pour n'importe quelle requête SQL en appuyant sur le CTRL+Mraccourci clavier.

entrez la description de l'image ici

Pour plus de détails sur l'obtention d'un plan d'exécution lors de l'utilisation de SQL Server, consultez cet article .

Vlad Mihalcea
la source
0

Expliquer le plan d'exécution peut être très détaillé et prend beaucoup de temps à lire, mais en résumé, si vous utilisez `` expliquer '' avant la requête, cela devrait vous donner beaucoup d'informations, y compris les parties qui ont été exécutées en premier et ainsi de suite. si vous voulez lire un peu plus de détails à ce sujet, j'ai compilé un petit blog à ce sujet qui vous indique également les bonnes références. https://medium.com/swlh/jetbrains-datagrip-explain-plan-ac406772c470

Abd Rmdn
la source