<?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; drapeau de trace</title>
	<atom:link href="https://blog.developpez.com/elsuket/ptag/drapeau-de-trace/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>Quelles statistiques l&#8217;Optimiseur a-t-il utilisées pour calculer le plan de requête ?</title>
		<link>https://blog.developpez.com/elsuket/p12023/moteur-de-base-de-donnees-sql-server/quelles-statistiques-loptimiseur-a-t-il-utilisees-pour-calculer-le-plan-de-requete</link>
		<comments>https://blog.developpez.com/elsuket/p12023/moteur-de-base-de-donnees-sql-server/quelles-statistiques-loptimiseur-a-t-il-utilisees-pour-calculer-le-plan-de-requete#comments</comments>
		<pubDate>Thu, 06 Jun 2013 16:19:44 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Moteur de base de données SQL Server]]></category>
		<category><![CDATA[Non documenté]]></category>
		<category><![CDATA[SQL Server 2012]]></category>
		<category><![CDATA[8666]]></category>
		<category><![CDATA[drapeau de trace]]></category>
		<category><![CDATA[plan d'exécution]]></category>
		<category><![CDATA[statistiques]]></category>
		<category><![CDATA[trace flag]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/elsuket/?p=559</guid>
		<description><![CDATA[Si une bonne partie de votre temps de travail est consacrée à l&#8217;optimisation de requête et à la compréhension du fonctionnement de l&#8217;Optimiseur de Requêtes, vous vous êtes probablement demandé sur quelles statistiques celui-ci se base pour calculer le plan &#8230; <a href="https://blog.developpez.com/elsuket/p12023/moteur-de-base-de-donnees-sql-server/quelles-statistiques-loptimiseur-a-t-il-utilisees-pour-calculer-le-plan-de-requete">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Si une bonne partie de votre temps de travail est consacrée à l&rsquo;optimisation de requête et à la compréhension du fonctionnement de l&rsquo;Optimiseur de Requêtes, vous vous êtes probablement demandé sur quelles statistiques celui-ci se base pour calculer le plan d&rsquo;une requête.</p>
<p>Il existe un drapeau de trace <strong>non-documenté</strong>, n° 8666, qui permet d&rsquo;ajouter au document XML qui décrit le plan de requête les statistiques utilisées par l&rsquo;optimiseur pour générer le plan de requêtes.</p>
<p>Voyons comment l&rsquo;utiliser avec une requête sur la base de données <a href="http://blog.developpez.com/elsuket/p11188/moteur-de-base-de-donnees-sql-server/attacher_base_donnees_sans_tran_log">AdventureWorks2012</a> :</p>
<p><span id="more-559"></span></p>
<p>Avant toute chose, notez que ce drapeau de trace n&rsquo;est pas documenté. Comme toute fonctionnalité non-documentée, on ne doit <strong>JAMAIS</strong> utiliser celui-ci sur une base de données ou une instance qui sert une charge de production. <strong>Si tel devait être le cas, je ne peux en aucun cas être tenu pour responsable des conséquences. Vous devez limiter strictement l’usage de cette instruction aux environnements de test.</strong></p>
<p>Utilisons 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 />13<br />14<br />15<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;">DBCC</span> TRACEON <span style="color: #808080;">&#40;</span><span style="color: #000;">8666</span><span style="color: #808080;">&#41;</span><br />
GO<br />
<br />
<span style="color: #0000FF;">USE</span> AdventureWorks2012<br />
GO<br />
<br />
<span style="color: #0000FF;">SELECT</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SOH.<span style="color: #202020;">OrderDate</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , SOH.<span style="color: #202020;">DueDate</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , SOH.<span style="color: #202020;">ShipDate</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , SOH.<span style="color: #202020;">AccountNumber</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , SOD.<span style="color: #202020;">OrderQty</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , SOD.<span style="color: #202020;">UnitPrice</span><br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Sales.<span style="color: #202020;">SalesOrderHeader</span> <span style="color: #0000FF;">AS</span> SOH<br />
<span style="color: #0000FF;">INNER</span> <span style="color: #808080;">JOIN</span>&nbsp; &nbsp; &nbsp; Sales.<span style="color: #202020;">SalesOrderDetail</span> <span style="color: #0000FF;">AS</span> SOD<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">ON</span> SOH.<span style="color: #202020;">SalesOrderID</span> <span style="color: #808080;">=</span> SOD.<span style="color: #202020;">SalesOrderID</span></div></td></tr></tbody></table></div>
<p>Demandons maintenant à SQL Server de générer le plan de requête estimé. Celui-ci s&rsquo;obtient soit en pressant CTRL + L, soit par un clic sur l&rsquo;icône suivante, présente dans la barre d&rsquo;outils : </p>
<p><img src="http://img199.imageshack.us/img199/605/estimatedexecutionplan.png" alt="" /></p>
<p>On obtiendra aussi les informations ajoutées par le drapeau de trace 8666 avec le plan d&rsquo;exécution réel, que l&rsquo;on obtient soit en pressant CTRL + M, soit par un clic sur l&rsquo;icône, suivante présente elle aussi dans la barre d&rsquo;outils : </p>
<p><img src="http://img41.imageshack.us/img41/2989/actualexecutionplan.png" alt="" /></p>
<p>Nous devons maintenant explorer le document XML à l&rsquo;origine du plan d&rsquo;exécution graphique, ce qui se fait par un simple clic droit dans une zone vierge de ce dernier :</p>
<p><img src="http://img546.imageshack.us/img546/1588/tf866601.png" alt="" /></p>
<p>Il nous suffit maintenant de chercher la chaîne de caractères <em>wszStatName</em>, et nous obtenons :</p>
<p><img src="http://img9.imageshack.us/img9/3892/tf866602.png" alt="" /></p>
<p>On voit clairement les détails de ce que SQL Server utilise comme métriques pour calculer le plan, notamment :</p>
<p>&#8211; le nom de la statistique (ici c&rsquo;est la statistiques sous-jacente à l&rsquo;index qui supporte la clé primaire)<br />
&#8211; le nom de la colonne la plus à gauche dans cette statistique (wszColName)<br />
&#8211; le nombre de lignes échantillonnées lors de la génération de la statique (m_ullSnapShotModCtr)<br />
&#8211; le nombre de lignes présentes dans la table (m_ullRowCount)<br />
&#8211; le seuil de recalcul automatique de la statistique (ullThreshold)</p>
<p>Pour cette dernière valeur, on peut d&rsquo;ailleurs faire le calcul suivant :</p>
<blockquote><p>100.0 * 24,763 / 121,317 = 20.41181367821492</p></blockquote>
<p>Soit environ 20%. Prenons la partie décimale de ce pourcentage : </p>
<blockquote><p>(0.41181367821492 / 100.0) * 121,317 = 499.5999999999945</p></blockquote>
<p>Soit environ 500 lignes. Ceci vérifie bien la règle du seuil de recalcul automatique des statistiques pour les tables de plus de 8MB : 500 lignes + 20% du nombre de lignes de la table.</p>
<p>Bons calculs de plans de requêtes et estimations de cardinalités !</p>
<p>ElSüket</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
