<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Blog do Ezequiel</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/blogdoezequiel/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/blogdoezequiel/feed.xml</link>
    <description>SQL Server Insights</description>
    <lastBuildDate>Fri, 29 Mar 2019 18:25:23 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>We have moved!</title>
      <link>https://docs.microsoft.com/archive/blogs/blogdoezequiel/we-have-moved</link>
      <pubDate>Fri, 29 Mar 2019 18:25:23 GMT</pubDate>
      <dc:creator><![CDATA[Pam Lahoud]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/blogdoezequiel/?p=4855</guid>
      <description><![CDATA[Thanks for visiting! This blog has now been migrated...]]></description>
      <content:encoded><![CDATA[Thanks for visiting! This blog has now been migrated to:

<a href="https://techcommunity.microsoft.com/t5/SQL-Server/bg-p/SQLServer/label-name/SQLServerTiger">https://techcommunity.microsoft.com/t5/SQL-Server/bg-p/SQLServer/label-name/SQLServerTiger</a>

&nbsp;]]></content:encoded>
    </item>
    <item>
      <title>Developer’s Choice: Hinting Query Execution model</title>
      <link>https://docs.microsoft.com/archive/blogs/blogdoezequiel/developers-choice-hinting-query-execution-model</link>
      <pubDate>Sat, 22 Sep 2018 01:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Pedro Lopes (PL)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/blogdoezequiel/?p=4845</guid>
      <description><![CDATA[This is a cross post with https://aka.ms/sqlserverteam
Over the years you have read a number of...]]></description>
      <content:encoded><![CDATA[<h4>This is a cross post with <a href="https://aka.ms/sqlserverteam">https://aka.ms/sqlserverteam</a></h4>
Over the years you have read a number of blogs advocating for or against trace flags that influence SQL Server’s query execution model. You can see a number of query execution related trace flags are documented at <a href="https://aka.ms/traceflags">https://aka.ms/traceflags</a>. However, trace flags are deemed a hacky way of influencing SQL Server’s behaviors – they’re named trace flags after all.

This is one of the reasons we introduced USE HINT query hints back in SQL Server 2016 SP1. The new class of hints is meant to provide knobs that are sometimes required, in a fully supported way, without having to remember trace flag numbers: which one is easier to understand below? Yet both queries implement the same behavior – to not use row goal during query optimization.
<pre class="csharpcode"><span class="kwrd">SELECT</span> <span class="kwrd">TOP</span> 1000 col1 
<span class="kwrd">FROM</span> tbl1
<span class="kwrd">OPTION</span> (QUERYTRACEON 4138);

<span class="kwrd">SELECT</span> <span class="kwrd">TOP</span> 1000 col1 
<span class="kwrd">FROM</span> tbl1
<span class="kwrd">OPTION</span> (<span class="kwrd">USE</span> HINT(<span class="str">'DISABLE_OPTIMIZER_ROWGOAL'</span>));</pre>
You can read more about USE HINTS <a target="_blank" href="https://blogs.msdn.microsoft.com/sql_server_team/developers-choice-use-hint-query-hints/" rel="noopener">here</a> and <a target="_blank" href="https://docs.microsoft.com/sql/t-sql/queries/hints-transact-sql-query7#use_hint" rel="noopener">here</a>, and on row goal <a target="_blank" href="https://blogs.msdn.microsoft.com/sql_server_team/more-showplan-enhancements-row-goal/" rel="noopener">here</a>.

As you probably understood by now, the existing USE HINT hints are meant to tweak the Query Optimizer for a specific intent, including the hints FORCE_<strong>LEGACY</strong>_CARDINALITY_ESTIMATION and FORCE_<strong>DEFAULT</strong>_CARDINALITY_ESTIMATION. On the latter, the “default” cardinality estimation (CE) is the CE model mapped to the <a target="_blank" href="https://docs.microsoft.com/sql/t-sql/statements/alter-database-transact-sql-compatibility-level" rel="noopener">database compatibility level</a> in use (in turn, using a newer compatibility level also implies use of query optimizer fixes under <a target="_blank" href="https://docs.microsoft.com/sql/t-sql/database-console-commands/dbcc-traceon-trace-flags-transact-sql#4199" rel="noopener">trace flag 4199</a>). Talking about the versions of the CE is a whole topic by itself, so I won’t get into much detail here, and you can read more on the versions of the CE <a target="_blank" href="https://docs.microsoft.com/sql/relational-databases/performance/cardinality-estimation-sql-server" rel="noopener">here</a>.

What is important to retain is that we have moved away from the notion of “New CE” and “Old CE”. Because in every version we have made changes and fixes to query optimization, there is no all-up “New CE” anymore. Referring to CE versions becomes clearer, and so we have CE70 (default CE for SQL Server 7.0 through SQL Server 2012), and starting with SQL Server 2014, the number that is default for each engine version: CE120 for 2014, CE130 for 2016, CE140 for 2017, and so on.

With that, let’s introduce a <strong>scenario:</strong>
<ol>
 	<li>You have upgraded your SQL Server from 2014 to SQL Server 2017, and upgraded your database compatibility level to the native 140.</li>
 	<li>You notice all your workload runs better on CE140, apart from this one specific query that has regressed.</li>
 	<li>And because you haven’t run the <a target="_blank" href="https://docs.microsoft.com/sql/database-engine/install-windows/change-the-database-compatibility-mode-and-use-the-query-store" rel="noopener">recommended upgrade process</a>, you don’t have a previously known-good plan in Query Store, and <a target="_blank" href="https://docs.microsoft.com/sql/relational-databases/automatic-tuning/automatic-tuning" rel="noopener">Automatic Tuning</a> cannot kick in and help.</li>
</ol>
In this scenario, you only have this one query that apparently does better in SQL Server 2014 than 2017. That’s all “New CE” – there’s no CE70 vs CE 120+ at issue here. Using any known trace flag, the FORCE_<strong>LEGACY</strong>_CARDINALITY_ESTIMATION hint or the FORCE_<strong>DEFAULT</strong>_CARDINALITY_ESTIMATION hint doesn’t help. Rewriting the query is an option, but in the interim, I need a quick fix. How?

In <a target="_blank" href="https://support.microsoft.com/help/4342123/cumulative-update-10-for-sql-server-2017" rel="noopener">SQL Server 2017 CU10</a>, we have introduced a few new USE HINTs: the <strong>QUERY_OPTIMIZER_COMPATIBILITY_LEVEL_<em>n</em></strong>, where <em>n</em> is a supported database compatibility level. This forces the query optimizer behavior at a query level, as if the query was compiled with database compatibility level. You can refer to <a href="https://docs.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-exec-valid-use-hints-transact-sql?view=sql-server-2017">sys.dm_exec_valid_use_hints</a> for a list of currently supported values for <em>n</em>.

So to be clear, the new hint is not forcing only a specific CE model, it’s forcing the equivalent of the specific database compatibility level’s query optimizer behavior, including any query optimizer fixes that are enabled by default in that database compatibility level.

Note: if you are running with trace flag 4199 enabled globally, then *all* query optimizer fixes are enabled, not only those default to the specified database compatibility level.

And what is the outcome for the scenario above?

See for yourself below: using the <span style="background-color: #ffff00">new hint</span>, I was able to compile that specific query as if the database compatibility level remained at SQL Server 2014 level (top plan), and you see the differences with the SQL Server 2017 plan (bottom plan).

<a href="https://msdnshared.blob.core.windows.net/media/2018/09/image83.png"><img width="882" height="296" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2018/09/image_thumb72.png" border="0" /></a>

Looking in the properties, also notice the <span style="background-color: #ffff00">differences</span> between the used CE versions (120 vs 130) and the respective QueryTimeStats.

<a href="https://msdnshared.blob.core.windows.net/media/2018/09/image84.png"><img width="531" height="569" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2018/09/image_thumb73.png" border="0" /></a>

Like any hint, it forces certain behaviors that may get addressed in subsequent updates. So Microsoft recommends you only apply hints when no other option exists, and plan to revisit hinted code with every new upgrade. By forcing behaviors, you may be precluding your workload from benefiting of enhancements introduced in newer versions.

Pedro Lopes (<a href="https://twitter.com/SQLPedro">@SQLPedro</a>) – Senior Program Manager]]></content:encoded>
    </item>
    <item>
      <title>Predicate Pushdown and why should I care?</title>
      <link>https://docs.microsoft.com/archive/blogs/blogdoezequiel/predicate-pushdown-and-why-should-i-care</link>
      <pubDate>Mon, 09 Jul 2018 12:35:00 GMT</pubDate>
      <dc:creator><![CDATA[Pedro Lopes (PL)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/blogdoezequiel/?p=4795</guid>
      <description><![CDATA[Cross post with https://aka.ms/sqlserverteam
If you follow this blog, you know that in the last...]]></description>
      <content:encoded><![CDATA[<h3>Cross post with <a href="https://aka.ms/sqlserverteam">https://aka.ms/sqlserverteam</a></h3>
If you follow this blog, you know that in the last couple years, we have been adding more information to showplan, to make it a one-stop-shop for all your query performance troubleshooting insights. You can see more about those showplan enhancements <a target="_blank" href="https://blogs.msdn.microsoft.com/sql_server_team/tag/showplan/" rel="noopener">here</a>.

Hold on, there’s a reason I’m writing about showplan: in this scenario we also enhanced showplan to provide better insights into good index usage in a plan.

First, let’s define a few terms, so we can see how to detect whether we’re making good use of our indexes, as they relate to the queries running in our SQL Server.
<ol>
 	<li>Whenever you submit a query to SQL Server, if it includes a JOIN and/or WHERE clause, that constitutes a row filtering pattern known as a <strong>predicate</strong>.</li>
 	<li>The query optimizer can use that to estimate how to best retrieve only the intended rows, <u>after</u> that predicate has been applied, this surfaces in the query plan as the <strong>Estimated Number of Rows</strong>.</li>
 	<li>When that estimated plan is executed, and you look at the actual execution plan, this surfaces as the <strong>Actual Number of Rows</strong>. Usually, a big difference between <em>Estimated</em> and <em>Actual</em> number of rows indicates a misestimation that may need to be addressed to improve performance: maybe you don’t have the right indexes in place?</li>
</ol>
These are the two properties related to rows you had on every SQL Server plan <u>up to SQL Server 2014</u>.
<h3>The good!</h3>
Keep the above concepts in mind, and let’s see what Predicate Pushdown is with an example. I’m using AdventureWorks2016, and my SalesOrderDetail table was bloated 5 times. Also created the single index below:
<pre class="csharpcode"><span class="kwrd">CREATE</span> <span class="kwrd">NONCLUSTERED</span> <span class="kwrd">INDEX</span> [IX_ModifiedDate_OrderQty] <span class="kwrd">ON</span> [Sales].[SalesOrderDetailBulk] ([ModifiedDate] <span class="kwrd">ASC</span>)
<span class="kwrd">INCLUDE</span> ([ProductID],[OrderQty]) 
GO</pre>
Now for the query to test, I’m using this:
<pre class="csharpcode"><span class="kwrd">SELECT</span> [ProductID]
<span class="kwrd">FROM</span> [Sales].[SalesOrderDetailBulk]
<span class="kwrd">WHERE</span> [ModifiedDate] <span class="kwrd">BETWEEN</span> <span class="str">'2011-01-01'</span> <span class="kwrd">AND</span> <span class="str">'2012-01-01'</span>
<span class="kwrd">AND</span> [OrderQty] = 2
GO</pre>
So just before executing the query, look at the predicates. I see these are over the ModifiedDate and OrderQty columns – my filters. Also note ModifiedDate is the key of the index I created earlier, but OrderQty is not an index key.

The query optimizer always evaluates predicates on top of a table or index scan/range operation (my FROM clause here). Some parts of the filter predicate may match an index key, and may therefore be used to run an index seek or range scan, <strong><u>pushing a predicate down to the storage engine</u></strong> (e.g. Predicate Pushdown), so it only needs to read the <u>required set of data</u>. The remaining parts of the predicate are known as "residual", and must be evaluated for each row the index seek outputs, using a filter operator.

This is what I have in the plan below: an index operation seeking on the BETWEEN predicate (notice the Seek Predicate) because it’s <a target="_blank" href="https://docs.microsoft.com/en-us/sql/relational-databases/sql-server-index-design-guide#sargable" rel="noopener">SARGable</a>. The <em>Estimated Number of Rows</em> was 329,400, which corresponds to the <em>Actual Number of Rows</em>. And then a Filter operation on top for the non-SARGable predicate (notice the Predicate), from where the final matching 80,950 rows are output. Note the <a target="_blank" href="https://blogs.msdn.microsoft.com/sql_server_team/new-showplan-enhancements/" rel="noopener">QueryTimeStats</a> for this query are 186ms CPU for 939ms elapsed time.

&nbsp;

<a href="https://msdnshared.blob.core.windows.net/media/2018/07/image42.png"><img width="520" height="527" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2018/07/image_thumb42.png" border="0" /></a>  <a href="https://msdnshared.blob.core.windows.net/media/2018/07/image43.png"><img width="350" height="465" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2018/07/image_thumb43.png" border="0" /></a>
<table width="875" border="0" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td width="100%" valign="top"><strong>Note</strong>: If you want to dig deeper into where this index seek estimation comes from, we also output to showplan which statistics were used by the query optimizer (see more <a target="_blank" href="https://blogs.msdn.microsoft.com/sql_server_team/sql-server-2017-showplan-enhancements/" rel="noopener">here</a>). Using this information and looking at the loaded statistics, the 329,400 rows correspond to the number of rows over the ModifiedDate column in a single-column loaded stat, for the histogram steps that match the BETWEEN clause.</td>
</tr>
</tbody>
</table>
&nbsp;
<h3>The better!</h3>
But I’m actually holding back SQL Server with the plan above. SQL Server could actually have implemented it’s <strong>default behavior of full predicate pushdown</strong> – meaning pushing down both the SARGable and non-SARGable predicates in one single operation.

Let’s remove all the breaks and allow SQL Server to do its thing. The same query now yields the plan below: no more Filter operator, and both predicates were pushed down to the storage engine to resolve in the Index Seek. The <a target="_blank" href="https://blogs.msdn.microsoft.com/sql_server_team/new-showplan-enhancements/" rel="noopener">QueryTimeStats</a> for this query are 104ms CPU for 897ms elapsed time. In this small example, notice the 45 percent CPU drop.

<a href="https://msdnshared.blob.core.windows.net/media/2018/07/image44.png"><img width="484" height="634" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2018/07/image_thumb44.png" border="0" /></a>

&nbsp;

Just the <em>Estimated Number of Rows</em> and the <em>Actual Number of Rows</em> properties don’t tell the full story for anyone looking to troubleshoot a query performance, where the observed I/O doesn’t really go hand-in-hand with the number of rows returned. You need more data to really reason about your underlying index design, as they relate to your queries. Which is why we added the <strong>Number of Rows Read</strong> back in SQL Server 2016, and <strong>Estimated Number of Rows to be Read</strong> in SQL Server 2016 SP1 (both also back-ported to SQL Server 2012 SP3 and 2014 SP2). This actually tells you how many rows are read in order to resolve your query, <u>before</u> any predicates are applied.

We see also that while the <em>Estimated Number of Rows</em> was 113,158, the <em>Estimated Number of Rows to be Read</em> was 329,400 (we’ve seen this before in the previous plan). Comparing these two numbers - before and after any predicates are applied - which are present even in the Estimated Execution Plan, tells us that while our index could be further optimized for this critical predicate.

<strong>Tip</strong>: These two properties are also in your cached plans, so you can explore your cache for those plans that have big differences, and maybe tune those queries and/or underlying index design.

This observation is confirmed by the runtime data: while the <em>Actual Number of Rows</em> was 80,950 (the output *after* applying all predicates), the <em>Number of Rows Read</em> was 329,400. This is a direct measure of the required I/O for my predicates. So these two new properties really allow you insights you could only guess before.
<h3>The Best!</h3>
So at this point I know SQL Server did its best with the indexes it had, but I now know what to do next for my critical predicate. Assume for a moment that while dates may change in my query, I mostly search for products with an OrderQty = 2. Then I can use this to <a target="_blank" href="https://docs.microsoft.com/en-us/sql/relational-databases/sql-server-index-design-guide#Filtered" rel="noopener">modify my index with a filter</a>, as below:
<pre class="csharpcode"><span class="kwrd">CREATE</span> <span class="kwrd">NONCLUSTERED</span> <span class="kwrd">INDEX</span> [IX_ModifiedDate_OrderQty] <span class="kwrd">ON</span> [Sales].[SalesOrderDetailBulk] ([ModifiedDate] <span class="kwrd">ASC</span>)
<span class="kwrd">INCLUDE</span> ([ProductID],[OrderQty]) 
<span style="background-color: #ffff00"><span class="kwrd">WHERE</span> [OrderQty] = 2</span>
GO</pre>
Which gives me the below plan (ignore the unmatched index warning, we actually used it). SQL Server estimated and really read *only* the required rows for the output: <em>Estimated Number of Rows</em> = <em>Estimated Number of Rows to be Read</em>, and <em>Actual Number of Rows</em> = <em>Number of Rows Read</em>.

<a href="https://msdnshared.blob.core.windows.net/media/2018/07/image45.png"><img width="466" height="529" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2018/07/image_thumb45.png" border="0" /></a>
<h3>In conclusion…</h3>
SQL Server will always try to pushdown all predicates that are covered by an index, even though when your index is not perfectly tailored for your predicates, which may be fine.

To get the I/O to be as close as possible to your required rowcount, you need to first understand if you are facing an issue due to excessive I/O (even without executing the query, by looking at estimations alone). Being able to leverage the showplan properties seen here is an invaluable tool to troubleshoot query performance, and fine tune your indexes and statistics.

Pedro Lopes (<a target="_blank" href="https://twitter.com/SQLPedro" rel="noopener">@SQLPedro</a>) – Senior Program Manager]]></content:encoded>
    </item>
    <item>
      <title>More Showplan enhancements – UDFs</title>
      <link>https://docs.microsoft.com/archive/blogs/blogdoezequiel/more-showplan-enhancements-udfs</link>
      <pubDate>Wed, 21 Feb 2018 16:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Pedro Lopes (PL)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/blogdoezequiel/?p=4695</guid>
      <description><![CDATA[Cross post with https://aka.ms/sqlserverteam
As I mentioned on yesterday’s post, with the recent...]]></description>
      <content:encoded><![CDATA[<h3>Cross post with <a href="https://aka.ms/sqlserverteam">https://aka.ms/sqlserverteam</a></h3>
As I mentioned on <a target="_blank" href="https://blogs.msdn.microsoft.com/blogdoezequiel/more-showplan-enhancements-row-goal/" rel="noopener">yesterday’s post</a>, with the recent release of <a target="_blank" href="https://support.microsoft.com/en-us/help/4052987/cumulative-update-3-for-sql-server-2017" rel="noopener">SQL Server 2017 CU3</a>, we released yet more showplan enhancements: you can see other posts related to showplan enhancements <a target="_blank" href="https://blogs.msdn.microsoft.com/blogdoezequiel/tag/showplan/" rel="noopener">here</a>.

In this article I’ll talk about the second showplan improvement we worked on, to assist in the discoverability of <strong>UDF </strong>usage impact on query execution.

<span>Although very useful as a means to create a reusable routine, when using UDFs referenced in a query, you may be facing hidden costs that can be detrimental to performance, in a cursor like execution model.</span>

The scenario is that if a query uses one or more user-defined scalar functions (such as T-SQL functions or CLR functions), a significant portion of query execution time may be spent inside those functions, depending on the function definition. And this may be not immediately obvious by looking at the query execution plan.

Recently, we added information on overall <strong>query CPU and elapsed time</strong> tracking for statistics showplan xml (both in ms), found in the root node of an actual plan (on which I blogged about <a target="_blank" href="https://blogs.msdn.microsoft.com/sql_server_team/new-showplan-enhancements/" rel="noopener">here</a>). We now added two new attributes: <strong>UdfCpuTime</strong> and <strong>UdfElapsedTime</strong>. These provide the total CPU and elapsed time (again, both in ms) that is spent inside all scalar user-defined functions, during the execution of a query. <span>Before this improvement, the internal execution of these functions was hidden from the query plan of the calling query.</span>

Below, observe how the UDF is responsible for most of the query's CPU usage and almost half of the execution time.

<a href="https://msdnshared.blob.core.windows.net/media/2018/02/image272.png"><img width="244" height="99" title="image" style="padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2018/02/image_thumb231.png" border="0" /></a>
<h3>So, what's next?</h3>
There are several option to replace UDFs, such as Inline expressions for simple functions or derived tables if possible.

For example, if you are using simple T-SQL UDFs that do not touch any tables (meaning do not access data), make sure you specify the SCHEMABINDING option during creation of the UDFs. This will make the UDFs schema-bound and ensure that the query optimizer does not generate any unnecessary spool operators for query plans involving these UDFs.

Note that for UDFs that are schema-bound, any attempt to change the underlying objects’ schema will raise an error. Using this option ensures that the UDF will not inadvertently break due to changes of an underlying object’s schema.
<h3>Anything else?</h3>
These will also be available in the upcoming SQL Server 2016 SP2.

For the metrics above I used the following example:
<pre class="csharpcode"><span class="rem">-- Create UDF</span>
<span class="kwrd">CREATE</span> <span class="kwrd">FUNCTION</span> ufn_CategorizePrice(@Price money)
<span class="kwrd">RETURNS</span> NVARCHAR(50)
<span class="kwrd">AS</span>
<span class="kwrd">BEGIN</span>
    <span class="kwrd">DECLARE</span> @PriceCategory NVARCHAR(50)

    <span class="kwrd">IF</span> @Price &lt; 100 <span class="kwrd">SELECT</span> @PriceCategory = <span class="str">'Cheap'</span>
    <span class="kwrd">IF</span> @Price <span class="kwrd">BETWEEN</span> 101 <span class="kwrd">and</span> 500 <span class="kwrd">SELECT</span> @PriceCategory =  <span class="str">'Mid Price'</span>
    <span class="kwrd">IF</span> @Price <span class="kwrd">BETWEEN</span> 501 <span class="kwrd">and</span> 1000 <span class="kwrd">SELECT</span> @PriceCategory =  <span class="str">'Expensive'</span>
    <span class="kwrd">IF</span> @Price &gt; 1001 <span class="kwrd">SELECT</span> @PriceCategory =  <span class="str">'Unaffordable'</span>
    <span class="kwrd">RETURN</span> @PriceCategory 
<span class="kwrd">END</span>
<span class="kwrd">GO</span>

<span class="rem">-- Execute</span>
<span class="kwrd">SELECT</span> dbo.ufn_CategorizePrice(UnitPrice), 
    SalesOrderID, SalesOrderDetailID, CarrierTrackingNumber, 
    OrderQty, ProductID, SpecialOfferID, UnitPrice, UnitPriceDiscount, 
    LineTotal, rowguid, ModifiedDate 
<span class="kwrd">FROM</span> Sales.SalesOrderDetail
<span class="kwrd">GO</span></pre>
Pedro Lopes (<a href="https://twitter.com/sqlpto">@sqlpto</a>) – Senior Program Manager]]></content:encoded>
    </item>
    <item>
      <title>More Showplan enhancements – Row Goal</title>
      <link>https://docs.microsoft.com/archive/blogs/blogdoezequiel/more-showplan-enhancements-row-goal</link>
      <pubDate>Tue, 20 Feb 2018 16:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Pedro Lopes (PL)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/blogdoezequiel/?p=4665</guid>
      <description><![CDATA[Cross post with https://aka.ms/sqlserverteam
As I shared before, we have been working for over a...]]></description>
      <content:encoded><![CDATA[<h3>Cross post with <a href="https://aka.ms/sqlserverteam">https://aka.ms/sqlserverteam</a></h3>
As I shared before, we have been working for over a year to make showplan the one-stop-shop for query performance analysis and troubleshooting (as much as possible).

With the recent release of <a target="_blank" href="https://support.microsoft.com/en-us/help/4052987/cumulative-update-3-for-sql-server-2017" rel="noopener">SQL Server 2017 CU3</a>, we released yet more <a target="_blank" href="https://blogs.msdn.microsoft.com/sql_server_team/tag/showplan/" rel="noopener">showplan</a> enhancements: you can see other posts related to showplan enhancements <a target="_blank" href="https://blogs.msdn.microsoft.com/sql_server_team/tag/showplan/" rel="noopener">here</a>.

In this article I’ll talk about one of these showplan improvements, to assist in the discoverability of <strong>Optimizer row goal </strong>use, and its impact in query execution. A new operator property <em><strong>EstimateRowsWithoutRowGoal</strong></em>. This will also be available in the upcoming SQL Server 2016 SP2.
<h4>So what is row goal?</h4>
When the <a target="_blank" href="https://docs.microsoft.com/en-us/sql/relational-databases/query-processing-architecture-guide" rel="noopener">Query Optimizer</a> estimates the cost of an execution plan, it usually assumes that all qualifying rows from all tables have to be processed. However, some query patterns cause the Optimizer to search for a plan that will return a smaller number of rows, with the purpose of doing it faster. So row goal is a very useful optimization strategy for certain query patterns.
<h4>How is row goal used?</h4>
This can occur if the query specifies a target number of rows (a.k.a. row goal) that may be expected at runtime. When a query uses a <strong>TOP</strong>, <strong>IN</strong> or <strong>EXISTS</strong> clause, the <strong>FAST </strong>query hint, or a <strong>SET ROWCOUNT </strong>statement, that row goal is used as part of the query optimization process. If the row goal plan is applied, the estimated number of rows in the query plan is reduced, because the Optimizer assumes that a smaller number of rows will have to be processed, in order to reach the row goal.

When row goal is very low, and a JOIN is required, then the Optimizer prefers a nested loops join, because its initial cost (the cost to produce the first row) is relatively low. But other types of JOIN may also be used if the row goal is larger:
<ul>
 	<li>A hash join is usually a good choice for joining larger inputs. Although it has a higher initial cost, because it has to build a hash table before any rows can be returned, once built, the hash join is generally cheaper.</li>
 	<li>But if the two join inputs are sorted on their join column (for example, if they were obtained by scanning sorted indexes), a merge join is the fastest join operation and can be chosen instead.</li>
</ul>
<h4>Example of row goal benefits</h4>
Let’s use the following query in Adventureworks2016, and look at the resulting query execution plan and execution metrics:
<pre class="csharpcode"><span class="kwrd">SELECT</span> <span class="kwrd">TOP</span> (100) *
<span class="kwrd">FROM</span> Sales.SalesOrderHeaderBulk <span class="kwrd">AS</span> s 
    <span class="kwrd">INNER</span> <span class="kwrd">JOIN</span> Sales.SalesOrderDetailBulk <span class="kwrd">AS</span> d <span class="kwrd">ON</span> s.SalesOrderID = d.SalesOrderID
<span class="kwrd">WHERE</span> s.TotalDue &gt; 1000
<span class="kwrd">OPTION</span> (RECOMPILE);
GO</pre>
Notice the nested loops plan driven by the low row goal (100):

<a href="https://msdnshared.blob.core.windows.net/media/2018/02/image258.png"><img width="885" height="162" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2018/02/image_thumb217.png" border="0" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2018/02/image259.png"><img width="301" height="516" title="image" align="left" style="float: left;padding-top: 0px;padding-left: 0px;margin: 0px 17px 0px 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2018/02/image_thumb218.png" border="0" /></a>

This query executed in just over 1.6s with 40ms of CPU time. Let’s keep these in mind for later.

<a href="https://msdnshared.blob.core.windows.net/media/2018/02/image260.png"><img width="244" height="65" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2018/02/image_thumb219.png" border="0" /></a>

Looking at the properties of the outer input for the nested loops, notice this scan returned 1550 rows (<em>Actual Number of Rows</em>), and only read the 1550 rows that satisfy the pushed down predicate (<em>Number of Rows Read</em>). Good!

And we see row goal optimization was used to benefit performance, because without row goal, the estimated rows would be about 6M.

We can see this information in the new operator property <em><strong>EstimateRowsWithoutRowGoal</strong></em>. In this plan, the new property can be seen in this Clustered Index Scan, and also in other operators up the tree, like the Compute Scalars.

This new property is only added to a plan operator if row goal was evaluated and used – if not, this property is absent.

&nbsp;

&nbsp;

&nbsp;

&nbsp;

&nbsp;

In fact, we can use a USE HINT to disable row goal optimization, and see how this really helped our query plan shape and execution metrics:
<pre class="csharpcode"><span class="kwrd">SELECT</span> <span class="kwrd">TOP</span> (100) *
<span class="kwrd">FROM</span> Sales.SalesOrderHeaderBulk <span class="kwrd">AS</span> s 
    <span class="kwrd">INNER</span> <span class="kwrd">JOIN</span> Sales.SalesOrderDetailBulk <span class="kwrd">AS</span> d <span class="kwrd">ON</span> s.SalesOrderID = d.SalesOrderID
<span class="kwrd">WHERE</span> s.TotalDue &gt; 1000
<span class="kwrd">OPTION</span> (RECOMPILE, <span class="kwrd">USE</span> HINT(<span class="str">'DISABLE_OPTIMIZER_ROWGOAL'</span>));
GO</pre>
&nbsp;

<a href="https://msdnshared.blob.core.windows.net/media/2018/02/image261.png"><img width="788" height="168" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2018/02/image_thumb220.png" border="0" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2018/02/image262.png"><img width="244" height="62" title="image" style="padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2018/02/image_thumb221.png" border="0" /></a>

Clearly, row goal was a benefit, as the execution time increased to just over 2.4s (60% worse). Row goal is a benefit most of the times it is used.
<h4>Example of row goal that we can improve upon</h4>
Most of the times it;’s a benefit, but not always clear. Which is why the new information can be useful. Let’s see an example using another query:
<pre class="csharpcode"><span class="kwrd">SELECT</span> <span class="kwrd">TOP</span> 250 *
<span class="kwrd">FROM</span> Production.TransactionHistory H
<span class="kwrd">INNER</span> <span class="kwrd">JOIN</span> Production.Product P <span class="kwrd">ON</span>  H.ProductID = P.ProductID
<span class="kwrd">OPTION</span> (RECOMPILE)
GO</pre>
The resulting query execution plan is using a nested loops, as expected for a low row goal. For reference, also notice the execution metrics:

<a href="https://msdnshared.blob.core.windows.net/media/2018/02/image263.png"><img width="535" height="168" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2018/02/image_thumb222.png" border="0" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2018/02/image264.png"><img width="244" height="65" title="image" style="padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2018/02/image_thumb223.png" border="0" /></a>

This singleton query executes very fast, no question. But let’s imagine you were seeing these numbers x100, and this query executed many times per minute.

I can see in the Clustered Index Scan below, how the estimated rows without row goal (<em><strong>EstimateRowsWithoutRowGoal</strong></em>) is much larger than the number of rows read (<em>Number of Rows Read</em>): 113K to 250. Row goal drove some decisions in the Optimizer that seem beneficial, and produced a nested loops plan with the specific order of outer and inner tables – <em>TransactionHistory</em> and <em>Product</em>, respectively. On the inner table <em>Product, </em>SQL Server does just a seek for the required 250 lookups, as expected.

<a href="https://msdnshared.blob.core.windows.net/media/2018/02/image265.png"><img width="285" height="511" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2018/02/image_thumb224.png" border="0" /></a> <a href="https://msdnshared.blob.core.windows.net/media/2018/02/image266.png"><img width="251" height="510" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2018/02/image_thumb225.png" border="0" /></a>

Keeping in mind the metrics above, and because we see row goal was used, I can try to disable row goal, and see if I get better performance.
<pre class="csharpcode"><span class="kwrd">SELECT</span> <span class="kwrd">TOP</span> 250 *
<span class="kwrd">FROM</span> Production.TransactionHistory H
<span class="kwrd">INNER</span> <span class="kwrd">JOIN</span> Production.Product P <span class="kwrd">ON</span>  H.ProductID = P.ProductID
<span class="kwrd">OPTION</span> (RECOMPILE, <span class="kwrd">USE</span> HINT(<span class="str">'DISABLE_OPTIMIZER_ROWGOAL'</span>))
GO</pre>
The resulting query execution plan now uses a hash join, and notice how the join inputs have changed order: <em>Product</em> is the build table, <em>TransactionHistory</em> the probe.

<a href="https://msdnshared.blob.core.windows.net/media/2018/02/image267.png"><img width="541" height="176" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2018/02/image_thumb226.png" border="0" /></a>

What about execution metrics? Better, no question.

<a href="https://msdnshared.blob.core.windows.net/media/2018/02/image268.png"><img width="244" height="63" title="image" style="padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2018/02/image_thumb227.png" border="0" /></a>

The build table <em>Product</em> only has 504 rows (see below), and once built, it’s much cheaper than a nested loop, which is what I see in this example. Even though the probe table <em>TransactionHistory</em> is much larger, now we need only probe the required 250 rows for our TOP clause.

So disabling row goal is better <u>in this case</u>, yielding a 89% improvement in execution time (165ms to 18ms).

<a href="https://msdnshared.blob.core.windows.net/media/2018/02/image269.png"><img width="287" height="500" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2018/02/image_thumb228.png" border="0" /></a><a href="https://msdnshared.blob.core.windows.net/media/2018/02/image270.png"><img width="286" height="502" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2018/02/image_thumb229.png" border="0" /></a>

Before this showplan improvement, if you were tasked with analyzing a query using a pattern that may be using row goal, you could only guess if it was present. But with the <em><strong>EstimateRowsWithoutRowGoal </strong></em>property, it becomes possible to see if row goal was in fact used, and then engage in these tuning exercises.

Pedro Lopes (<a href="https://twitter.com/sqlpto">@sqlpto</a>) – Senior Program Manager]]></content:encoded>
    </item>
    <item>
      <title>Perfect statistics histogram in just few steps</title>
      <link>https://docs.microsoft.com/archive/blogs/blogdoezequiel/perfect-statistics-histogram-in-just-few-steps</link>
      <pubDate>Thu, 23 Nov 2017 08:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Pedro Lopes (PL)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/blogdoezequiel/?p=4395</guid>
      <description><![CDATA[Cross post with https://aka.ms/sqlserverteam
A similar question about statistics came to the team...]]></description>
      <content:encoded><![CDATA[<h3>Cross post with <a href="https://aka.ms/sqlserverteam">https://aka.ms/sqlserverteam</a></h3>
A similar question about <a target="_blank" href="https://docs.microsoft.com/en-us/sql/relational-databases/statistics/statistics" rel="noopener">statistics</a> came to the team twice this week: why does <a target="_blank" href="https://docs.microsoft.com/en-us/sql/t-sql/statements/update-statistics-transact-sql" rel="noopener">updating with fullscan</a> result in fewer <a target="_blank" href="https://docs.microsoft.com/en-us/sql/relational-databases/statistics/statistics#histogram" rel="noopener">histogram steps</a> than when doing a sampled scan?

The answer is: the number of histogram steps can be fewer than the number of distinct values. For a histogram with perfect distribution (frequency* = 1), the consolidated histogram will have a minimum of three steps, because that’s how many steps are required to accurately portray the underlying data distribution.

* <strong>Frequency</strong> is calculated by multiplying the row count and density. <a target="_blank" href="https://docs.microsoft.com/en-us/sql/relational-databases/statistics/statistics#densityvector" rel="noopener"><strong>Density</strong></a> is calculated as 1/distinct value count. For more information, refer to the documentation page on <a target="_blank" href="https://docs.microsoft.com/en-us/sql/relational-databases/statistics/statistics#densityvector" rel="noopener" title="Statistics">Statistics</a>.

Let’s see a couple of examples where we can observe this: using <a target="_blank" href="https://docs.microsoft.com/en-us/sql/t-sql/statements/create-table-transact-sql-identity-property" rel="noopener">IDENTITY </a>(or any non-repeatable integer) and using GUIDs (specifically <a target="_blank" href="https://docs.microsoft.com/en-us/sql/t-sql/functions/newid-transact-sql" rel="noopener">NEWID</a>):
<ol>
 	<li>Create a new table with a UNIQUEIDENTIFIER column or IDENTITY as primary key. Both inherently unique by design.
<pre class="csharpcode"><span class="kwrd">IF</span> <span class="kwrd">NOT</span> <span class="kwrd">EXISTS</span> (<span class="kwrd">SELECT</span> [object_id] <span class="kwrd">FROM</span> sys.objects (NOLOCK) <span class="kwrd">WHERE</span> [object_id] = OBJECT_ID(N<span class="str">'[CustomersTableGuid]'</span>) <span class="kwrd">AND</span> [type] <span class="kwrd">IN</span> (N<span class="str">'U'</span>))
<span class="kwrd">CREATE</span> <span class="kwrd">TABLE</span> CustomersTableGuid
(
    ID UNIQUEIDENTIFIER <span class="kwrd">NOT</span> <span class="kwrd">NULL</span> <span class="kwrd">DEFAULT</span> NEWID() <span class="kwrd">PRIMARY</span> <span class="kwrd">KEY</span>,
    FirstName <span class="kwrd">VARCHAR</span>(50),
    LastName <span class="kwrd">VARCHAR</span>(50)
)
<span class="kwrd">GO</span>

<span class="kwrd">IF</span> <span class="kwrd">NOT</span> <span class="kwrd">EXISTS</span> (<span class="kwrd">SELECT</span> [object_id] <span class="kwrd">FROM</span> sys.objects (NOLOCK) <span class="kwrd">WHERE</span> [object_id] = OBJECT_ID(N<span class="str">'[CustomersTableIdent]'</span>) <span class="kwrd">AND</span> [type] <span class="kwrd">IN</span> (N<span class="str">'U'</span>))
<span class="kwrd">CREATE</span> <span class="kwrd">TABLE</span> CustomersTableIdent
(
    ID <span class="kwrd">int</span> <span class="kwrd">IDENTITY</span>(1,1) <span class="kwrd">NOT</span> <span class="kwrd">NULL</span> <span class="kwrd">PRIMARY</span> <span class="kwrd">KEY</span>,
    FirstName <span class="kwrd">VARCHAR</span>(50),
    LastName <span class="kwrd">VARCHAR</span>(50)
)
<span class="kwrd">GO</span></pre>
</li>
 	<li>Insert 1 million records.
<pre class="csharpcode"><span class="kwrd">SET</span> NOCOUNT <span class="kwrd">ON</span>;
<span class="kwrd">DECLARE</span> @i <span class="kwrd">INT</span> = 0
<span class="kwrd">WHILE</span> (@i &lt;= 1000000)
<span class="kwrd">BEGIN</span>
    INSERT <span class="kwrd">INTO</span> CustomersTableGuid (FirstName, LastName)
    <span class="kwrd">VALUES</span> (<span class="str">'FirstName'</span> + <span class="kwrd">CAST</span>(@i <span class="kwrd">AS</span> <span class="kwrd">VARCHAR</span>),<span class="str">'LastName'</span> + <span class="kwrd">CAST</span>(@i <span class="kwrd">AS</span> <span class="kwrd">VARCHAR</span>))

    INSERT <span class="kwrd">INTO</span> CustomersTableIdent (FirstName, LastName)
    <span class="kwrd">VALUES</span> (<span class="str">'FirstName'</span> + <span class="kwrd">CAST</span>(@i <span class="kwrd">AS</span> <span class="kwrd">VARCHAR</span>),<span class="str">'LastName'</span> + <span class="kwrd">CAST</span>(@i <span class="kwrd">AS</span> <span class="kwrd">VARCHAR</span>))
    
    <span class="kwrd">SET</span> @i +=1
<span class="kwrd">END</span>
GO</pre>
</li>
 	<li>And let's update the statistics with a FULLSCAN.
<pre class="csharpcode"><span class="kwrd">UPDATE</span> <span class="kwrd">STATISTICS</span> CustomersTableGuid <span class="kwrd">WITH</span> FULLSCAN
<span class="kwrd">GO</span>
<span class="kwrd">UPDATE</span> <span class="kwrd">STATISTICS</span> CustomersTableIdent <span class="kwrd">WITH</span> FULLSCAN
GO</pre>
</li>
 	<li>Now, let’s find stats info:
<ol>
 	<li>Verifying sampled rows and steps, we have 3 steps for each statistic, with 100% row sampling (rows = rows_sampled).
<pre class="csharpcode"><span class="kwrd">SELECT</span> OBJECT_NAME(stat.[object_id]) <span class="kwrd">AS</span> [TableName], sp.stats_id, name, 
    last_updated, <span class="kwrd">rows</span>, rows_sampled, steps, unfiltered_rows, modification_counter   
<span class="kwrd">FROM</span> sys.stats <span class="kwrd">AS</span> stat   
<span class="kwrd">CROSS</span> APPLY sys.dm_db_stats_properties(stat.[object_id], stat.stats_id) <span class="kwrd">AS</span> sp  
<span class="kwrd">WHERE</span> stat.[object_id] = OBJECT_ID(<span class="str">'CustomersTableGuid'</span>)
    <span class="kwrd">OR</span> stat.[object_id] = OBJECT_ID(<span class="str">'CustomersTableIdent'</span>);
GO</pre>
<a href="https://msdnshared.blob.core.windows.net/media/2017/11/image296.png"><img width="1026" height="72" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/11/image_thumb272.png" border="0" /></a></li>
 	<li>Looking at the histograms for ID column, we see the 3 steps for each statistic. SQL Server will compact multiple histogram steps into as few steps as possible, without losing histogram quality. As expected, the fullscan is a perfect distribution, and so it can be compacted into just 3 steps.
<pre class="csharpcode"><span class="kwrd">SELECT</span> OBJECT_NAME(stat.[object_id]) <span class="kwrd">AS</span> [TableName], stat.name, sh.stats_id, 
    sh.range_high_key, sh.range_rows, sh.equal_rows
<span class="kwrd">FROM</span> sys.stats <span class="kwrd">AS</span> stat
<span class="kwrd">INNER</span> <span class="kwrd">JOIN</span> sys.stats_columns <span class="kwrd">AS</span> sc 
    <span class="kwrd">ON</span> stat.stats_id = sc.stats_id <span class="kwrd">AND</span> stat.[object_id] = sc.[object_id]
<span class="kwrd">INNER</span> <span class="kwrd">JOIN</span> sys.all_columns <span class="kwrd">AS</span> ac 
    <span class="kwrd">ON</span> ac.column_id = sc.column_id <span class="kwrd">AND</span> ac.[object_id] = sc.[object_id]
<span class="kwrd">CROSS</span> APPLY sys.dm_db_stats_histogram(stat.[object_id], stat.stats_id) <span class="kwrd">AS</span> sh
<span class="kwrd">WHERE</span> (stat.[object_id] = OBJECT_ID(<span class="str">'CustomersTableGuid'</span>) 
    <span class="kwrd">OR</span> stat.[object_id] = OBJECT_ID(<span class="str">'CustomersTableIdent'</span>))
    <span class="kwrd">AND</span> ac.name = <span class="str">'ID'</span>;
GO</pre>
<a href="https://msdnshared.blob.core.windows.net/media/2017/11/image297.png"><img width="851" height="163" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/11/image_thumb273.png" border="0" /></a>

Let’s take the histogram steps on ID for the CustomersTableIdent table:
<ul>
 	<li>1st step with value 1;</li>
 	<li>2nd step with 999,998 rows with no repeats (the density is 1);</li>
 	<li>3rd step with the last row at 1,000,001.</li>
</ul>
</li>
</ol>
</li>
 	<li>Now let's update the statistics with a smaller sample (try whatever value you want), and look at the stats info.
SQL Server pulls pages worth of data, then extrapolates that to a full distribution. So, as expected, the sampled distribution is only approximate, and being an extrapolation, this is why we see frequencies that are close to 1, but not exactly 1.
<pre class="csharpcode"><span class="kwrd">UPDATE</span> <span class="kwrd">STATISTICS</span> CustomersTableGuid <span class="kwrd">WITH</span> SAMPLE 90 <span class="kwrd">PERCENT</span>
<span class="kwrd">GO</span>
<span class="kwrd">UPDATE</span> <span class="kwrd">STATISTICS</span> CustomersTableIdent <span class="kwrd">WITH</span> SAMPLE 90 <span class="kwrd">PERCENT</span>
GO</pre>
<a href="https://msdnshared.blob.core.windows.net/media/2017/11/image298.png"><img width="1053" height="74" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/11/image_thumb274.png" border="0" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2017/11/image299.png"><img width="848" height="240" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/11/image_thumb275.png" border="0" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2017/11/image300.png"><img width="848" height="419" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/11/image_thumb276.png" border="0" /></a></li>
</ol>
In conclusion, what we have done here was to insert 1,000,001 unique keys into the tables. The fullscan histograms with 3 steps are reflecting this perfect distribution. With sampling on the other hand, SQL Server pulls random pages worth of data, then extrapolates distribution.

More importantly, <strong>having more steps in a statistic object is not always synonym of better key value coverage</strong>, and better estimations. Find more information in the documentation page on <a target="_blank" href="https://docs.microsoft.com/en-us/sql/relational-databases/statistics/statistics" rel="noopener" title="Statistics">Statistics</a>, namely how statistics are built.

One note on GUIDs: my advice is just don’t use them as predicates, or on anything that requires good estimates for range scans. If you really, really have to use them as PK on a table to maintain uniqueness and therefore leverage singleton lookups as possible, then GUID is ok enough. But use <a target="_blank" href="https://docs.microsoft.com/en-us/sql/t-sql/functions/newsequentialid-transact-sql" rel="noopener">NEWSEQUENTIALID</a> generation instead of <a target="_blank" href="https://docs.microsoft.com/en-us/sql/t-sql/functions/newid-transact-sql" rel="noopener">NEWID</a>, create the PK as non-clustered, and get a surrogate key that can fulfill the <a target="_blank" href="https://www.sqlskills.com/blogs/kimberly/guids-as-primary-keys-andor-the-clustering-key/" rel="noopener">requirements of a good clustering key</a>.

Pedro Lopes (<a href="https://twitter.com/sqlpto">@sqlpto</a>) – Senior Program Manager]]></content:encoded>
    </item>
    <item>
      <title>Making parallelism waits actionable</title>
      <link>https://docs.microsoft.com/archive/blogs/blogdoezequiel/making-parallelism-waits-actionable</link>
      <pubDate>Mon, 13 Nov 2017 14:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Pedro Lopes (PL)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/blogdoezequiel/?p=4305</guid>
      <description><![CDATA[Cross post with https://aka.ms/sqlserverteam
During PASS we announced changes to how users will be...]]></description>
      <content:encoded><![CDATA[<h3>Cross post with <a href="https://aka.ms/sqlserverteam">https://aka.ms/sqlserverteam</a></h3>
During PASS we announced changes to how users will be able to make parallelism waits more actionable – specifically the “infamous” CXPACKET. This change effectively splits CXPACKET waits into an actionable wait (<strong>CXPACKET</strong>) and a negligible wait (<strong>CXCONSUMER</strong>). This change will be effective starting with upcoming SQL Server 2017 CU3 and SQL Server 2016 SP2 (this wait type is already present in Azure SQL Database).
<h4>So why split?</h4>
It’s important to mention a couple notes before getting into details:
<ol>
 	<li>Parallelism use is intrinsically a benefit for costly queries, bound by the <a target="_blank" href="https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/configure-the-cost-threshold-for-parallelism-server-configuration-option" rel="noopener">Cost Threshold for Parallelism</a> and <a target="_blank" href="https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/configure-the-max-degree-of-parallelism-server-configuration-option" rel="noopener">Max Degree of Parallelism</a> server configurations among other considerations. See the <a target="_blank" href="https://docs.microsoft.com/en-us/sql/relational-databases/query-processing-architecture-guide#parallel-query-processing" rel="noopener">Query Processing Guide</a> for more in-depth information on how SQL Server implements parallelism. Also refer to <a target="_blank" href="https://blogs.msdn.microsoft.com/craigfr/tag/parallelism/" rel="noopener">Craig Freedman’s blog series</a> on the topic.</li>
 	<li>Waits are a normal part of the <a target="_blank" href="https://technet.microsoft.com/en-us/library/cc966413.aspx" rel="noopener">waits and queues model</a>, allowing SQL Server to concurrently execute many more requests than there are schedulers available. See more about waits and queues <a target="_blank" href="https://technet.microsoft.com/en-us/library/cc966413.aspx" rel="noopener">here</a>,</li>
</ol>
It’s also important to understand that <a target="_blank" href="https://docs.microsoft.com/en-us/sql/relational-databases/query-processing-architecture-guide#dop" rel="noopener">parallelism</a> is implemented as if it were two operators. There’s the <strong>producers</strong> that push data to consumers, and the <strong>consumers</strong> that may have to wait for data from producers.

And so it becomes easier to understand how producer waits are the ones that may require attention, while consumer waits are inevitable as a passive consequence of longer running producers.
<h4>What is what going forward?</h4>
With this split, <strong>CXPACKET</strong> occurs when trying to synchronize the query processor exchange iterator or getting a required buffer.
<ul>
 	<li>This is the <strong>actionable</strong> wait. If contention on this wait type becomes a problem for most of your workload, consider for example:
<ul>
 	<li>Lowering the <a target="_blank" href="https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/configure-the-max-degree-of-parallelism-server-configuration-option" rel="noopener">Max Degree of Parallelism</a>, which can be done at the server or query level;</li>
 	<li>Changing the default <a target="_blank" href="https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/configure-the-cost-threshold-for-parallelism-server-configuration-option" rel="noopener">Cost Threshold for Parallelism</a> based on observed query cost for your entire workload;</li>
 	<li>Or better yet, by improving cardinality estimations if actual rows are very different from estimations. See <a target="_blank" href="https://blogs.msdn.microsoft.com/sql_server_team/new-in-ssms-query-performance-troubleshooting-made-easier/" rel="noopener">this previous blog post</a> on how to use the new SSMS Plan Analysis feature to get insights into cardinality estimation differences. Improving estimations can include actions such as updating or adding statistics, revising the underlying index design (consider leveraging the <a target="_blank" href="https://docs.microsoft.com/en-us/sql/tools/dta/tutorial-database-engine-tuning-advisor" rel="noopener">Database Tuning Advisor</a> for this), or even hinting the Query Optimizer in edge cases.</li>
</ul>
</li>
</ul>
And <strong>CXCONSUMER</strong> occurs when a consumer thread waits for a producer thread to send rows.
<ul>
 	<li>This is a wait type that is a normal part of parallel query execution, and cannot be directly influenced by changing the above mentioned configurations. This is why I called it "negligible" above.</li>
</ul>
<h4>Where can I see how this affects my SQL Servers?</h4>
These wait types will be surfaced at the server level with <a target="_blank" href="https://docs.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-os-wait-stats-transact-sql" rel="noopener">sys.dm_os_wait_stats</a>, database level with <a target="_blank" href="https://docs.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-query-store-wait-stats-transact-sql" rel="noopener">sys.query_store_wait_stats</a>, and session level with <a target="_blank" href="https://docs.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-exec-session-wait-stats-transact-sql" rel="noopener">sys.dm_exec_session_wait_stats</a> DMVs. The same for <a href="https://docs.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-os-waiting-tasks-transact-sql">sys.dm_os_waiting_tasks</a>, and the WAIT_INFO and WAIT_COMPLETED xEvents.

However, because CXCONSUMER is not actionable directly, this wait will not surface in the <a target="_blank" href="https://blogs.msdn.microsoft.com/sql_server_team/new-in-ssms-performance-dashboard-built-in/" rel="noopener">Performance Dashboard</a> nor in Showplan.
<h4>Practical example</h4>
Take the following simple query running in AdventureWorks2016:
<div id="codeSnippetWrapper">
<div id="codeSnippetWrapper">
<pre class="csharpcode" id="codeSnippet"><span class="kwrd">SELECT</span> *
<span class="kwrd">FROM</span> Sales.SalesOrderDetail SOD
<span class="kwrd">INNER</span> <span class="kwrd">JOIN</span> Production.Product P <span class="kwrd">ON</span> SOD.ProductID = P.ProductID
<span class="kwrd">WHERE</span> SalesOrderDetailID &gt; 10
<span class="kwrd">ORDER</span> <span class="kwrd">BY</span> Style</pre>
With the resulting showplan:

</div>
</div>
&nbsp;

<a href="https://msdnshared.blob.core.windows.net/media/2017/11/image136.png"><img width="1150" height="162" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/11/image_thumb116.png" border="0" /></a>

Since we have wait stats and query time stats in the root node of showplan, let’s see how they look:

<a href="https://msdnshared.blob.core.windows.net/media/2017/11/image146.png"><img width="211" height="182" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/11/image_thumb124.png" border="0" /></a> <a href="https://msdnshared.blob.core.windows.net/media/2017/11/image138.png"><img width="186" height="65" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/11/image_thumb118.png" border="0" /></a>

A lot of CXPACKET waits, totaling over 31s, for 1.2s CPU and 2.8s overall elapsed execution time. Also notice from showplan, this query is executing with DOP 12:

<a href="https://msdnshared.blob.core.windows.net/media/2017/11/image139.png"><img width="201" height="243" title="image" style="padding-top: 0px;padding-left: 0px;margin: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/11/image_thumb119.png" border="0" /></a>

As mentioned above, both producer and consumer waits are tracked at the server and session level, so let’s look at <a target="_blank" href="https://docs.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-exec-session-wait-stats-transact-sql" rel="noopener">sys.dm_exec_session_wait_stats</a> also. Note that any change that is done to improve on the high waits scenario above is aimed at producer waits (CXPACKET), given consumer waits (CXCONSUMER) may inevitably exist a normal part of parallelism:

<a href="https://msdnshared.blob.core.windows.net/media/2017/11/image140.png"><img width="722" height="82" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/11/image_thumb120.png" border="0" /></a>

Ok, so actually most of the parallelism waits are producer waits. We may expect to see consumer waits to go up in the initial moments of parallel query execution, but then stabilize.

A quick way to handle this scenario is to reduce DOP using a hint:
<div>
<pre class="csharpcode" id="codeSnippet"><span class="kwrd">SELECT</span> *
<span class="kwrd">FROM</span> Sales.SalesOrderDetail SOD
<span class="kwrd">INNER</span> <span class="kwrd">JOIN</span> Production.Product P <span class="kwrd">ON</span> SOD.ProductID = P.ProductID
<span class="kwrd">WHERE</span> SalesOrderDetailID &gt; 10
<span class="kwrd">ORDER</span> <span class="kwrd">BY</span> Style
<span class="kwrd">OPTION</span> (MAXDOP 4)</pre>
</div>
<div>In the resulting plan, here are the wait stats and query time stats:</div>
<div></div>
<div><a href="https://msdnshared.blob.core.windows.net/media/2017/11/image141.png"><img width="221" height="149" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/11/image_thumb121.png" border="0" /></a> <a href="https://msdnshared.blob.core.windows.net/media/2017/11/image142.png"><img width="201" height="69" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/11/image_thumb122.png" border="0" /></a></div>
CXPACKET waits down to just over 10s, for 0.8s CPU and 2.7s overall elapsed execution time. So while the elapsed time remained very similar (although lower), there were gains in reducing CPU usage and waits (3x lower) by adjusting DOP just enough.

Your mileage may vary depending on your setup, but thinking that this query may run at scale in a given environment, the gains are relevant. And were made possible by all the insights unlocked in showplan.

Pedro Lopes (<a href="https://twitter.com/sqlpto">@sqlpto</a>) – Senior Program Manager]]></content:encoded>
    </item>
    <item>
      <title>New Showplan enhancements</title>
      <link>https://docs.microsoft.com/archive/blogs/blogdoezequiel/new-showplan-enhancements</link>
      <pubDate>Fri, 10 Nov 2017 16:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Pedro Lopes (PL)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/blogdoezequiel/?p=4125</guid>
      <description><![CDATA[Cross post with https://aka.ms/sqlserverteam  If you follow this blog, you have seen that in the past...]]></description>
      <content:encoded><![CDATA[<h3>Cross post with <a href="https://aka.ms/sqlserverteam">https://aka.ms/sqlserverteam</a> </h3> <p>If you follow this blog, you have seen that in the past few releases we have continuously included a number of diagnostic improvements to Showplan. You can read about some of them <a href="https://blogs.msdn.microsoft.com/sql_server_team/tag/showplan/" target="_blank">here</a>.</p> <p>Looking at the actual execution plan is one of the most used performance troubleshooting techniques. Having information on elapsed CPU time and overall execution time, together with session wait information in an actual execution plan allows a DBA to use showplan to troubleshoot issues away from the server, and be able to correlate and compare different types of waits that result from query or schema changes.  </p><p>A few months ago we had introduced exposed in SSMS some of the per-operator statistics, such as <a href="https://blogs.msdn.microsoft.com/sql_server_team/new-showplan-xml-properties-in-ssms-october-release/" target="_blank">CPU and elapsed time per thread</a>. More recently, we have introduced overall <strong>query CPU and elapsed time</strong> tracking for statistics showplan xml (both in ms). These can be found in the root node of an actual plan. Available using the latest versions of SSMS v17, when used with <a href="https://support.microsoft.com/en-us/help/4018073/sql-server-2012-service-pack-4-release-information" target="_blank">SQL Server 2012 SP4</a>, <a href="https://support.microsoft.com/en-us/help/3182545/sql-server-2016-service-pack-1-release-information" target="_blank">SQL Server 2016 SP1</a> and SQL Server 2017. For SQL Server 2014 it will become available in a future Service Pack.&nbsp; </p><p><a href="https://msdnshared.blob.core.windows.net/media/2017/11/image_thumb710.png"><img title="image_thumb7" style="border-top: 0px;border-right: 0px;border-bottom: 0px;padding-top: 0px;padding-left: 0px;border-left: 0px;margin: 0px;padding-right: 0px" border="0" alt="image_thumb7" src="https://msdnshared.blob.core.windows.net/media/2017/11/image_thumb7_thumb.png" width="196" height="60"/></a>&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/2017/11/image_thumb610.png"><img title="image_thumb6" style="border-top: 0px;border-right: 0px;border-bottom: 0px;padding-top: 0px;padding-left: 0px;border-left: 0px;margin: 0px;padding-right: 0px" border="0" alt="image_thumb6" src="https://msdnshared.blob.core.windows.net/media/2017/11/image_thumb6_thumb.png" width="210" height="58"/></a>  </p><p>And also included the <strong>top 10 waits</strong> that the execution was waiting on (includes WaitType, WaitTimeMs and WaitCount), based on <a href="https://docs.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-exec-session-wait-stats-transact-sql" target="_blank">sys.dm_exec_session_wait_stats</a>. Most common sleep and idle waits are filtered out from the actual plan, so that it becomes easier to really see the relevance of non-idle waits for query performance.  </p><p><a href="https://msdnshared.blob.core.windows.net/media/2017/11/image_thumb810.png"><img title="image_thumb8" style="border-top: 0px;border-right: 0px;border-bottom: 0px;padding-top: 0px;padding-left: 0px;border-left: 0px;margin: 0px;padding-right: 0px" border="0" alt="image_thumb8" src="https://msdnshared.blob.core.windows.net/media/2017/11/image_thumb8_thumb.png" width="322" height="296"/></a></p> <p>This allows a user to correlate waits with overall times, and be more precise in what to look for to improve query performance. For example, in the picture below, I can correlate the overall elapsed time with the top waits, see that CXPACKET were the most prevalent, that this query is running with DOP 12, and choose to reduce DOP as a way to address this (among other actions possible).</p> <p><a href="https://msdnshared.blob.core.windows.net/media/2017/11/image_thumb310.png"><img title="image_thumb[3]" style="border-top: 0px;border-right: 0px;border-bottom: 0px;padding-top: 0px;padding-left: 0px;border-left: 0px;margin: 0px;padding-right: 0px" border="0" alt="image_thumb[3]" src="https://msdnshared.blob.core.windows.net/media/2017/11/image_thumb3_thumb.png" width="794" height="353"/></a></p> <p>Available using the latest versions of SSMS v17, when used with <a href="https://support.microsoft.com/en-us/help/3182545/sql-server-2016-service-pack-1-release-information" target="_blank">SQL Server 2016 SP1</a> and SQL Server 2017. Note that CXPACKET wait will be available in showplan with SQL Server 2017 CU3 and 2016 SP2. </p> <p>One other information you can now find in showplan is trace flags. This is relevant to understand what trace flags are active during compilation, and which one (if any) actually influence compilation. Below we can see trace flags 2371, 7412 and 9481 were active during compilation (IsCompileTime = True), but 23714 and 7412 did not influence the Query Optimizer (IsCompileTime = False). You can see more information on these trace flags and others in <a href="https://aka.ms/traceflags">https://aka.ms/traceflags</a>. </p> <p><a href="https://msdnshared.blob.core.windows.net/media/2017/11/image_thumb211.png"><img title="image_thumb[2]" style="border-top: 0px;border-right: 0px;border-bottom: 0px;padding-top: 0px;padding-left: 0px;border-left: 0px;margin: 0px;padding-right: 0px" border="0" alt="image_thumb[2]" src="https://msdnshared.blob.core.windows.net/media/2017/11/image_thumb2_thumb1.png" width="229" height="406"/></a></p> <p>These can be found in the root node of even an estimated plan, given this is a compile time ionformation. Available using the latest versions of SSMS v17, when used with <a href="https://support.microsoft.com/en-us/help/4018073/sql-server-2012-service-pack-4-release-information" target="_blank">SQL Server 2012 SP4</a>, <a href="https://support.microsoft.com/en-us/help/3182545/sql-server-2016-service-pack-1-release-information" target="_blank">SQL Server 2016 SP1</a> and SQL Server 2017. For SQL Server 2014 it will become available in a future Service Pack. </p> <p>Pedro Lopes (<a href="https://twitter.com/sqlpto">@sqlpto</a>) – Senior Program Manager</p>]]></content:encoded>
    </item>
    <item>
      <title>Persisting statistics sampling rate</title>
      <link>https://docs.microsoft.com/archive/blogs/blogdoezequiel/persisting-statistics-sampling-rate</link>
      <pubDate>Sat, 12 Aug 2017 06:24:32 GMT</pubDate>
      <dc:creator><![CDATA[Pedro Lopes (PL)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/blogdoezequiel/?p=4036</guid>
      <description><![CDATA[Cross post with https://aka.ms/sqlserverteam When SQL Server creates or updates statistics and a...]]></description>
      <content:encoded><![CDATA[<h4>Cross post with <a href="https://aka.ms/sqlserverteam">https://aka.ms/sqlserverteam</a></h4> <p>When SQL Server creates or updates statistics and a sampling rate is not manually specified, SQL Server calculates a default sampling rate. Depending on the real distribution of data in the underlying table, the default sampling rate may not accurately represent the data distribution and then cause degradation of query plan efficiency. </p> <p>To improve this scenario, a database administrator can choose to manually update statistics with a specific sampling rate that can better represent the distribution of data. However, a subsequent automatic update statistics operation will reset back to the default sampling rate, possibly reintroducing degradation of query plan efficiency.  </p><p>With the most recent <a href="https://support.microsoft.com/en-us/help/4024305" target="_blank">SQL Server 2016 SP1 CU4</a>, we released an enhancement for the <a href="https://docs.microsoft.com/en-us/sql/t-sql/statements/create-statistics-transact-sql" target="_blank">CREATE</a> and <a href="https://docs.microsoft.com/en-us/sql/t-sql/statements/update-statistics-transact-sql" target="_blank">UPDATE STATISTICS</a> command – the ability to persist sampling rates between updates with a <strong>PERSIST_SAMPLE_PERCENT</strong> keyword.  </p><p>Let’s use an example. I’m using the following query:</p><pre class="csharpcode"><span class="kwrd">SELECT</span> [SalesOrderID],[ShipDate],[DueDate],[OrderDate]
<span class="kwrd">FROM</span> [Sales].[SalesOrderHeaderBulk]
<span class="kwrd">WHERE</span> OrderDate <span class="kwrd">BETWEEN</span> <span class="str">'8/30/2012 00:00:00.000'</span> <span class="kwrd">AND</span> <span class="str">'9/30/2012 00:00:00.000'</span> 
GO</pre>
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }


<p>Looking at the actual plan, we see a skew between estimated and actual rows in the scan over the orders table:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/2017/08/image223.png"><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb166.png" width="290" height="116" /></a></p>
<p>Let’s check stats on this table then. I’m searching for stats on table orders with column col2 (part of the join argument):</p><pre class="csharpcode"><span class="kwrd">SELECT</span> ss.stats_id, ss.name, filter_definition, last_updated, <span class="kwrd">rows</span>, 
    rows_sampled, steps, unfiltered_rows, modification_counter, persisted_sample_percent,
    (rows_sampled * 100)/<span class="kwrd">rows</span> <span class="kwrd">AS</span> sample_percent
<span class="kwrd">FROM</span> sys.stats ss
<span class="kwrd">INNER</span> <span class="kwrd">JOIN</span> sys.stats_columns sc 
    <span class="kwrd">ON</span> ss.stats_id = sc.stats_id <span class="kwrd">AND</span> ss.object_id = sc.object_id
<span class="kwrd">INNER</span> <span class="kwrd">JOIN</span> sys.all_columns ac 
    <span class="kwrd">ON</span> ac.column_id = sc.column_id <span class="kwrd">AND</span> ac.object_id = sc.object_id
<span class="kwrd">CROSS</span> APPLY sys.dm_db_stats_properties(ss.object_id, ss.stats_id) shr
<span class="kwrd">WHERE</span> ss.[object_id] = OBJECT_ID(<span class="str">'[Sales].[SalesOrderHeaderBulk]'</span>) 
    <span class="kwrd">AND</span> ac.name = <span class="str">'OrderDate'</span>;</pre>
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }


<p>We see a statistic for the index used above, with a sampling rate of 6 percent. Let’s say I really need to improve estimations, and that having a higher sampling rate could just do that.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/2017/08/image224.png"><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb167.png" width="862" height="43" /></a></p>
<p>So I’ll just update this statistic, and while I could try to find a better (and higher) sampling rate, for this demo I’ll just update with full scan:</p><pre class="csharpcode"><span class="kwrd">UPDATE</span> <span class="kwrd">STATISTICS</span> [Sales].[SalesOrderHeaderBulk] [IX_OrderDate] <span class="kwrd">WITH</span> FULLSCAN</pre>
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }


<p><a href="https://msdnshared.blob.core.windows.net/media/2017/08/image225.png"><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb168.png" width="870" height="40" /></a></p>
<p>Let’s see the estimations now:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/2017/08/image226.png"><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb169.png" width="297" height="113" /></a></p>
<p>Great, so what happens when auto update statistics is triggered? Or I have some stats maintenance job that does not explicitly sets the sampling rate? </p><pre class="csharpcode"><span class="kwrd">UPDATE</span> <span class="kwrd">STATISTICS</span> [Sales].[SalesOrderHeaderBulk] [IX_OrderDate]</pre>
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }


<p><a href="https://msdnshared.blob.core.windows.net/media/2017/08/image227.png"><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb170.png" width="892" height="45" /></a></p>
<p>It’s back at default sampling (in this case 6 percent). </p>
<p>I really want to always update this statistic with 100 percent sampling rate, so I can now use the following <strong>PERSIST_SAMPLE_PERCENT</strong> keyword:</p><pre class="csharpcode"><span class="kwrd">UPDATE</span> <span class="kwrd">STATISTICS</span> [Sales].[SalesOrderHeaderBulk] [IX_OrderDate] 
<span class="kwrd">WITH</span> FULLSCAN, PERSIST_SAMPLE_PERCENT = ON</pre>
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }


<p><a href="https://msdnshared.blob.core.windows.net/media/2017/08/image228.png"><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb171.png" width="907" height="42" /></a></p>
<p>Notice the new <strong>persisted_sample_percent</strong> column is now showing 100 percent (because sI used FULLSCAN). Both <a href="https://docs.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-show-statistics-transact-sql" target="_blank">DBCC SHOW_STATISTICS</a> and <a href="https://docs.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-db-stats-properties-transact-sql" target="_blank">sys.dm_db_stats_properties</a> have this new column.</p>
<p>What happens when auto update statistics is triggered or my stats are manually updated again?</p><pre class="csharpcode"><span class="kwrd">UPDATE</span> <span class="kwrd">STATISTICS</span> [Sales].[SalesOrderHeaderBulk] [IX_OrderDate]</pre>
<p><a href="https://msdnshared.blob.core.windows.net/media/2017/08/image229.png"><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb172.png" width="901" height="45" /></a> 
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }

</p>
<p>My choice for sampling percentage is now persisted. It will remain persisted until I set this option to OFF. When set to OFF (which is the default), the statistics sampling percentage will get reset to default sampling in subsequent updates that do not explicitly specify a sampling percentage.</p>
<p>Note that if a manual update statistics is executed with a different sampling percentage, but not using PERSIST_SAMPLE_PERCENT keyword to set it as the new persisted value, the previously set fixed sampling will still be in effect for subsequent auto update statistics, or any other manual update that does not set a specific sampling rate.</p><pre class="csharpcode"><span class="kwrd">UPDATE</span> <span class="kwrd">STATISTICS</span> [Sales].[SalesOrderHeaderBulk] [IX_OrderDate] <span class="kwrd">WITH</span> SAMPLE 90 PERCENT</pre>
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }


<p><a href="https://msdnshared.blob.core.windows.net/media/2017/08/image230.png"><img title="image" style="border-left-width: 0px;border-right-width: 0px;border-bottom-width: 0px;padding-top: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb173.png" width="904" height="45" /></a></p>
<p>Pedro Lopes (<a href="https://twitter.com/sqlpto">@sqlpto</a>) – Senior Program Manager</p>]]></content:encoded>
    </item>
    <item>
      <title>New in SSMS: Searching in Showplan</title>
      <link>https://docs.microsoft.com/archive/blogs/blogdoezequiel/new-in-ssms-searching-in-showplan</link>
      <pubDate>Tue, 08 Aug 2017 07:05:41 GMT</pubDate>
      <dc:creator><![CDATA[Pedro Lopes (PL)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/blogdoezequiel/?p=3925</guid>
      <description><![CDATA[Cross post with https://aka.ms/sqlserverteam
Have you ever analyzed a somewhat big plan? And while...]]></description>
      <content:encoded><![CDATA[<h4>Cross post with <a href="https://aka.ms/sqlserverteam">https://aka.ms/sqlserverteam</a></h4>
Have you ever analyzed a somewhat big plan? And while doing so did you ever wish you could search for something like table name, index name or column name?

In <a href="https://docs.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms">SSMS</a> 17.2, we are including the ability to search all these and more in graphical showplan.

Let’s look at an example. I executed a query while an xEvent session with <a target="_blank" href="https://blogs.msdn.microsoft.com/sql_server_team/added-per-operator-level-performance-stats-for-query-processing/" rel="noopener noreferrer">query_thread_profile</a> is running (see sample session <a target="_blank" href="https://blogs.msdn.microsoft.com/sql_server_team/added-per-operator-level-performance-stats-for-query-processing/" rel="noopener noreferrer">here</a>). Opening the xel file provides a lot of insight. For example, going through the performance information collected per node, I see node 30 is doing a good part of the IO for this query.

<a href="https://msdnshared.blob.core.windows.net/media/2017/08/image69.png"><img width="716" height="639" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb68.png" border="0" /></a>

Great. So now I want to open the associated cached plan, so I can see which operator this one is, and where in the plan it sits. I will correlate the query_plan_signed xEvent action with DMVs/DMFs (see example <a target="_blank" href="https://blogs.msdn.microsoft.com/sql_server_team/correlating-xevents-with-dmvs/" rel="noopener noreferrer">here</a>).
<div id="codeSnippetWrapper">
<pre class="csharpcode" id="codeSnippet"><span class="kwrd">SELECT</span> qp.query_plan 
<span class="kwrd">FROM</span> sys.dm_exec_query_stats qs
<span class="kwrd">CROSS</span> APPLY sys.dm_exec_query_plan(qs.plan_handle) qp
<span class="kwrd">WHERE</span> <span class="kwrd">CAST</span>(qs.query_plan_hash <span class="kwrd">AS</span> BIGINT) = -832496756154281217</pre>
How will I search for node_id 30? The showplan xml is available to search on in SSMS:

</div>
<div><a href="https://msdnshared.blob.core.windows.net/media/2017/08/image70.png"><img width="505" height="263" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb69.png" border="0" /></a></div>
Ok, so it’s a Table Spool, but the plan XML has more Table Spools, and it’s fairly large, so I still need to visually search for this Table Spool manually. Not the best or fastest experience.

<a href="https://msdnshared.blob.core.windows.net/media/2017/08/image71.png"><img width="768" height="287" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb70.png" border="0" /></a>

But what if I could search for node id 30 while looking at the graphical showplan?

Starting with <a href="https://docs.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms">SSMS</a> 17.2, just use CTRL+F to start a search in graphical showplan (or right-click on a blank area of the plan, and in the context menu click on <em>Find Node</em> option), and you can quickly see exactly where node id 30 is:

<a href="https://msdnshared.blob.core.windows.net/media/2017/08/image72.png"><img width="672" height="315" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb71.png" border="0" /></a>

But I could search on all physical operations containing the word Spool, and move thru them using the arrows (highlighted):

<a href="https://msdnshared.blob.core.windows.net/media/2017/08/image73.png"><img width="689" height="315" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb72.png" border="0" /></a>

I can actually search on any property I want to, such as table name, column name, schema name, index name, index type and many other properties, making navigation in graphical showplan even easier:

<a href="https://msdnshared.blob.core.windows.net/media/2017/08/image74.png"><img width="355" height="477" title="image" style="padding-top: 0px;padding-left: 0px;padding-right: 0px;border-width: 0px" alt="image" src="https://msdnshared.blob.core.windows.net/media/2017/08/image_thumb73.png" border="0" /></a>

This feature is available anywhere a graphical showplan is open, including Plan Comparison, Plan Scenarios and Query Store. More information on these other SSMS features available in <a target="_blank" href="https://blogs.msdn.microsoft.com/sql_server_team/new-in-ssms-query-performance-troubleshooting-made-easier/" rel="noopener noreferrer">New in SSMS: Query Performance Troubleshooting made easier!</a>

Pedro Lopes (<a href="https://twitter.com/sqlpto">@sqlpto</a>) – Senior Program Manager]]></content:encoded>
    </item>
  </channel>
</rss>