<?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>Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx</link><description>Scalar. Function. Wow. Could any other combination of words evoke the same feeling of encapsulation, information hiding, and simplification of client code? After years spent developing software in the procedural and OO worlds, it can be difficult--perhaps,</description><dc:language>en</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#150</link><pubDate>Tue, 08 Aug 2006 05:15:28 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:150</guid><dc:creator>Greg_Linwood</dc:creator><description>Hey Adam - nicely written post&lt;br&gt;&lt;br&gt;Another issue that complicates measuring IO from UDFs is that the Profiler Reads output contains Proc Cache lookups - which are also 8K IOs, whereas statistics io doesn't. In SQL 2000 UDFs, the Proc Cache was looked up per-invocation of the UDF (per row), potentially skewing the values returned by Reads depending on the size of the cache. I've seen scenarios where the same statement (involving a UDF) recorded signficantly variant Reads during peak processing periods (when the cache is bloated) vs during average processing periods (when the cache has reduced to a smaller size). &lt;br&gt;&lt;br&gt;In SQL 2005, this has been sensibly scaled back so that the proc cache is only looked up for the first invocation in a rowset, improving UDF performance somewhat by eliminating the repetitive cache lookups performed in SQL 2000..&lt;br&gt;&lt;br&gt;Cheers&lt;br&gt;Greg</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#183</link><pubDate>Mon, 04 Sep 2006 05:53:30 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:183</guid><dc:creator>glenntoy</dc:creator><description>Nice one. &lt;br&gt;&lt;br&gt;When I started with SQL 2000 I was fascinated with its UDF feature, I used to do this way but my boss told to change it due to performance reason. As much as possible I do avoid performing a query inside the function, but in cases where it can't be avoided the best way is to optimized the query inside the function.</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#799</link><pubDate>Fri, 09 Feb 2007 18:44:15 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:799</guid><dc:creator>Meher</dc:creator><description>&lt;p&gt;Great Post Adam. Fascinating details of UDF. I always wondered how a Scalar UDF be converted to a Inline table valued UDF and this post actually shows that.&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#3932</link><pubDate>Thu, 13 Dec 2007 19:02:32 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:3932</guid><dc:creator>Darren</dc:creator><description>&lt;p&gt;great article, confirming what I've been seeing...really a surprise to me. &amp;nbsp;Good suggestions for handling as table functions...will try that.&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#4821</link><pubDate>Fri, 01 Feb 2008 16:16:20 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:4821</guid><dc:creator>SJC</dc:creator><description>&lt;p&gt;Thanks for this post Adam; I'm experiencing this problem at the moment and the article gives me great pointers on how to solve it to everyone's satisfaction. &lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#7548</link><pubDate>Fri, 27 Jun 2008 14:30:11 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:7548</guid><dc:creator>Matt Miller</dc:creator><description>&lt;p&gt;Adam - &lt;/p&gt;
&lt;p&gt;Since you're using a TVF, you could &amp;quot;improve readability&amp;quot; with a CROSS APPLY statement. Since it's a single value, the perf penalties that come in from CROSS APPLY don't seem to pop up...&lt;/p&gt;
&lt;p&gt;So it would look like&lt;/p&gt;
&lt;p&gt;SELECT &amp;nbsp; &amp;nbsp;ProductId,&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;MaxQty&lt;/p&gt;
&lt;p&gt;FROM Production.Product&lt;/p&gt;
&lt;p&gt;CROSS APPLY dbo.GetMaxProductQty_Inline(ProductId) MaxQT&lt;/p&gt;
&lt;p&gt;ORDER BY ProductId&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#7565</link><pubDate>Sun, 29 Jun 2008 20:27:39 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:7565</guid><dc:creator>gene</dc:creator><description>&lt;p&gt;Adam, this is a great post. I only want to add one practical detail to your post which support it.&lt;/p&gt;
&lt;p&gt;Most of the time ( or in my experience of 15yr - all the time) programmers are not trained and do not care about performance tunning. However, application usually should be maintained for 3-5 years of it's life span.&lt;/p&gt;
&lt;p&gt;This is usually overlooked. Finally, dba - person who did not develop the application should start tunning it and here is a big problem having UDF's and views.&lt;/p&gt;
&lt;p&gt;When you say that UDF may bring benefits, did you take in count the fact that code which uses UDF's and views is almoust impossible to analize for performance improvements?&lt;/p&gt;
&lt;p&gt;Try to traverse a code which use UDF which goes aganist view, which uses another 2 views or so!&lt;/p&gt;
&lt;p&gt;This is a real price for 'sleek' UDF use. That's the real difference between experienced seasoned programmer who had met and learned this by his own experience and talanted 2-3 yr. programmer who measures his work by complexity of his queries and use of funcy new features like UDF.&lt;/p&gt;
&lt;p&gt;I bet real good code is measured by it's ability to be troubleshouted easily too. And UDF's and views are sure means not to achieve that.&lt;/p&gt;
</description></item><item><title>TSQL Scalar functions are evil.</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#9853</link><pubDate>Mon, 03 Nov 2008 21:49:38 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:9853</guid><dc:creator>SimonS Blog on SQL Server Stuff</dc:creator><description>&lt;p&gt;I’ve been working with a number of clients recently who all have suffered at the hands of TSQL Scalar&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#14265</link><pubDate>Mon, 25 May 2009 14:15:16 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:14265</guid><dc:creator>d1rtyw0rm</dc:creator><description>&lt;p&gt;Thanks alot !&lt;/p&gt;
&lt;p&gt;That is really well explains and solve my problem.&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#19428</link><pubDate>Wed, 02 Dec 2009 15:53:26 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:19428</guid><dc:creator>Tom VdP</dc:creator><description>&lt;p&gt;Thank you! &amp;nbsp;I have succesfully used this optimalisation to speed up our ETL process. &amp;nbsp;We were doing quite a lot of date calculations via functions: having a date format yyyymmdd but needing date calculations like &amp;quot;substract 6 hours&amp;quot; made scalar UDFs a logical choice. &amp;nbsp;It is now implemented using 'inline' table-valued functions. &amp;nbsp;Speeds up the processing!&lt;/p&gt;
&lt;p&gt;Thanks again, excellent post.&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#22706</link><pubDate>Mon, 01 Mar 2010 21:50:06 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:22706</guid><dc:creator>Denise</dc:creator><description>&lt;p&gt;We just went thru this issue and when I went to do the research for a possible fis, I found your post.&lt;/p&gt;
&lt;p&gt;Invaluable!&lt;/p&gt;
&lt;p&gt;Thanks very much.&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#25543</link><pubDate>Wed, 26 May 2010 08:40:50 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:25543</guid><dc:creator>RichB</dc:creator><description>&lt;p&gt;I'm on a project migrating from Oracle to SQL Server. It turns out a lot of our reports call scalar UDFs for most of the projected columns. In Oracle, a typical query takes seconds. In SQL Server, 30 minutes.&lt;/p&gt;
&lt;p&gt;Clearly, it's not that SQL Server can't solve the perf problem they have with scalar UDFs, but that they haven't prioritized it over other features.&lt;/p&gt;
&lt;p&gt;So now I've found your great article (and a number of other similar articles on Cross Apply), that's what we will have to do.&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#28622</link><pubDate>Wed, 08 Sep 2010 08:48:05 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:28622</guid><dc:creator>ali dkj</dc:creator><description>&lt;p&gt;nice post man,&lt;/p&gt;
&lt;p&gt;keep up the good work&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#28783</link><pubDate>Wed, 15 Sep 2010 11:30:28 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:28783</guid><dc:creator>SP</dc:creator><description>&lt;p&gt;Hurrr&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#42861</link><pubDate>Wed, 18 Apr 2012 01:05:26 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:42861</guid><dc:creator>Dave</dc:creator><description>&lt;p&gt;Great post. I would like to say though that Scalar functions can still be very useful, AS LONG AS you aren't using them in an SQL expression with loads of rows. &lt;/p&gt;
&lt;p&gt;For example I have some scalar functions such as fn_Daysearch, which returns a date for a day previous or future, like last Wednesday or next Monday. I typically only call these functions once at the start of a stored proc, usually passing in a proc parameter and using the return value in the WHERE clause of my main query. As a rule if it's only getting called once or a few times, then I'll go scalar.&lt;/p&gt;
&lt;p&gt;Also Matts CROSS APPLY above is a perfectly good option, although I'd prefer using MAX(sod.OrderQty) OVER (PARTITION BY sod.ProductId) myself.&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#42878</link><pubDate>Wed, 18 Apr 2012 14:11:37 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:42878</guid><dc:creator>Adam Machanic</dc:creator><description>&lt;p&gt;Dave, agreed. But make sure that you assign the results of your scalar UDF to a variable, and then use that in the WHERE clause. Otherwise, you A) don't know that it will only be called once, and B) may encounter some other issues (T-SQL scalar UDFs will inhibit parallelism).&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#43517</link><pubDate>Wed, 23 May 2012 15:39:38 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43517</guid><dc:creator>Brad</dc:creator><description>&lt;p&gt;Great information!. &amp;nbsp;I used this to streamline our ETL process. &amp;nbsp;I am now saving an average of 10 hours process time per day. &amp;nbsp;Unbelievable. &amp;nbsp;Thanks for the post.&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#43523</link><pubDate>Wed, 23 May 2012 17:49:48 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43523</guid><dc:creator>Adam Machanic</dc:creator><description>&lt;p&gt;Great news, Brad!&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#43729</link><pubDate>Tue, 05 Jun 2012 15:01:56 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43729</guid><dc:creator>Paul Barbin</dc:creator><description>&lt;p&gt;Adam, it's amazing that you wrote this over 6 years ago and it's still relevant (amazingly good for you or bad for MS?).&lt;/p&gt;
&lt;p&gt;We recently had an issue with a scalar UDF. &amp;nbsp;Being aware that scalar functions could cause problems we were careful to test before rolling to production. &amp;nbsp;Total run time on test machines was 5 minutes. &amp;nbsp;Production was a faster box; &amp;nbsp;we expected faster results. &amp;nbsp;Wrong. Production ran for 45 minutes before we had to kill it. &amp;nbsp;&lt;/p&gt;
&lt;p&gt;Subsequent &amp;quot;tests&amp;quot; in production showed nearly 2000 reads in production for a single run of the UDF and 3 in test (not kidding). &amp;nbsp;Same configuration, same settings, same db, same everything. &amp;nbsp;Almost. &amp;nbsp;&lt;/p&gt;
&lt;p&gt;In production we had two server traces running that were capturing statement-level events. &amp;nbsp;While both traces were filtering out most events, the server still collected them before discarding. &amp;nbsp;&lt;/p&gt;
&lt;p&gt;We stopped the traces, ran the UDF and it now shows 3 reads in production now...&lt;/p&gt;
&lt;p&gt;This URL showed us the light:&lt;/p&gt;
&lt;p&gt;&lt;a rel="nofollow" target="_new" href="http://sqlblog.com/blogs/linchi_shea/archive/2009/06/15/performance-impact-sql-trace-and-user-defined-scalar-functions.aspx"&gt;http://sqlblog.com/blogs/linchi_shea/archive/2009/06/15/performance-impact-sql-trace-and-user-defined-scalar-functions.aspx&lt;/a&gt;&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#43951</link><pubDate>Tue, 19 Jun 2012 11:35:39 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43951</guid><dc:creator>Leandro</dc:creator><description>&lt;p&gt;What I noticed is that an application that we develop, when using UDFs, increases a lot the RowCounts compared to when it's not using. I modified a query to check it and the query had to return 1250 rows, the RowCount using UDF was 5022 and, without it, the RowCount dropped to 1255. The reads count didn't differ so much between using and not using UDF, using it it was about 30 more reads than without it.&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#47114</link><pubDate>Fri, 11 Jan 2013 15:01:12 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:47114</guid><dc:creator>Christian</dc:creator><description>&lt;p&gt;Today, you are my hero.&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#47323</link><pubDate>Sat, 26 Jan 2013 16:35:21 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:47323</guid><dc:creator>JRStern</dc:creator><description>&lt;p&gt;Had an interesting experience yesterday looking at the index usage across a new-ish database. &amp;nbsp;The major tables showed usage of about 3,000,000. &amp;nbsp;But a couple of small control tables showed usage of about 240,000,000. &amp;nbsp;For a modest little app, 240m is a big number. &amp;nbsp;So, what is going on?&lt;/p&gt;
&lt;p&gt;Well, the index usage stats basically count plans that touch the index, not the number of rows touched. So, 240m plans??? &amp;nbsp;Well yes - when you use a UDF in the where clause! &amp;nbsp;Each invocation is a *plan*, not just a statement, not just a fncall. &lt;/p&gt;
&lt;p&gt;So it's MUCH worse than a cursor.&lt;/p&gt;
&lt;p&gt;And I will soon be a hero at work when we eliminate those UDFs, which are really there more to be pretty than because of need. &amp;nbsp;And they are pretty, dammit. &amp;nbsp;Has anyone at Microsoft ever talked about changing their scalar UDF implementation to be more like the TVFs, in that the optimizer can look inside? &amp;nbsp;Microsoft basically botched the whole UDF project in SQL 2000, they got confused about stochastic and non-stochastic and never did figure out what they were really doing, ... at least that's my reading on it.&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#48035</link><pubDate>Tue, 05 Mar 2013 08:33:15 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:48035</guid><dc:creator>Asit</dc:creator><description>&lt;p&gt;Adam, i've been following you post for quite a long and find them of great help.&lt;/p&gt;
&lt;p&gt;But in my production environment we have a great UDF usage(which are multi statement table values function). They have great bussiness logic in them but they are IO HOGS. To improve in IO i mostly removed the code into the calling procedure or created an inline table function. So i suggest the developer that avoid using multi statement table valued function as much as possible. &lt;/p&gt;
&lt;p&gt;Your commetnts on that and reason of them hogging the IO&lt;/p&gt;
&lt;p&gt;Regards&lt;/p&gt;
&lt;p&gt;Asit&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#48050</link><pubDate>Tue, 05 Mar 2013 17:30:01 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:48050</guid><dc:creator>Adam Machanic</dc:creator><description>&lt;p&gt;@Asit: Multistatement UDFs use involve temp tables, so all of that I/O is almost certainly due to tempdb activity.&lt;/p&gt;
&lt;p&gt;--Adam&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#48550</link><pubDate>Fri, 05 Apr 2013 15:26:33 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:48550</guid><dc:creator>Adrian</dc:creator><description>&lt;p&gt;Rewrite the original scalar UDF to the code below. It will make a difference.&lt;/p&gt;
&lt;p&gt;CREATE FUNCTION GetMaxProductQty_Scalar&lt;/p&gt;
&lt;p&gt;(&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;@ProductId INT&lt;/p&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;p&gt;RETURNS INT&lt;/p&gt;
&lt;p&gt;AS&lt;/p&gt;
&lt;p&gt;BEGIN&lt;/p&gt;
&lt;p&gt;	RETURN (&lt;/p&gt;
&lt;p&gt;		SELECT TOP 1&lt;/p&gt;
&lt;p&gt;			MAX(sod.OrderQty)&lt;/p&gt;
&lt;p&gt;		FROM&lt;/p&gt;
&lt;p&gt;			Sales.SalesOrderDetail sod&lt;/p&gt;
&lt;p&gt;		WHERE&lt;/p&gt;
&lt;p&gt;			sod.ProductId = @ProductId&lt;/p&gt;
&lt;p&gt;	);&lt;/p&gt;
&lt;p&gt;END;&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#48562</link><pubDate>Sun, 07 Apr 2013 18:44:37 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:48562</guid><dc:creator>Adam Machanic</dc:creator><description>&lt;p&gt;Adrian:&lt;/p&gt;
&lt;p&gt;Unfortunately doing that does not, in fact, make any difference whatsoever. The query plans will still be identical, performance implications will still be identical, and the query optimizer will still be unable to make use of various features, including parallelism.&lt;/p&gt;
&lt;p&gt;--Adam&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#48805</link><pubDate>Mon, 22 Apr 2013 13:08:08 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:48805</guid><dc:creator>MarcVB</dc:creator><description>&lt;p&gt;Very interesting and to the point, but not complete for my case. So, is there someone who can help me to higher the performance when you have to deal with a function that aggregates the results of a select in 1 line. Eg&lt;/p&gt;
&lt;p&gt;CREATE FUNCTION [dbo].[Get_PaymentLines] &lt;/p&gt;
&lt;p&gt;	(@client nvarchar(255)&lt;/p&gt;
&lt;p&gt;	,@language nvarchar(255)&lt;/p&gt;
&lt;p&gt;	)&lt;/p&gt;
&lt;p&gt;RETURNS nvarchar(500) &lt;/p&gt;
&lt;p&gt;AS&lt;/p&gt;
&lt;p&gt;BEGIN&lt;/p&gt;
&lt;p&gt; &amp;nbsp;Declare &lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;@dummy nvarchar(500),&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;@Line nvarchar(255)&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;SET @Dummy = ''&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;DECLARE Payment_cursor CURSOR&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;FOR SELECT convert(nvarchar(2), line) + ' ' + &amp;nbsp; &lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; convert(nvarchar(10), convert(money,amount))&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;FROM payments p&lt;/p&gt;
&lt;p&gt;	WHERE &amp;nbsp;(p.client = @client and p.language = @language)&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;OPEN Payment_Cursor&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;FETCH NEXT FROM Payment_Cursor INTO @Line&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;WHILE @@FETCH_STATUS = 0&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;BEGIN&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp;IF @dummy = '' SET @dummy = @Line ELSE SET @dummy = @dummy + ' ' + @Line&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp;FETCH NEXT FROM Payment_Cursor INTO @Line&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;END&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;CLOSE &amp;nbsp;Payment_Cursor&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;DEALLOCATE &amp;nbsp;Payment_Cursor&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;RETURN @Dummy&lt;/p&gt;
&lt;p&gt;END&lt;/p&gt;
&lt;p&gt;Because applying this kind of functions for a couple of hundred lines is very slow on SQL server.&lt;/p&gt;
&lt;p&gt;thanks&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#48808</link><pubDate>Mon, 22 Apr 2013 14:49:25 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:48808</guid><dc:creator>Adam Machanic</dc:creator><description>&lt;p&gt;@MarcVB:&lt;/p&gt;
&lt;p&gt;The &amp;quot;aggregation&amp;quot; in your case is string concatenation. And although SQL Server does not include a string concat aggregate, we can fake it very easily by creating an XML document that lacks tags:&lt;/p&gt;
&lt;p&gt;SELECT&lt;/p&gt;
&lt;p&gt;	x + ' ' AS [text()]&lt;/p&gt;
&lt;p&gt;FROM&lt;/p&gt;
&lt;p&gt;(&lt;/p&gt;
&lt;p&gt;	SELECT 'a'&lt;/p&gt;
&lt;p&gt;	UNION &amp;nbsp;ALL&lt;/p&gt;
&lt;p&gt;	SELECT 'b'&lt;/p&gt;
&lt;p&gt;) AS y (x)&lt;/p&gt;
&lt;p&gt;FOR XML PATH('')&lt;/p&gt;
&lt;p&gt;In conjunction with STUFF and a few other tricks you can better control the output. Google around for more information.&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#49150</link><pubDate>Tue, 21 May 2013 19:40:27 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:49150</guid><dc:creator>Laura</dc:creator><description>&lt;p&gt;@Adam:&lt;/p&gt;
&lt;p&gt;I was able to improve the performance of simply selecting the value returned from my scalar udf by changing it to a table udf. But what if I need to then join to another table based on the value returned from my udf? This appears to still cause a major performance hit if I try to do more than simply select the value from the udf, and try to actually use it in my table join criteria. Does your work around only help with selecting the data and if I need to use it in the table join criteria I will still face the performance woe's of udf's?&lt;/p&gt;
&lt;p&gt;Thanks for your ariticle. &amp;nbsp;Very helpful.&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#49154</link><pubDate>Tue, 21 May 2013 20:44:53 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:49154</guid><dc:creator>Laura</dc:creator><description>&lt;p&gt;Adam,&lt;/p&gt;
&lt;p&gt;Correction, I am seeing a performance improvement even when using the udf table function in my join criteria. &amp;nbsp;I just realized the same query went from 3:41 to 1:31 by changing the function from scalar to table. Didn't realize this earlier since it it still taking over a minute and had not actually timed it yet.&lt;/p&gt;
</description></item><item><title>re: Scalar functions, inlining, and performance: An entertaining title for a boring post</title><link>http://www2.sqlblog.com/blogs/adam_machanic/archive/2006/08/04/scalar-functions-inlining-and-performance-an-entertaining-title-for-a-boring-post.aspx#49652</link><pubDate>Thu, 13 Jun 2013 07:39:54 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:49652</guid><dc:creator>Xia</dc:creator><description>&lt;p&gt;It's really appreciable article.it improved the query performance&lt;/p&gt;
&lt;p&gt;thanks!&lt;/p&gt;
</description></item></channel></rss>