<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://www2.sqlblog.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>The Curious Case of the Optimizer that doesn’t</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/04/the-curious-case-of-the-optimizer-that-doesn-t.aspx</link><description>The optimizer is the part of SQL Server that takes your query and reorders and rearranges your query to find the optimal execution plan. In theory. In practice, that doesn’t always work out well. Often, the optimizer manages to come up with brilliant</description><dc:language>en</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>re: The Curious Case of the Optimizer that doesn’t</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/04/the-curious-case-of-the-optimizer-that-doesn-t.aspx#43165</link><pubDate>Thu, 03 May 2012 23:18:59 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43165</guid><dc:creator>Paul White</dc:creator><description>&lt;p&gt;Hi Hugo,&lt;/p&gt;
&lt;p&gt;The same considerations apply to the extensions in 2012 (e.g. SUM OVER ORDER BY) that use a Window Spool operator.&lt;/p&gt;
&lt;p&gt;Almost all the optimizer's current exploration rules are based in relational theory and the algebraic equivalences derived from that theory (extended a bit to work with SQL's multi-sets, rather than strict sets), as you mention. &amp;nbsp;These rules don't work directly with sequences, which were a new concept for the engine added in SQL Server 2005 (hence the 'Sequence Project' operator). &amp;nbsp;Sequences have a order to them that sets (and multi-sets) do not have.&lt;/p&gt;
&lt;p&gt;The optimizer reasons about sort orders for operations like Merge Join and Stream Aggregate, but this reasoning is based on multi-sets, and does not apply to sequences. &amp;nbsp;Nevertheless, I had hoped for optimizer support for sequences to deepen more than it has since SQL Server 2005.&lt;/p&gt;
&lt;p&gt;For example, the optimizer still cannot push a predicate past a sequence operation unless the sequence has the predicated column in its PARTITION BY clause, *and* the predicate evaluates against a runtime constant value. &amp;nbsp;See the unpushed Filter in this query plan:&lt;/p&gt;
&lt;p&gt;WITH MyCTE AS&lt;/p&gt;
&lt;p&gt;(&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;SELECT&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;TerritoryID,&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;SalesLastYear,&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Rank1 = RANK() OVER (ORDER BY SalesLastYear),&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Rank2 = RANK() OVER (ORDER BY SalesYTD)&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;FROM Sales.SalesTerritory&lt;/p&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;p&gt;SELECT&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;TerritoryID,&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;Rank1,&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;Rank2&lt;/p&gt;
&lt;p&gt;FROM MyCTE&lt;/p&gt;
&lt;p&gt;WHERE&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;MyCTE.TerritoryID &amp;lt; 5&lt;/p&gt;
&lt;p&gt;ORDER BY&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;MyCTE.SalesLastYear;&lt;/p&gt;
&lt;p&gt;You have my vote.&lt;/p&gt;
&lt;p&gt;Paul&lt;/p&gt;
</description></item><item><title>re: The Curious Case of the Optimizer that doesn’t</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/04/the-curious-case-of-the-optimizer-that-doesn-t.aspx#43173</link><pubDate>Fri, 04 May 2012 05:30:39 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43173</guid><dc:creator>SomewhereSomehow</dc:creator><description>&lt;p&gt;Hugo Kornelis,&lt;/p&gt;
&lt;p&gt;Very interesting nuance, I'll add it to my KB.&lt;/p&gt;
&lt;p&gt;Paul White,&lt;/p&gt;
&lt;p&gt;How could we use predicate pushdown, to early filtering before ranking, in your example? If we do so, we may expect different logical sense, and different ranking numbers...&lt;/p&gt;
</description></item><item><title>re: The Curious Case of the Optimizer that doesn’t</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/04/the-curious-case-of-the-optimizer-that-doesn-t.aspx#43174</link><pubDate>Fri, 04 May 2012 06:27:15 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43174</guid><dc:creator>Paul White</dc:creator><description>&lt;p&gt;@SomewhereSomehow TerritoryID would need to be part of the RANK's PARTITION BY clause. &amp;nbsp;Point is, it only works with constants.&lt;/p&gt;
&lt;p&gt;Paul&lt;/p&gt;
</description></item><item><title>re: The Curious Case of the Optimizer that doesn’t</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/04/the-curious-case-of-the-optimizer-that-doesn-t.aspx#43175</link><pubDate>Fri, 04 May 2012 07:47:54 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43175</guid><dc:creator>SomewhereSomehow</dc:creator><description>&lt;p&gt;I talked about your example. You said still can not push if there is no partition by, and I thought how could it be ever possible to push without partition by in such queries.&lt;/p&gt;
&lt;p&gt;Interesting note about a run-time constant, seems to be so indeed.&lt;/p&gt;
</description></item><item><title>re: The Curious Case of the Optimizer that doesn’t</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/04/the-curious-case-of-the-optimizer-that-doesn-t.aspx#43176</link><pubDate>Fri, 04 May 2012 08:13:44 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43176</guid><dc:creator>Paul White</dc:creator><description>&lt;p&gt;That's right, the PARTITION BY requirement is logical. &amp;nbsp;In 2005, the optimizer couldn't do the push even with a constant. &amp;nbsp;2008 on, it can, but not, in general, with a variable reference (without OPTION RECOMPILE or something else that causes a statement-level recompilation.)&lt;/p&gt;
</description></item><item><title>re: The Curious Case of the Optimizer that doesn’t</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/04/the-curious-case-of-the-optimizer-that-doesn-t.aspx#43177</link><pubDate>Fri, 04 May 2012 09:35:35 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43177</guid><dc:creator>SomewhereSomehow</dc:creator><description>&lt;p&gt;Maybe it is worth saying, I did some experiments and couldn't find any other ways (for now) except option(recomple) to force predicate push down with variable after recompilation. &lt;/p&gt;
&lt;p&gt;Altering schema, using temp tables, changing set options, auto update stats - all these stuff produce StmtRecompile event, but we see no pushdown. Even creating proc with recompile keyword isn't helpful. It seems to act like &amp;quot;is null or value&amp;quot; problem for some reasons.&lt;/p&gt;
</description></item><item><title>re: The Curious Case of the Optimizer that doesn’t</title><link>http://www2.sqlblog.com/blogs/hugo_kornelis/archive/2012/05/04/the-curious-case-of-the-optimizer-that-doesn-t.aspx#43181</link><pubDate>Fri, 04 May 2012 10:32:41 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43181</guid><dc:creator>Paul White</dc:creator><description>&lt;p&gt;Of course - RECOMPILE is required for the parameter embedding optimization. &amp;nbsp;I must have been thinking of table variable cardinality estimation, which is affected by a statement-level recompile. &amp;nbsp;Thanks.&lt;/p&gt;
</description></item></channel></rss>