<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Le Blog SQL Server d&#039;ElSüket &#187; SQL Server 2014</title>
	<atom:link href="https://blog.developpez.com/elsuket/pcategory/sql-server-2014/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.developpez.com/elsuket</link>
	<description>Nicolas Souquet - Expert SQL Server</description>
	<lastBuildDate>Mon, 05 Apr 2021 07:32:41 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.42</generator>
	<item>
		<title>Variables de type table, statistiques et drapeau de trace 2453</title>
		<link>https://blog.developpez.com/elsuket/p13151/moteur-de-base-de-donnees-sql-server/variables-de-type-table-statistiques-et-drapeau-de-trace-2453</link>
		<comments>https://blog.developpez.com/elsuket/p13151/moteur-de-base-de-donnees-sql-server/variables-de-type-table-statistiques-et-drapeau-de-trace-2453#comments</comments>
		<pubDate>Sun, 30 Jul 2017 21:39:01 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Moteur de base de données SQL Server]]></category>
		<category><![CDATA[SQL Server 2012]]></category>
		<category><![CDATA[SQL Server 2014]]></category>
		<category><![CDATA[SQL Server 2016]]></category>
		<category><![CDATA[drapeau de trace]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[trace flag]]></category>
		<category><![CDATA[variable de type table]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/elsuket/?p=1409</guid>
		<description><![CDATA[M&#8217;étant arrêté d&#8217;écrire pendant un certain temps, mais certainement pas de lire, me voilà de retour au clavier pour partager sur mon sujet préféré : l&#8217;optimiseur de requêtes, et plus particulièrement l&#8217;estimation de cardinalités. En butinant des billets de blog &#8230; <a href="https://blog.developpez.com/elsuket/p13151/moteur-de-base-de-donnees-sql-server/variables-de-type-table-statistiques-et-drapeau-de-trace-2453">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>M&rsquo;étant arrêté d&rsquo;écrire pendant un certain temps, mais certainement pas de lire, me voilà de retour au clavier pour partager sur mon sujet préféré : l&rsquo;optimiseur de requêtes, et plus particulièrement l&rsquo;estimation de cardinalités. En butinant des billets de blog ici et là à propos de SQL Server, je trouvais un billet détaillant le comportement des requêtes spécifiant des variables de type TABLE.</p>
<p>Qu&rsquo;est-ce que l&rsquo;estimation de cardinalités ? Pour faire très court, c&rsquo;est l&rsquo;ensemble des règles mathématiques qui permettent à SQL Server d&rsquo;avoir une idée assez précise du nombre de lignes qu&rsquo;il aura à traiter lors de l&rsquo;exécution d&rsquo;une requête. C&rsquo;est avec ce calcul-là qu&rsquo;il sélectionne les algorithmes de jointure, de regroupement, l&rsquo;ordre et la façon d&rsquo;accéder aux tables, et bien d&rsquo;autres choses encore. Bien sûr, ces choix varient suivant le volume de données à traiter. On le comprend donc, c&rsquo;est un sujet très important, puisqu&rsquo;il impacte directement les performances de l&rsquo;exécution de nos chères (parfois en IO et temps CPU !) requêtes.</p>
<p>Alors vous allez me dire, crevant d&rsquo;impatience : &laquo;&nbsp;bon d&rsquo;accord, mais il le sort de son chapeau magique ce calcul ?&nbsp;&raquo; : au risque de vous décevoir, non. Dès lors qu&rsquo;on soumet une requête qui filtre une table par une colonne, ou l&rsquo;utilise dans une jointure, un regroupement, alors par défaut, le moteur crée automatiquement des objets de statistique. C&rsquo;est à dire qu&rsquo;il va échantillonner les données des colonnes des tables participant à la requête pour évaluer la distribution des données dans les colonnes (et index) de ces tables. Fort de ces informations, il peut alors réaliser le fameux calcul. Bref, ce sont des mathématiques <img src="https://blog.developpez.com/elsuket/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley" /></p>
<p>L&rsquo;auteur du billet en question partageait sur le fait que par défaut, SQL Server estime qu&rsquo;il n&rsquo;y a qu&rsquo;une seule ligne dans une variable de type TABLE. Ceci s&rsquo;explique par le fait que SQL Server ne maintient pas d&rsquo;objet de statistique sur les variables de type TABLE (pour les curieux, il le fait néanmoins sur les <a href="http://blog.developpez.com/elsuket/p7739/moteur-de-base-de-donnees-sql-server/variable_table_temporaire_performance" title="Utilisation des variables de type table ou des tables temporaires, et performances">tables temporaires</a>). Quand on sait l&rsquo;usage qui est fait des variables de type TABLE dans les applications, il est évident qu&rsquo;il arrive rarement que ces tables ne soient en charge que d&rsquo;une seule ligne; de là des performances qui ne sont pas toujours en adéquation avec le volume de données à traiter.</p>
<p>Voyons le comportement par défaut du moteur à l&rsquo;aide de la base de données AdventureWorks2012 :<br />
<span id="more-1409"></span></p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">SET</span> <span style="color: #0000FF;">NOCOUNT</span> <span style="color: #0000FF;">ON</span><br />
GO<br />
<br />
<span style="color: #0000FF;">USE</span> AdventureWorks2012<br />
GO<br />
<br />
<span style="color: #0000FF;">DECLARE</span> @BusinessEntityId <span style="color: #0000FF;">TABLE</span><br />
<span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; BusinessEntityID <span style="color: #0000FF;">INT</span> <span style="color: #808080;">NOT</span> <span style="color: #808080;">NULL</span><br />
<span style="color: #808080;">&#41;</span>;<br />
&nbsp;<br />
<span style="color: #0000FF;">INSERT</span> <span style="color: #0000FF;">INTO</span> @BusinessEntityId<br />
<span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; BusinessEntityID<br />
<span style="color: #808080;">&#41;</span><br />
<span style="color: #0000FF;">SELECT</span>&nbsp; BusinessEntityID<br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; Person.<span style="color: #202020;">Person</span>;<br />
&nbsp;<br />
<span style="color: #0000FF;">SET</span> <span style="color: #0000FF;">STATISTICS</span> IO, <span style="color: #0000FF;">TIME</span>, XML <span style="color: #0000FF;">ON</span><br />
&nbsp;<br />
<span style="color: #0000FF;">SELECT</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #FF00FF;">COUNT</span><span style="color: #808080;">&#40;</span><span style="color: #808080;">*</span><span style="color: #808080;">&#41;</span><br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @BusinessEntityId b<br />
<span style="color: #0000FF;">INNER</span> <span style="color: #808080;">JOIN</span>&nbsp; &nbsp; &nbsp; Person.<span style="color: #202020;">Person</span> p<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">ON</span> b.<span style="color: #202020;">BusinessEntityID</span> <span style="color: #808080;">=</span> p.<span style="color: #202020;">BusinessEntityID</span>;<br />
<br />
<span style="color: #0000FF;">SET</span> <span style="color: #0000FF;">STATISTICS</span> IO, <span style="color: #0000FF;">TIME</span>, XML <span style="color: #0000FF;">OFF</span></div></td></tr></tbody></table></div>
<p>L&rsquo;option de session SET STATISTICS nous permet de collecter des métriques IO, temps CPU et durée en millisecondes de la requête. Son option XML expose le <a href="http://blog.developpez.com/elsuket/p12879/moteur-de-base-de-donnees-sql-server/capture-manuelle-de-plans-de-requete" title="Capture manuelle de plans de requête">plan réel de requête</a> en plus du résultat de la requête.  La sortie de ce lot est, tronquée des lectures &laquo;&nbsp;physiques&nbsp;&raquo; (i.e. sur disque et pas en RAM), et des lectures LOB, puisqu&rsquo;il n&rsquo;y en a pas :</p>
<p><em>Table &lsquo;Person&rsquo;. Scan count 0, logical reads 59916<br />
Table &lsquo;#BEF1AB90&prime;. Scan count 1, logical reads 33</p>
<p> SQL Server Execution Times:<br />
   CPU time = 47 ms,  elapsed time = 56 ms.</em></p>
<p>Si l&rsquo;on étudie le plan de requête, voici ce que l&rsquo;on trouve pour notre variable de type TABLE :</p>
<p><img src="http://imgur.com/IyPj2KC.png" alt="" /></p>
<p>Pour voir sur quelle base le moteur a réalisé ses calculs, il suffit de survoler l&rsquo;opérateur <em>Table Scan</em> avec le curseur de la souris :</p>
<p><img src="http://imgur.com/CPy7CtN.png" alt="" /></p>
<p>Le moteur a donc estimé qu&rsquo;il n&rsquo;y qu&rsquo;une seule ligne dans la variable de type TABLE, puis il a exécuté le plan de cette requête. D&rsquo;une certaine manière, il nous avoue s&rsquo;être un peu trompé, puisqu&rsquo;il nous indique qu&rsquo;en réalité, il a lu 19972 lignes.</p>
<p>Mais, à la lecture du résumé l&rsquo;article <a href="https://support.microsoft.com/en-us/help/2952444">2952444</a>, on voit que ce comportement a été corrigé à l&rsquo;aide d&rsquo;un correctif dès SQL Server 2012 SP2 et le CU3 de SQL Server 2014, ce qui fait qu&rsquo;il est dans les RTM des versions suivantes de SQL Server, à ce jour SQL Server 2016 et 2017 (bientôt !) :</p>
<p><em>When you populate a table variable with many rows and then join it with other tables, the query optimizer may choose an inefficient query plan, which may lead to slow query performance.<br />
</em></p>
<p>Voyons donc ce qu&rsquo;il en est : nous rejouons le même lot de requête, mais avec le drapeau de trace activé cette fois :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008080;">-- Activation du drapeau de trace 2453 pour toutes</span><br />
<span style="color: #008080;">-- les bases de données que l'instance héberge</span><br />
<span style="color: #0000FF;">DBCC</span> TRACEON <span style="color: #808080;">&#40;</span><span style="color: #000;">2453</span>, <span style="color: #808080;">-</span><span style="color: #000;">1</span><span style="color: #808080;">&#41;</span><br />
GO<br />
<br />
<span style="color: #0000FF;">SET</span> <span style="color: #0000FF;">NOCOUNT</span> <span style="color: #0000FF;">ON</span><br />
GO<br />
<br />
<span style="color: #0000FF;">USE</span> AdventureWorks2012<br />
GO<br />
<br />
<span style="color: #0000FF;">DECLARE</span> @BusinessEntityId <span style="color: #0000FF;">TABLE</span><br />
<span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; BusinessEntityID <span style="color: #0000FF;">INT</span> <span style="color: #808080;">NOT</span> <span style="color: #808080;">NULL</span><br />
<span style="color: #808080;">&#41;</span>;<br />
&nbsp;<br />
<span style="color: #0000FF;">INSERT</span> <span style="color: #0000FF;">INTO</span> @BusinessEntityId<br />
<span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; BusinessEntityID<br />
<span style="color: #808080;">&#41;</span><br />
<span style="color: #0000FF;">SELECT</span> &nbsp;BusinessEntityID<br />
<span style="color: #0000FF;">FROM</span> &nbsp; &nbsp;Person.<span style="color: #202020;">Person</span>;<br />
&nbsp;<br />
<span style="color: #0000FF;">SET</span> <span style="color: #0000FF;">STATISTICS</span> IO, <span style="color: #0000FF;">TIME</span>, XML <span style="color: #0000FF;">ON</span><br />
&nbsp;<br />
<span style="color: #0000FF;">SELECT</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #FF00FF;">COUNT</span><span style="color: #808080;">&#40;</span><span style="color: #808080;">*</span><span style="color: #808080;">&#41;</span><br />
<span style="color: #0000FF;">FROM</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@BusinessEntityId b<br />
<span style="color: #0000FF;">INNER</span> <span style="color: #808080;">JOIN</span> &nbsp; &nbsp; &nbsp;Person.<span style="color: #202020;">Person</span> p<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">ON</span> b.<span style="color: #202020;">BusinessEntityID</span> <span style="color: #808080;">=</span> p.<span style="color: #202020;">BusinessEntityID</span>;<br />
<br />
<span style="color: #0000FF;">SET</span> <span style="color: #0000FF;">STATISTICS</span> IO, <span style="color: #0000FF;">TIME</span>, XML <span style="color: #0000FF;">OFF</span></div></td></tr></tbody></table></div>
<p>La sortie est :</p>
<p><em>Table &lsquo;Workfile&rsquo;. Scan count 7, logical reads 64, physical reads 0, read-ahead reads 64<br />
Table &lsquo;Worktable&rsquo;. Scan count 0, logical reads 0<br />
Table &lsquo;Person&rsquo;. Scan count 1, logical reads 67<br />
Table &lsquo;#A96F2843&prime;. Scan count 1, logical reads 33</p>
<p> SQL Server Execution Times:<br />
   CPU time = 31 ms,  elapsed time = 39 ms.</em></p>
<p>Le gain de temps pour une requête aussi simple n&rsquo;est pas négligeable, mais c&rsquo;est surtout le gain en IOs qui est très intéressant ! Voyons ce que nous dit le plan de requête :</p>
<p><img src="http://imgur.com/suEqrcd.png" alt="" /></p>
<p>L&rsquo;ordre d&rsquo;accès aux tables est le même, mais on voit bien que la façon de les traiter a changé : les jointures et agrégats sont exécutés par hachage. On note aussi les avertissements (petit point d&rsquo;exclamation noir dans un triangle jaune) sur ces deux opérateurs : ils ont du accéder à TempDB pour exécuter la jointure et l&rsquo;agrégat, d&rsquo;où les <em>Workfile</em> et <em>Worktable</em> dans la sortie de SET STATISTICS : ce sont des structures créées à la volée dans TempDB, souvent à défaut d&rsquo;index pouvant supporter la requête efficacement.</p>
<p>Voyons ce que nous indique l&rsquo;opérateur <em>Table Scan</em> :</p>
<p><img src="http://imgur.com/JuxVHGM.png" alt="" /></p>
<p>Ici on voit bien que l&rsquo;estimation du nombre de lignes s&rsquo;est faite correctement, et c&rsquo;est donc bien cela qui a conduit le moteur à changer les algorithmes de jointure et de calcul de l&rsquo;agrégat.</p>
<p>Pour ma part, la grande majorité des instances SQL Server que j&rsquo;administre actuellement sont de version 2014, et j&rsquo;ai activé ce drapeau de trace sur toutes celles-ci. En effet, l&rsquo;application qui repose sur cette base de données fait souvent appel à des <em>Tabled-Valued Parameters</em>, qui sont des variables de type table que l&rsquo;on peut passer en paramètre à une procédure stockée ou un appel à la procédure stockée système <em>sp_executesql</em>. Les performances générales de l&rsquo;application s&rsquo;en sont immédiatement ressenti positivement.</p>
<p>Je n&rsquo;irai pas jusqu&rsquo;à écrire qu&rsquo;il faudrait que ce drapeau de trace soit activé sur toute les instances de production, car :</p>
<ol>
<li>toutes les applications et leurs charges de travail sont différentes</li>
<li>il est toujours primordial de tester et de mesurer avant d&rsquo;effectuer un quelconque changement de configuration sur une instance de production</li>
</ol>
<p>Je vous engage vivement donc à tester pour en observer l&rsquo;effet :</p>
<ul>
<li>Pour savoir quels sont les drapeaux de trace actifs, il suffit d&rsquo;exécuter DBCC TRACESTATUS seul, ou si l&rsquo;on veut être plus spécifique : DBCC TRACESTATUS (2453, -1)</li>
<li>Pour désactiver un drapeau de trace, il faut exécuter : DBCC TRACEOFF ({traceFlag}, -1), soit dans le cadre de ce billet : DBCC TRACEOFF (2453, -1)</li>
</ul>
<p>N&rsquo;hésitez pas à me laisser un petit commentaire !</p>
<p>ElSüket.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>sys.dm_exec_query_profiles : la DMV qui détaille les noeuds d&#8217;un plan d&#8217;exécution réel</title>
		<link>https://blog.developpez.com/elsuket/p13089/moteur-de-base-de-donnees-sql-server/indexation/sys-dm_exec_query_profiles-la-dmv-qui-detaille-les-noeuds-dun-plan-dexecution-reel</link>
		<comments>https://blog.developpez.com/elsuket/p13089/moteur-de-base-de-donnees-sql-server/indexation/sys-dm_exec_query_profiles-la-dmv-qui-detaille-les-noeuds-dun-plan-dexecution-reel#comments</comments>
		<pubDate>Tue, 09 Aug 2016 08:00:57 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Indexation]]></category>
		<category><![CDATA[Moteur de base de données SQL Server]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[SQL Server 2014]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/elsuket/?p=1266</guid>
		<description><![CDATA[La lecture du plan d&#8217;exécution réel peut s&#8217;avérer être une tâche laborieuse, surtout lorsque le plan contient de nombreux opérateurs ou nœuds. Introduite avec SQL Server 2014, la vue de gestion dynamique sys.dm_exec_query_profiles nous permet de voir quel(s) nœud(s) d&#8217;un &#8230; <a href="https://blog.developpez.com/elsuket/p13089/moteur-de-base-de-donnees-sql-server/indexation/sys-dm_exec_query_profiles-la-dmv-qui-detaille-les-noeuds-dun-plan-dexecution-reel">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>La lecture du plan d&rsquo;exécution réel peut s&rsquo;avérer être une tâche laborieuse, surtout lorsque le plan contient de nombreux opérateurs ou nœuds.</p>
<p>Introduite avec SQL Server 2014, la vue de gestion dynamique <em>sys.dm_exec_query_profiles</em> nous permet de voir quel(s) nœud(s) d&rsquo;un <a href="http://blog.developpez.com/elsuket/p12879/moteur-de-base-de-donnees-sql-server/capture-manuelle-de-plans-de-requete" title="Capture manuelle de plans de requête">plan d&rsquo;exécution réel</a> consomme le plus de ressources et /ou de temps. C&rsquo;est donc un formidable outil qui peut faire largement diminuer la recherche des points noueux d&rsquo;une requête à l&rsquo;étude.</p>
<p><span id="more-1266"></span></p>
<p><a href="https://msdn.microsoft.com/en-us/library/dn223301.aspx">La documentation</a> de cette DMV montre qu&rsquo;elle expose de nombreuses colonnes, qui nous renseignent de façon très précise sur la consommation de ressources physiques de chaque opérateur du plan de requête, notamment avec le nombre de millisecondes après lequel un opérateur s&rsquo;est exécuté pour la première et la dernière fois. Pour simplifier l&rsquo;analyse des requêtes, on peut s&rsquo;en tenir à quelques unes d&rsquo;entre-elles, comme dans la requête suivante :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">SELECT</span>&nbsp; physical_operator_name<br />
&nbsp; &nbsp; &nbsp; &nbsp; , node_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; , elapsed_time_ms<br />
&nbsp; &nbsp; &nbsp; &nbsp; , cpu_time_ms<br />
&nbsp; &nbsp; &nbsp; &nbsp; , row_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , estimate_row_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , logical_read_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , rewind_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , rebind_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , end_of_scan_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , scan_count<br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; sys.<span style="color: #202020;">dm_exec_query_profiles</span></div></td></tr></tbody></table></div>
<p>La colonne <em>node_id</em> nous donne le numéro de l&rsquo;opérateur dans le plan de requête. Il faut noter que l&rsquo;opérateur racine de l&rsquo;arbre de résolution qu&rsquo;est le plan de requête, et qui se situe en haut et à gauche dans le plan d&rsquo;exécution graphique, est le seul dans tout plan à ne pas porter de <em>NodeID</em>. L&rsquo;opérateur qui le précède porte le <em>NodeID</em> 0, et celui qui précède ce dernier le <em>NodeID</em> 1, et ainsi de suite. Le plus grand numéro de <em>NodeID</em> est à l&rsquo;opérateur qui est le plus à droite et en bas du plan d&rsquo;exécution graphique.</p>
<p>La colonne <em>session_id</em> va nous permettre de spécifier sur quelle session porte notre étude : pour que cette vue expose des lignes, il est nécessaire que l&rsquo;option de session SET STATISTICS XML soit positionnée à ON pour la requête à étudier. Ceci équivaut à l&rsquo;activation de l&rsquo;option d&rsquo;inclusion du plan d&rsquo;exécution réel dans la barre d&rsquo;outil de SQL Server Management Studio (SSMS) avant l&rsquo;exécution d&rsquo;une requête. Ceci est normal, puisque comme pour toutes les tâches de monitoring, elle viennent avec un coût : celui-ci pourrait devenir trop élevé si toutes les requêtes étaient auditées à ce niveau de détail, d&rsquo;autant que ce type d&rsquo;information est utilisé par les DBAs, et pas par les applications qui interagissent avec la base de données.</p>
<p>Supposons que la requête (très simple) que l&rsquo;on souhaite étudier est la suivante :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">SELECT</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">*</span><br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Sales.<span style="color: #202020;">SalesOrderDetail</span> <span style="color: #0000FF;">AS</span> SOD<br />
<span style="color: #0000FF;">INNER</span> <span style="color: #808080;">JOIN</span>&nbsp; &nbsp; &nbsp; Production.<span style="color: #202020;">Product</span> <span style="color: #0000FF;">AS</span> P<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">ON</span> SOD.<span style="color: #202020;">ProductID</span> <span style="color: #808080;">=</span> P.<span style="color: #202020;">ProductID</span><br />
<span style="color: #0000FF;">WHERE</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; P.<span style="color: #202020;">ListPrice</span> <span style="color: #808080;">&amp;</span>gt; <span style="color: #000;">1000</span></div></td></tr></tbody></table></div>
<p>On peut récupérer le session_id de plusieurs manières :</p>
<ul>
<li>Il est indiqué dans la barre d&rsquo;état de toute fenêtre de requête sous SSMS, en bas à droite;</li>
<li>Si l&rsquo;on a conservé les options par défaut de SSMS, il est aussi indiqué sur l&rsquo;onglet de la fenêtre de requête;</li>
<li>On peut exécuter SELECT @@SPID dans la même fenêtre de requête que celle à étudier.</li>
</ul>
<p><img src="http://i.imgur.com/JLFuhns.png" alt="" /></p>
<p>Ne soyez pas perturbé par l&rsquo;option de session <em>SET STATISTICS IO, TIME ON</em> positionné juste avant la requête : je l&rsquo;utilise toujours pour diagnostiquer une requête, car cela expose le temps CPU, la durée totale, et surtout, le nombre d&rsquo;IOs produit par la requête pour chaque table participant à celle-ci. On peut adjoindre l&rsquo;option <em>XML</em> à la liste <em>IO, TIME</em> si on le souhaite.</p>
<p>Les lecteurs aux yeux affûtés auront remarqué que dans la capture d&rsquo;écran ci-dessus, il y a un deuxième onglet ouvert : en effet, on doit utiliser une fenêtre de requête pour celle à étudier, et une autre pour lire la sortie de la vue <em>sys.dm_exec_query_profiles</em> pour cette session. Pour cet exemple, on peut reprendre la première requête, et rajouter la clause WHERE adéquate : la session qui va exécuter la requête à l&rsquo;étude porte le <em>session_id</em> 51 :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">SELECT</span>&nbsp; physical_operator_name<br />
&nbsp; &nbsp; &nbsp; &nbsp; , node_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; , elapsed_time_ms<br />
&nbsp; &nbsp; &nbsp; &nbsp; , cpu_time_ms<br />
&nbsp; &nbsp; &nbsp; &nbsp; , row_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , estimate_row_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , logical_read_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , rewind_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , rebind_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , end_of_scan_count<br />
&nbsp; &nbsp; &nbsp; &nbsp; , scan_count<br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; sys.<span style="color: #202020;">dm_exec_query_profiles</span><br />
<span style="color: #0000FF;">WHERE</span> &nbsp; session_id <span style="color: #808080;">=</span> <span style="color: #000;">51</span> <span style="color: #008080;">-- session_id de la requête à l'étude</span></div></td></tr></tbody></table></div>
<p>L&rsquo;exercice consiste donc à démarrer l&rsquo;exécution de la requête à l&rsquo;étude, puis à basculer vers la fenêtre de requête qui spécifie la vue <em>sys.dm_exec_query_profiles</em> avant la fin de l&rsquo;exécution de la requête à l&rsquo;étude. Pour la requête de cet exemple, cela nous donne :</p>
<p><img src="http://i.imgur.com/FJozDlw.png" alt="" /></p>
<p>On constate ainsi des écarts importants entre le nombre de lignes estimé et réel pour les opérateurs dont le <em>NodeID</em> est 0 et 4, mais il y a un problème : alors que la somme des valeurs de la colonne <em>elapsed_time_ms</em> nous donne 15, la sortie dans l&rsquo;onglet <em>Messages</em> est la suivante (légèrement écourtée, notamment les IOs physiques et de LOBs, pour les besoins de l&rsquo;article) :</p>
<blockquote><p>(29382 row(s) affected)<br />
Table &lsquo;Workfile&rsquo;. Scan count 0, logical reads 0<br />
Table &lsquo;Worktable&rsquo;. Scan count 0, logical reads 0<br />
Table &lsquo;SalesOrderDetail&rsquo;. Scan count 1, logical reads 1246<br />
Table &lsquo;Product&rsquo;. Scan count 1, logical reads 15</p>
<p> SQL Server Execution Times:<br />
   CPU time = 156 ms,  elapsed time = <strong>1225</strong> ms.</p></blockquote>
<p>Il y a bien sûr le temps de consommation du jeu de lignes de résultat par SSMS. On peut le confirmer en éliminant le résultat une fois la requête exécutée : pour ce faire, il suffit de faire un clic-droit dans un zone vierge de la requête &gt; <em>Query options</em> &#8230; &gt; <em>Results</em> / <em>Grid</em> &gt; et de cocher la case <em>Discard results after execution</em>.</p>
<p>La question qui vient maintenant est : comment faire pour les requêtes dont l&rsquo;exécution est bien plus longue ? Et dans tous les cas, la durée d&rsquo;exécution des requêtes n&rsquo;étant pas précisément prédictible même après une ou deux exécutions, comment capturer les valeurs qu&rsquo;expose cette DMV en s&rsquo;approchant le plus possible de la fin de la requête ? On peut pour cela écrire une boucle qui va stocker le contenu de la DMV à intervalles réguliers et fréquents, et qui vérifie à chaque tour que la requête est toujours en cours d&rsquo;exécution :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br />73<br />74<br />75<br />76<br />77<br />78<br />79<br />80<br />81<br />82<br />83<br />84<br />85<br />86<br />87<br />88<br />89<br />90<br />91<br />92<br />93<br />94<br />95<br />96<br />97<br />98<br />99<br />100<br />101<br />102<br />103<br />104<br />105<br />106<br />107<br />108<br />109<br />110<br />111<br />112<br />113<br />114<br />115<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">SET</span> <span style="color: #0000FF;">NOCOUNT</span> <span style="color: #0000FF;">ON</span><br />
GO<br />
<br />
<span style="color: #0000FF;">DECLARE</span> @session_id <span style="color: #0000FF;">int</span> <span style="color: #808080;">=</span> <span style="color: #000;">51</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , @delay <span style="color: #0000FF;">varchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">8</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">=</span> <span style="color: #FF0000;">'00:00:00.010'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , @i <span style="color: #0000FF;">int</span> <span style="color: #808080;">=</span> <span style="color: #000;">1</span><br />
<br />
<span style="color: #0000FF;">IF</span> <span style="color: #FF00FF;">OBJECT_ID</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'TempDB.dbo.#query_profile_global'</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">IS</span> <span style="color: #808080;">NOT</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">DROP</span> <span style="color: #0000FF;">TABLE</span> #query_profile_global<br />
<br />
<span style="color: #0000FF;">CREATE</span> <span style="color: #0000FF;">TABLE</span> #query_profile_global<br />
<span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; physical_operator_name <span style="color: #0000FF;">nvarchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">256</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , node_id <span style="color: #0000FF;">int</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , elapsed_time_ms <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , cpu_time_ms <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , row_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , estimate_row_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , logical_read_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , rewind_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , rebind_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , end_of_scan_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #FF00FF;">object_name</span> sysname <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , index_name sysname <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , scan_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , time_stamp <span style="color: #0000FF;">datetime</span> <span style="color: #808080;">NULL</span><br />
<span style="color: #808080;">&#41;</span><br />
<br />
<span style="color: #0000FF;">DECLARE</span> @query_profile <span style="color: #0000FF;">TABLE</span><br />
<span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; physical_operator_name <span style="color: #0000FF;">nvarchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">256</span><span style="color: #808080;">&#41;</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , node_id <span style="color: #0000FF;">int</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , elapsed_time_ms <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , cpu_time_ms <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , row_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , estimate_row_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , logical_read_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , rewind_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , rebind_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , end_of_scan_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #FF00FF;">object_name</span> sysname <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , index_name sysname <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , scan_count <span style="color: #0000FF;">bigint</span> <span style="color: #808080;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , time_stamp <span style="color: #0000FF;">datetime</span> <span style="color: #808080;">NULL</span><br />
<span style="color: #808080;">&#41;</span><br />
<br />
<span style="color: #0000FF;">WHILE</span> <span style="color: #808080;">EXISTS</span><br />
<span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SELECT</span>&nbsp; <span style="color: #808080;">*</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; sys.<span style="color: #202020;">dm_exec_requests</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WHERE</span> &nbsp; session_id <span style="color: #808080;">=</span> @session_id<br />
<span style="color: #808080;">&#41;</span><br />
<span style="color: #0000FF;">BEGIN</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">INSERT</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">INTO</span> @query_profile<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SELECT</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; QP.<span style="color: #202020;">physical_operator_name</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , QP.<span style="color: #202020;">node_id</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , QP.<span style="color: #202020;">elapsed_time_ms</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , QP.<span style="color: #202020;">cpu_time_ms</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , QP.<span style="color: #202020;">row_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , QP.<span style="color: #202020;">estimate_row_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , QP.<span style="color: #202020;">logical_read_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , QP.<span style="color: #202020;">rewind_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , QP.<span style="color: #202020;">rebind_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , QP.<span style="color: #202020;">end_of_scan_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , O.<span style="color: #202020;">name</span> <span style="color: #0000FF;">AS</span> <span style="color: #FF00FF;">object_name</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , I.<span style="color: #202020;">name</span> <span style="color: #0000FF;">AS</span> index_name<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , QP.<span style="color: #202020;">scan_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #FF00FF;">GETDATE</span><span style="color: #808080;">&#40;</span><span style="color: #808080;">&#41;</span> <span style="color: #0000FF;">AS</span> time_stamp<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sys.<span style="color: #202020;">dm_exec_query_profiles</span> <span style="color: #0000FF;">AS</span> QP<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">LEFT</span> <span style="color: #808080;">JOIN</span> &nbsp; &nbsp; &nbsp; sys.<span style="color: #202020;">objects</span> <span style="color: #0000FF;">AS</span> O<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">ON</span> QP.<span style="color: #FF00FF;">object_id</span> <span style="color: #808080;">=</span> O.<span style="color: #FF00FF;">object_id</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">LEFT</span> <span style="color: #808080;">JOIN</span> &nbsp; &nbsp; &nbsp; sys.<span style="color: #202020;">indexes</span> <span style="color: #0000FF;">AS</span> I<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">ON</span> QP.<span style="color: #202020;">index_id</span> <span style="color: #808080;">=</span> I.<span style="color: #202020;">index_id</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">AND</span> QP.<span style="color: #FF00FF;">object_id</span> <span style="color: #808080;">=</span> I.<span style="color: #FF00FF;">object_id</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WHERE</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; QP.<span style="color: #202020;">session_id</span> <span style="color: #808080;">=</span> @session_id <span style="color: #008080;">-- spid running query</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">IF</span> @i <span style="color: #808080;">=</span> <span style="color: #000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">BEGIN</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">INSERT</span>&nbsp; <span style="color: #0000FF;">INTO</span> #query_profile_global<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SELECT</span>&nbsp; <span style="color: #808080;">*</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; @query_profile<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">ELSE</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">BEGIN</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">UPDATE</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #query_profile_global<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SET</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; physical_operator_name <span style="color: #808080;">=</span> QP.<span style="color: #202020;">physical_operator_name</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , node_id <span style="color: #808080;">=</span> QP.<span style="color: #202020;">node_id</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , elapsed_time_ms <span style="color: #808080;">=</span> QP.<span style="color: #202020;">elapsed_time_ms</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , cpu_time_ms <span style="color: #808080;">=</span> QP.<span style="color: #202020;">cpu_time_ms</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , row_count <span style="color: #808080;">=</span> QP.<span style="color: #202020;">row_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , estimate_row_count <span style="color: #808080;">=</span> QP.<span style="color: #202020;">estimate_row_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , logical_read_count <span style="color: #808080;">=</span> QP.<span style="color: #202020;">logical_read_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , rewind_count <span style="color: #808080;">=</span> QP.<span style="color: #202020;">rewind_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , rebind_count <span style="color: #808080;">=</span> QP.<span style="color: #202020;">rebind_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , end_of_scan_count <span style="color: #808080;">=</span> QP.<span style="color: #202020;">end_of_scan_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #FF00FF;">object_name</span> <span style="color: #808080;">=</span> QP.<span style="color: #FF00FF;">object_name</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , index_name <span style="color: #808080;">=</span> QP.<span style="color: #202020;">index_name</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , scan_count <span style="color: #808080;">=</span> QP.<span style="color: #202020;">scan_count</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , time_stamp <span style="color: #808080;">=</span> QP.<span style="color: #202020;">time_stamp</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @query_profile <span style="color: #0000FF;">AS</span> QP<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">INNER</span> <span style="color: #808080;">JOIN</span>&nbsp; &nbsp; &nbsp; #query_profile_global <span style="color: #0000FF;">AS</span> QFG<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">ON</span> QFG.<span style="color: #202020;">node_id</span> <span style="color: #808080;">=</span> QP.<span style="color: #202020;">node_id</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">END</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">WAITFOR</span> DELAY @delay<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">DELETE</span> <span style="color: #0000FF;">FROM</span> @query_profile<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SET</span> @i <span style="color: #808080;">+=</span> <span style="color: #000;">1</span><br />
<span style="color: #0000FF;">END</span><br />
<br />
<span style="color: #0000FF;">SELECT</span>&nbsp; <span style="color: #0000FF;">DISTINCT</span> <span style="color: #808080;">*</span><br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; #query_profile_global<br />
<span style="color: #0000FF;">ORDER</span> &nbsp; <span style="color: #0000FF;">BY</span> node_id<br />
<span style="color: #008080;">--ORDER BY elapsed_time_ms DESC</span></div></td></tr></tbody></table></div>
<p>Ici on stocke le contenu de la DMV toutes les 10 ms. Le délai entre chaque boucle peut être adapté : si l&rsquo;on sait que la requête dure environ quart d&rsquo;heure, une récupération du contenu de la vue toutes les secondes est suffisante. Cette valeur peut donc être adaptée suivant la durée d&rsquo;exécution globale de la requête. Il faut aussi veiller à exécuter ce lot de requêtes dans le même contexte de base de données que celui sous lequel on exécute la requête à étudier. En effet, cela permet d&rsquo;obtenir le nom de l&rsquo;objet de base de données accédé :</p>
<p><img src="http://i.imgur.com/vdDfdkK.png" /></p>
<p>On constate dans la sortie du lot de requêtes interrogeant la DMV que, par exemple, l&rsquo;opérateur de <em>NodeID</em> 4 est l&rsquo;accès à l&rsquo;index cluster de la table <em>SalesOrderDetail</em>, et qu&rsquo;il a traité 121317 lignes. Voyons si cela est reflété par le plan d&rsquo;exécution réel graphique de la requête :</p>
<p><img src="http://i.imgur.com/Z6l9xMA.png" alt="" /></p>
<p>Le numéro de <em>NodeID</em> 4 est bien l&rsquo;opérateur exposé par la DMV, et si l&rsquo;on lit la ligne de la bulle dont le libellé est <em>Actual number of rows</em>, on a bien 121317.</p>
<p>Pour l&rsquo;étude des requêtes plus lourdes, la DMV <em>sys.dm_exec_query_profiles</em> nous permettra de repérer immédiatement les opérateurs les plus consommateurs de ressources, et donc de travailler directement sur ceux-ci en se reportant au plan de requête, puis à la requête elle-même pour en revoir l&rsquo;écriture et éventuellement l&rsquo;indexation.</p>
<p>Bonne optimisation !</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Le ebook gratuit Introducing SQL Server 2014</title>
		<link>https://blog.developpez.com/elsuket/p12563/sql-server-2014/le-ebook-gratuit-introducing-sql-server-2014</link>
		<comments>https://blog.developpez.com/elsuket/p12563/sql-server-2014/le-ebook-gratuit-introducing-sql-server-2014#comments</comments>
		<pubDate>Sun, 06 Apr 2014 12:29:34 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[SQL Server 2014]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/elsuket/?p=973</guid>
		<description><![CDATA[C&#8217;est par ici ! Bonne lecture !]]></description>
				<content:encoded><![CDATA[<p>C&rsquo;est par <a href="http://aka.ms/684751pdf">ici</a> !</p>
<p>Bonne lecture !</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
