<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://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>Search results matching tag 'UDF'</title><link>http://sqlblog.com/search/SearchResults.aspx?o=DateDescending&amp;tag=UDF&amp;orTags=0</link><description>Search results matching tag 'UDF'</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>SQLRally Nordic 2012 – session material</title><link>http://sqlblog.com/blogs/hugo_kornelis/archive/2012/10/05/sqlrally-nordic-2012-session-material.aspx</link><pubDate>Fri, 05 Oct 2012 16:49:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:45456</guid><dc:creator>Hugo Kornelis</dc:creator><description>&lt;p&gt;As some of you might know, I have been to &lt;a href="http://www.sqlpass.org/sqlrally/2012/nordic/"&gt;SQLRally Nordic 2012&lt;/a&gt; in Copenhagen earlier this week. I was able to attend many interesting sessions, I had a great time catching up with old friends and meeting new people, and I was allowed to present a session myself.&lt;/p&gt;  &lt;p&gt;I understand that the PowerPoint slides and demo code I used in my session will be made available through the SQLRally website – but I don’t know how long it will take the probably very busy volunteers to do so. And I promised my attendees to make them available through my blog as well.&lt;/p&gt;  &lt;p&gt;So, here they are, for everyone to download, see, and play with. Though, in all honesty, I expect people who were not present at my session to get very little out of this material.&lt;/p&gt;  &lt;p&gt;(I’m not sure, but I *think* that the SQLRally organization will also make a recording of my session available. If that is true, then once it’s up the slides and demo code should make a lot more sense to anyone who is able to view the recording).&lt;/p&gt;  &lt;p&gt;I know I’ve said it before, but I can’t repeat this often enough – thanks to everyone involved with the organization of SQLRally for creating a truly wonderful event, and thanks to all the attendees who took the time and energy to come to my session and listen to me.&lt;/p&gt;</description></item><item><title>T-SQL User-Defined Functions: the good, the bad, and the ugly (part 4)</title><link>http://sqlblog.com/blogs/hugo_kornelis/archive/2012/08/24/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-4.aspx</link><pubDate>Fri, 24 Aug 2012 21:07:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:44860</guid><dc:creator>Hugo Kornelis</dc:creator><description>&lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;Scalar user-defined functions are bad for performance. I already showed that for T-SQL scalar user-defined functions &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:12pt;"&gt;&lt;a href="http://sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff" face="Times New Roman"&gt;without&lt;/font&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt; and &lt;/font&gt;&lt;/span&gt;&lt;a href="http://sqlblog.com/blogs/hugo_kornelis/archive/2012/05/26/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-2.aspx"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff" face="Times New Roman"&gt;with&lt;/font&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt; data access, and for &lt;/font&gt;&lt;/span&gt;&lt;a href="http://sqlblog.com/blogs/hugo_kornelis/archive/2012/06/29/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-3.aspx"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff" face="Times New Roman"&gt;most CLR scalar user-defined functions without data access&lt;/font&gt;&lt;/span&gt;&lt;/a&gt;&lt;/font&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;, and in this blog post I will show that CLR scalar user-defined functions with data access fit into that picture.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;b&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:13.5pt;"&gt;First attempt&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;Sticking to my simplistic example of finding the triple of an integer value by reading it from a pre-populated lookup table and following the standard recommendations and templates that Microsoft publishes for CLR scalar table-valued functions, my first attempt for this function looked like this:&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;[Microsoft.SqlServer.Server.&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlFunction&lt;/font&gt;&lt;/span&gt;(DataAccess=&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;DataAccessKind&lt;/font&gt;&lt;/span&gt;.Read,&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;IsDeterministic=&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;true&lt;/font&gt;&lt;/span&gt;,SystemDataAccess=&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SystemDataAccessKind&lt;/font&gt;&lt;/span&gt;.None,IsPrecise=&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;true&lt;/font&gt;&lt;/span&gt;)]&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;public&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;static&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlInt32&lt;/font&gt;&lt;/span&gt; CLRTripFromTbl1(&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlInt32&lt;/font&gt;&lt;/span&gt; Value)&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;{&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlInt32&lt;/font&gt;&lt;/span&gt; Result;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;using&lt;/font&gt;&lt;/span&gt; (&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlConnection&lt;/font&gt;&lt;/span&gt; conn = &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlConnection&lt;/font&gt;&lt;/span&gt;(&lt;span style="color:;"&gt;&lt;font color="#a31515"&gt;"context connection=true"&lt;/font&gt;&lt;/span&gt;))&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;{&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;conn.Open();&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlCommand&lt;/font&gt;&lt;/span&gt; cmd = &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlCommand&lt;/font&gt;&lt;/span&gt;(&lt;span style="color:;"&gt;&lt;font color="#a31515"&gt;"SELECT Triple FROM dbo.Triples WHERE Value = @Value;"&lt;/font&gt;&lt;/span&gt;, conn);&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;cmd.Parameters.Add(&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlParameter&lt;/font&gt;&lt;/span&gt;(&lt;span style="color:;"&gt;&lt;font color="#a31515"&gt;"Value"&lt;/font&gt;&lt;/span&gt;, Value));&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;Result = (&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlInt32&lt;/font&gt;&lt;/span&gt;)((&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;int&lt;/font&gt;&lt;/span&gt;)cmd.ExecuteScalar());&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;return&lt;/font&gt;&lt;/span&gt; Result;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;Below is the code I used to test the performance of this version in comparison to the T-SQL scalar user-defined function and the version without UDF I used earlier (in part 2 – where I also explain why the query without UDF is more complex than needed). Note that I added a WHERE clause that limits the test to just 10% of the table (one million rows instead of all ten million) to limit the testing time.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;SET&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;STATISTICS&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;TIME&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;ON&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;" color="#008000"&gt;-- T-SQL UDF&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;SELECT&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#ff00ff"&gt;MAX&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;TripFromTbl&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;DataVal&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;))&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt; &lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;MaxTriple&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;FROM&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;LargeTable&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;WHERE&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;KeyVal&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;&amp;lt;=&lt;/font&gt;&lt;/span&gt; 1000000&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;" color="#008000"&gt;-- CLR UDF&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;SELECT&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#ff00ff"&gt;MAX&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;CLRTripFromTbl1&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;DataVal&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;))&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt; &lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;MaxTriple&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;FROM&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;LargeTable&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;WHERE&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;KeyVal&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;&amp;lt;=&lt;/font&gt;&lt;/span&gt; 1000000&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;" color="#008000"&gt;-- No UDF&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;WITH&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;TheTrips&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;AS&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;SELECT &lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;SELECT&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;t&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;Triple&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;FROM&lt;/font&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Triples&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt; &lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;t&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;WHERE&lt;/font&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;t&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Value&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;=&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;l&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;DataVal&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;)&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt; &lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;TheTrip&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;FROM&lt;/font&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;LargeTable&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt; &lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;l&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;WHERE&lt;/font&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;l&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;KeyVal&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;&amp;lt;=&lt;/font&gt;&lt;/span&gt; 1000000&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;)&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;SELECT&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#ff00ff"&gt;MAX&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;TheTrip&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;)&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt; &lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;MaxTriple&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;FROM&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;TheTrips&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;SET&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;STATISTICS&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;TIME&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;OFF&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;If you run this and check the CPU and elapsed time, you’ll find a huge (and very nasty) surprise. I expected the CLR version to be about as bad as the T-SQL user-defined function with data access, but I was wrong – it is more than ten times slower! For processing just these one million rows (with the data already in cache), the version without UDF took about 0.2 seconds elapsed, 0.8 seconds CPU (the CPU time being higher than the elapsed time is because parallelism); the version with T-SQL UDF took about 26 seconds (elapsed and CPU – no parallelism in this execution plan) – and the CLR version took over 350 seconds! This is also the reason why I added the WHERE clause; without it, the CLR version would probably have taken more than half an hour to finish.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;For completeness sake, I also checked the execution plan and the SET STATISTICS IO output of the CLR versions. All the issues I saw with the T-SQL scalar user-defined function with data access plague the CLR versions as well – no indication at all of the cost of the function in the execution plan, and no report of the amount of I/O in the SET STATISTICS IO output (though it is still visible in a profiler trace). Also, like the T-SQL scalar function with or without data access (but unlike the CLR scalar function without data access), you will never get a parallel plan on a query that invokes a CLR scalar user-defined function with data access. And, unlike a T-SQL UDF with data access, even the estimated execution plan will not show any hint of the data access performed in the function.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;b&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:13.5pt;"&gt;The parallel loopback misunderstanding&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;When I discussed these results with some people I consider more knowledgeable on CLR than myself, someone told me that by using a loopback connection instead of the context connection, it is possible to forgo the DataAccessKind.Read switch, which impedes parallelism.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;Well – if I could give a price for the worst advice ever (okay, it later turned out to be the most misunderstood advice ever – more about that later), this would definitely qualify. I created and tested this UDF:&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;[Microsoft.SqlServer.Server.&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlFunction&lt;/font&gt;&lt;/span&gt;(DataAccess = &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;DataAccessKind&lt;/font&gt;&lt;/span&gt;.Read,&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;IsDeterministic = &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;true&lt;/font&gt;&lt;/span&gt;, SystemDataAccess = &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SystemDataAccessKind&lt;/font&gt;&lt;/span&gt;.None, IsPrecise = &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;true&lt;/font&gt;&lt;/span&gt;)]&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;public&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;static&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlInt32&lt;/font&gt;&lt;/span&gt; CLRTripFromTbl2(&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlInt32&lt;/font&gt;&lt;/span&gt; Value)&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;{&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlInt32&lt;/font&gt;&lt;/span&gt; Result;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;using&lt;/font&gt;&lt;/span&gt; (&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlConnection&lt;/font&gt;&lt;/span&gt; conn = &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlConnection&lt;/font&gt;&lt;/span&gt;(&lt;span style="color:;"&gt;&lt;font color="#a31515"&gt;@"Data Source=perFact\SQL2012; Initial Catalog=udf; Integrated Security=True;"&lt;/font&gt;&lt;/span&gt;))&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;{&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;conn.Open();&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlCommand&lt;/font&gt;&lt;/span&gt; cmd = &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlCommand&lt;/font&gt;&lt;/span&gt;(&lt;span style="color:;"&gt;&lt;font color="#a31515"&gt;"SELECT Triple FROM dbo.Triples WHERE Value = @Value;"&lt;/font&gt;&lt;/span&gt;, conn);&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;cmd.Parameters.Add(&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlParameter&lt;/font&gt;&lt;/span&gt;(&lt;span style="color:;"&gt;&lt;font color="#a31515"&gt;"Value"&lt;/font&gt;&lt;/span&gt;, Value));&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;Result = (&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlInt32&lt;/font&gt;&lt;/span&gt;)((&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;int&lt;/font&gt;&lt;/span&gt;)cmd.ExecuteScalar());&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;return&lt;/font&gt;&lt;/span&gt; Result;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;You may note that the DataAccessKind.Read switch is still present. That’s because, when testing this with DataAccessKind.None, I got a run-time error. After restoring the DataAccessKind.Read switch, I at least got this code to run – but not very fast! When testing this UDF, I had to reduce the amount of rows to process even further – processing just 1% of the table (a hundred thousand rows) took 168 seconds elapsed (though “only” 54 seconds CPU), so the one million row test I used earlier would have taken almost half an hour, and if I had used the full testset, the test would have run for almost 5 hours! That makes this test with the loopback connection almost five times slower than the one with the context connection – which was already about ten times slower than the T-SQL UDF (which, in turn, was well over a hundred times slower than the version without UDF).&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;It later turned out that I had misunderstood the advice. For the record, this advice was given by &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:12pt;"&gt;&lt;a href="http://sqlblog.com/blogs/adam_machanic/default.aspx"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff" face="Times New Roman"&gt;Adam Machanic&lt;/font&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;, who is a true crack at everything CLR. It was not his advice that was bad; it was my ability to understand what he meant. He later clarified that his suggestion was to move the data access to a separate thread. He even pointed me to the library he created for this – see &lt;/font&gt;&lt;/span&gt;&lt;a href="http://sqlblog.com/files/folders/beta/entry29021.aspx"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff" face="Times New Roman"&gt;this link&lt;/font&gt;&lt;/span&gt;&lt;/a&gt;&lt;/font&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;I have to be honest. I looked at the code. And looked at it again. Then I looked at the sample code. And again. And yet another time. And then I admitted defeat. My understanding of CLR is simply too limited to enable me to adapt me “triples” example to use this technique, so I will not be able to include it in performance comparisons. If anyone is willing to give it a try, then by all means do – and please let me know the results!&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;b&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:13.5pt;"&gt;Cache as cache can&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;Another tip, also from Adam (and this time not misunderstood by me!), is to avoid multiple lookups of the same value by implementing a cache in the CLR code. This is very easy to do for anyone with a fair bit of CLR skills – and I think that I have proven that you can even replace those CLR skills with a judicious amount of Google (or Bing). Here is how my code (after several failed attempts) eventually looked:&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;" color="#008000"&gt;// This is the initial size of the cache; it will grow when needed.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;private&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;const&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;int&lt;/font&gt;&lt;/span&gt; InitialSize = 40;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;public&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;static&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;TripleCache&lt;/font&gt;&lt;/span&gt; tc = &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;TripleCache&lt;/font&gt;&lt;/span&gt;(InitialSize);&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;[Microsoft.SqlServer.Server.&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlFunction&lt;/font&gt;&lt;/span&gt;(DataAccess = &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;DataAccessKind&lt;/font&gt;&lt;/span&gt;.Read,&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;IsDeterministic = &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;true&lt;/font&gt;&lt;/span&gt;, SystemDataAccess = &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SystemDataAccessKind&lt;/font&gt;&lt;/span&gt;.None, IsPrecise = &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;true&lt;/font&gt;&lt;/span&gt;)]&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;public&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;static&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlInt32&lt;/font&gt;&lt;/span&gt; CLRTripFromTbl3(&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlInt32&lt;/font&gt;&lt;/span&gt; Value)&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;{&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlInt32&lt;/font&gt;&lt;/span&gt; Result = tc[Value].Value;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;return&lt;/font&gt;&lt;/span&gt; Result;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;public&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;class&lt;/font&gt;&lt;/span&gt; &lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#2b91af"&gt;TripleCache&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;{&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008000"&gt;// Dictionary to contain the cache.&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;static&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;Dictionary&lt;/font&gt;&lt;/span&gt;&amp;lt;&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlInt32&lt;/font&gt;&lt;/span&gt;, &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;WeakReference&lt;/font&gt;&lt;/span&gt;&amp;gt; _cache;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt;&lt;/span&gt; TripleCache(&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;int&lt;/font&gt;&lt;/span&gt; count)&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;{&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;_cache = &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;Dictionary&lt;/font&gt;&lt;/span&gt;&amp;lt;&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlInt32&lt;/font&gt;&lt;/span&gt;, &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;WeakReference&lt;/font&gt;&lt;/span&gt;&amp;gt;();&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008000"&gt;// Access a data object from the cache.&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;Triple&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;this&lt;/font&gt;&lt;/span&gt;[&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlInt32&lt;/font&gt;&lt;/span&gt; index]&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;{&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#0000ff"&gt;get&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;{&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;Triple&lt;/font&gt;&lt;/span&gt; tr;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008000"&gt;// Try to read the triple from the cache.&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#0000ff"&gt;try&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;{&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;tr = _cache[index].Target &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;as&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;Triple&lt;/font&gt;&lt;/span&gt;;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#0000ff"&gt;catch&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;{&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008000"&gt;// Triple not yet in cache; read from table and add to cache&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;tr = &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;Triple&lt;/font&gt;&lt;/span&gt;(index);&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;_cache.Add(index, &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;WeakReference&lt;/font&gt;&lt;/span&gt;(tr));&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;if&lt;/font&gt;&lt;/span&gt; (tr == &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;null&lt;/font&gt;&lt;/span&gt;)&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008000"&gt;// Triple has been in cache but was evicted - read from table again and renew cache&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;tr = &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;Triple&lt;/font&gt;&lt;/span&gt;(index);&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;_cache[index] = &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;WeakReference&lt;/font&gt;&lt;/span&gt;(tr);&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;return&lt;/font&gt;&lt;/span&gt; tr;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;" color="#008000"&gt;// This class reads the triple value from the table&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;public&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;class&lt;/font&gt;&lt;/span&gt; &lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#2b91af"&gt;Triple&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;{&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;private&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlInt32&lt;/font&gt;&lt;/span&gt; _triple;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt;&lt;/span&gt; Triple(&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlInt32&lt;/font&gt;&lt;/span&gt; single)&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;{&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;using&lt;/font&gt;&lt;/span&gt; (&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlConnection&lt;/font&gt;&lt;/span&gt; conn = &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlConnection&lt;/font&gt;&lt;/span&gt;(&lt;span style="color:;"&gt;&lt;font color="#a31515"&gt;"context connection=true"&lt;/font&gt;&lt;/span&gt;))&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;{&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;conn.Open();&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlCommand&lt;/font&gt;&lt;/span&gt; cmd = &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlCommand&lt;/font&gt;&lt;/span&gt;(&lt;span style="color:;"&gt;&lt;font color="#a31515"&gt;"SELECT Triple FROM dbo.Triples WHERE Value = @Value;"&lt;/font&gt;&lt;/span&gt;, conn);&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;cmd.Parameters.Add(&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlParameter&lt;/font&gt;&lt;/span&gt;(&lt;span style="color:;"&gt;&lt;font color="#a31515"&gt;"Value"&lt;/font&gt;&lt;/span&gt;, single));&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;_triple = (&lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlInt32&lt;/font&gt;&lt;/span&gt;)((&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;int&lt;/font&gt;&lt;/span&gt;)cmd.ExecuteScalar());&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008000"&gt;// Simple property.&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#2b91af"&gt;SqlInt32&lt;/font&gt;&lt;/span&gt; Value&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;{&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#0000ff"&gt;get&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;{&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;return&lt;/font&gt;&lt;/span&gt; _triple;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;With the test data used so far, this method really performs very well. The test with one million rows finished in 3.5 seconds (again, both elapsed and CPU – we still do not get a parallel plan for this query). That is a lot faster than all other UDF versions tested so far – though still not even near the performance we can get by not using a UDF at all.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;To be fair, the test data is *very* nice for this specific method. The lookup table used holds two hundred thousand rows, but the sample data is skewed to use only ten distinct values. So this last CLR version reads those ten values into its cache and then keeps serving them from cache over and over again. While using only a minimal amount of memory for its cache, it reduces the amount of actual I/O to only ten queries. In short, my test case was the ideal use case for the caching technique.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;I wanted to know how the cached version holds up when the circumstances are less ideal, so I also executed this query:&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;SELECT&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#ff00ff"&gt;MAX&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;CLRTripFromTbl3&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;KeyVal&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;%&lt;/font&gt;&lt;/span&gt; 90000&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;))&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt; &lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;MaxTriple&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;FROM&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;LargeTable&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;WHERE&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;KeyVal&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;&amp;lt;=&lt;/font&gt;&lt;/span&gt; 1000000&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;By using “KeyVal % 90000” instead of “DataVal”, I now ensure that 90,000 different rows from the lookup table are accessed, each 11 or 12 times. This means that, even with the cache, a lot of database queries are still needed – though still than without the cache. The results were devastating! The above query ran for almost seven MINUTES (415 seconds, to be exact, using 405 seconds CPU time). At this point, I started to think that maybe the cache didn’t work properly with this amount of entries. The WeakReference class I used is supposed to allow allocations to be freed in order to free up some memory; maybe that was happening so aggressively that there cached data was evicted every time before it could be reused? To test this, I ran the same query another time; now the elapsed time was down to “only” 326 seconds, almost 100 seconds less. So it looks like the cache is still working, saving the need to fetch the same data multiple times – but the overhead for creating and using the cache costs more than the saved database calls; the simple CLR UDF that just calls the database every time is lots faster!&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;(To be fair, all methods see some performance loss when tested with the equivalent of the above query, just not as much. The T-SQL UDF takes 27 seconds, the CLR UDF takes 364 seconds, and the version with inlined logic instead of a UDF now takes almost 0.5 seconds – slower, but still comfortably running rings around all the competitors!)&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;Now obviously, the two tests I used are both extreme cases. In many cases where you might consider implementing a CLR UDF with data access, the amount of distinct rows read will be somewhere between ten and ninety thousand – so you really should run your own tests, on your own system and with your own typical data distribution.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;There are also a few other caveats you should consider before deciding to implement this caching technique for your scalar CLR user-defined functions:&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;text-indent:-18pt;margin:0cm 0cm 0pt 36pt;mso-list:l0 level1 lfo1;" class="MsoListParagraphCxSpFirst" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;mso-fareast-font-family:symbol;mso-bidi-font-family:symbol;"&gt;&lt;span style="mso-list:ignore;"&gt;&lt;font face="Symbol"&gt;&lt;font style="font-size:12pt;"&gt;·&lt;/font&gt;&lt;/font&gt;&lt;span style="line-height:normal;font-family:;"&gt;&lt;font style="font-size:7pt;" face="Times New Roman"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;The cache persists across query executions. So if I execute the same query again, I will get an even better performance, because all the data is still available in the CLR cache. If you run a profiler trace while executing this query a second time, you will see no data being read at all. For performance, this can be a good thing – but beware! It also means that you will have to find a way to deal with stale data. For triples, this is not really an issue. But there are also many lookup tables where the data may change. Like, for instance, a table with exchange ratios for foreign currencies. How would your bank do if, even after entering the new exchange ratios for the failing European currencies, lookup queries still return the old values?&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;text-indent:-18pt;margin:0cm 0cm 0pt 36pt;mso-list:l0 level1 lfo1;" class="MsoListParagraphCxSpLast" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;mso-fareast-font-family:symbol;mso-bidi-font-family:symbol;"&gt;&lt;span style="mso-list:ignore;"&gt;&lt;font face="Symbol"&gt;&lt;font style="font-size:12pt;"&gt;·&lt;/font&gt;&lt;/font&gt;&lt;span style="line-height:normal;font-family:;"&gt;&lt;font style="font-size:7pt;" face="Times New Roman"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;The assembly that implements the cache has to be loaded with PERMISSION_SET = UNSAFE. Your DBA might not like that. And for good reasons. If you consider implementing techniques such as this cache, or Adam’s parallelizer, be aware that these techniques trade safety for speed. You may crash your AppDomain, which may cause the loss of all data in the cache or even kill executing queries. You may have to implement code to detect and repair this – if performance is really important, and you really have to use a UDF with data access, you could consider accepting the risks and downsides. But I won’t. Even after discussing this with Adam, I still don’t feel that I really understand the risks – and if I don’t understand the risks, then there is no way I will allow the code to run on my machine (except in test environments).&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;b&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:13.5pt;"&gt;Bottom line&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;Out of the box, CLR user-defined functions will not perform well when data access is involved. They can be up to ten times slower than their T-SQL counterparts, and those were already pretty bad.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;Previously, we have seen that CLR user-defined functions can offer a good performance improvement when heavy computations are involved. So, what to do if your required functionality includes a combination of data retrieval and heavy computations? My recommendation would be to try to separate the two parts. Retrieve all the data in the T-SQL query, without using any user-defined data, then pass the required arguments to a CLR user-defined function without data access to do the computation. Or do the computation inline – even with heavy computations, inlining the logic sometimes is still faster!&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;One way to speed up a CLR user-defined function with data access is to implement a cache, to prevent unnecessary roundtrips to the server. This does require you to think very carefully about the risk of serving stale data, and you may also find it very hard to convince your DBA to allow you to load an unsafe assembly – but when implemented successfully, it can result in a tremendous boost in performance, especially if the typical use of the function involves repeatedly reading a small set of data. But beware – when the number of distinct rows that are used (and will hence be read in cache) increases, and the number of cache hits decreases, caching can easily become a bane rather than a boon, because of the overhead involved.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="mso-ansi-language:en-us;"&gt;&lt;font face="Times New Roman"&gt;&lt;font style="font-size:12pt;"&gt;This concludes my discussion of scalar user-defined functions. In the next episodes of this series, we will look at table-valued user-defined functions. And we will find that those come in different flavors, with VERY different performance characteristics. Stay tuned!&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;</description></item><item><title>T-SQL User-Defined Functions: the good, the bad, and the ugly (part 3)</title><link>http://sqlblog.com/blogs/hugo_kornelis/archive/2012/06/29/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-3.aspx</link><pubDate>Fri, 29 Jun 2012 18:44:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:44146</guid><dc:creator>Hugo Kornelis</dc:creator><description>&lt;p&gt;I showed why T-SQL scalar user-defined functions are bad for performance in two previous posts. In this post, I will show that CLR scalar user-defined functions are bad as well (though not always quite as bad as T-SQL scalar user-defined functions).&lt;/p&gt;
  
&lt;p&gt;I will admit that I had not really planned to cover CLR in this series. But shortly after publishing &lt;a href="http://sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx"&gt;the first part&lt;/a&gt;, I received an email from &lt;a href="http://sqlblog.com/blogs/adam_machanic/default.aspx"&gt;Adam Machanic&lt;/a&gt;, which basically said that I should make clear that the information in that post does not apply to CLR functions. So I dutifully added a comment to that post, and included a similar disclaimer in &lt;a href="http://sqlblog.com/blogs/hugo_kornelis/archive/2012/05/26/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-2.aspx"&gt;the second part&lt;/a&gt; – but I also planned to run some tests, for it is my strong belief that you should never take anything for granted, no matter how knowledgeable the person telling you it is. And if I am running those tests anyway, why not share my findings with you?&lt;/p&gt;
  
&lt;font size="+1"&gt;
&lt;p&gt;&lt;b&gt;No data access&lt;/b&gt;&lt;/p&gt;
&lt;/font&gt;
  
&lt;p&gt;The first part of this post focused on scalar user-defined functions (UDFs) that don’t include any data access; only computations, string handling, etc. I used a very unrepresentative example: multiplying an integer value by 3. Here is a CLR equivalent (using C#) of that function:&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;[Microsoft.SqlServer.Server.&lt;span style="color:#2B91AF;"&gt;SqlFunction&lt;/span&gt;(DataAccess=&lt;span style="color:#2B91AF;"&gt;DataAccessKind&lt;/span&gt;.None,&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;IsDeterministic=&lt;span style="color:blue;"&gt;true&lt;/span&gt;,SystemDataAccess=&lt;span style="color:#2B91AF;"&gt;SystemDataAccessKind&lt;/span&gt;.None,IsPrecise=&lt;span style="color:blue;"&gt;true&lt;/span&gt;)]&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;public&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color:#2B91AF;"&gt;SqlInt32&lt;/span&gt; CLRTriple(&lt;span style="color:#2B91AF;"&gt;SqlInt32&lt;/span&gt;
Value)&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;{&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;return&lt;/span&gt;
Value * 3;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;}&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;In order to test the performance of this version of the function and compare it to the alternatives (T-SQL function and inline logic), I ran this batch against the LargeTable table, which is still populated with ten million rows.&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;SET&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:blue;"&gt;STATISTICS&lt;/span&gt; &lt;span style="color:blue;"&gt;TIME&lt;/span&gt; &lt;span style="color:blue;"&gt;ON&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:fuchsia;"&gt;MAX&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:teal;"&gt;dbo&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;Triple&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:teal;"&gt;DataVal&lt;/span&gt;&lt;span style="color:gray;"&gt;))&lt;/span&gt; &lt;span style="color:blue;"&gt;AS&lt;/span&gt; &lt;span style="color:teal;"&gt;MaxTriple&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;FROM&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:teal;"&gt;dbo&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;LargeTable&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:fuchsia;"&gt;MAX&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:teal;"&gt;dbo&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;CLRTriple&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:teal;"&gt;DataVal&lt;/span&gt;&lt;span style="color:gray;"&gt;))&lt;/span&gt; &lt;span style="color:blue;"&gt;AS&lt;/span&gt; &lt;span style="color:teal;"&gt;MaxTriple&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;FROM&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:teal;"&gt;dbo&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;LargeTable&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:fuchsia;"&gt;MAX&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;3 &lt;span style="color:gray;"&gt;*&lt;/span&gt; &lt;span style="color:teal;"&gt;DataVal&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;span style="color:blue;"&gt;AS&lt;/span&gt; &lt;span style="color:teal;"&gt;MaxTriple&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;FROM&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:teal;"&gt;dbo&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;LargeTable&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;SET&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:blue;"&gt;STATISTICS&lt;/span&gt; &lt;span style="color:blue;"&gt;TIME&lt;/span&gt; &lt;span style="color:blue;"&gt;OFF&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;The execution plans immediately show a huge advantage of CLR UDFs over their T-SQL counterparts: they don’t inhibit parallelism!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sqlblog.com/blogs/hugo_kornelis/image_45A22725.png"&gt;&lt;img src="http://sqlblog.com/blogs/hugo_kornelis/image_thumb_16040899.png" style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" alt="image" border="0" height="393" width="1012"&gt;&lt;/a&gt;&lt;/p&gt;
  
&lt;p&gt;But other than that, this execution plan is doing pretty much the same as all other execution plans in this series of blog posts: lying until it is black in its face. Because that is what execution plans do when UDFs are involved, and CLR functions are no exception. For the real comparison, I ran the same batch without outputting the execution plan (to eliminate their overhead) and checked the amount of CPU time used and the time elapsed. For the T-SQL function, CPU time was 35,709 ms, and elapsed was 38,621 ms. The CLR version used less CPU time, only 13,072 ms – a huge saving. And thanks to the parallelism, the saving in elapsed time was even more: only 2,071 ms left.&lt;/p&gt;
  
&lt;p&gt;However, the version that avoids any UDF and instead places the logic inline still wins, with a CPU time of only 5,741 ms, and an elapsed time of 768 ms – almost three times as fast as the CLR version, and over 45 times as fast as the T-SQL version.&lt;/p&gt;
  
&lt;p&gt;Given the total lack of complexity in the UDF, the huge performance difference between the CLR and T-SQL versions of the function cannot be explained by CLR code being faster than T-SQL code (though that is definitely the case – see below). The only explanation I can come up with is that invoking a T-SQL involves a lot more overhead than invoking a CLR function. However, the CLR function is still not entirely free of overhead, otherwise it should have performed about the same as the version with the logic inline.&lt;/p&gt;
  
&lt;font size="+1"&gt;
&lt;p&gt;&lt;b&gt;Complex calculations&lt;/b&gt;&lt;/p&gt;
&lt;/font&gt;
  
&lt;p&gt;Up until now, the conclusion is that, even though scalar CLR functions definitely perform much better than scalar T-SQL functions, the best performance is still achieved by placing the logic inline. But there are exceptions to this rule. As already mentioned above, CLR code executes a lot faster than T-SQL code – so if you have a function that performs extremely complicated logic, it may well be worth your time to do a thorough comparison between inlined logic and a CLR function.&lt;/p&gt;
  
&lt;p&gt;Because I wanted to use a realistic example, I decided to dig up the code I wrote many years ago, when I needed to compute the distance between points on the earth on SQL Server 2005 (before spatial data types were introduced). The formula used to calculate the distance between two points, given their latitude and longitude, is as follows:&lt;/p&gt;
  
&lt;p&gt;&lt;a href="http://sqlblog.com/blogs/hugo_kornelis/image_52531DD5.png"&gt;&lt;img src="http://sqlblog.com/blogs/hugo_kornelis/image_thumb_11449E71.png" style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" alt="image" border="0" height="75" width="654"&gt;&lt;/a&gt;&lt;/p&gt;
  
&lt;p&gt;This formula assumes that the input and result are all measured in radians. The data set I used for testing has locations with latitude and longitude measured in degrees, and I prefer to see the distance reported in kilometers, so we’ll have to add some unit conversions to get the correct results.&lt;/p&gt;
  
&lt;p&gt;I first implemented this calculation as a T-SQL scalar user-defined function:&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;CREATE&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:blue;"&gt;FUNCTION&lt;/span&gt; &lt;span style="color:teal;"&gt;dbo&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;Distance&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:gray;mso-ansi-language:EN-US;"&gt;(&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:teal;mso-ansi-language:EN-US;"&gt;@Lat1&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:blue;"&gt;FLOAT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:teal;"&gt;@Lon1&lt;/span&gt;
&lt;span style="color:blue;"&gt;FLOAT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:teal;"&gt;@Lat2&lt;/span&gt;
&lt;span style="color:blue;"&gt;FLOAT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:teal;"&gt;@Lon2&lt;/span&gt;
&lt;span style="color:blue;"&gt;FLOAT&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;RETURNS&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:blue;"&gt;FLOAT&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;AS&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;BEGIN&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:gray;mso-ansi-language:EN-US;"&gt;;&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;DECLARE&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:teal;"&gt;@Lat1R&lt;/span&gt; &lt;span style="color:blue;"&gt;FLOAT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:teal;"&gt;@Lon1R&lt;/span&gt; &lt;span style="color:blue;"&gt;FLOAT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:teal;"&gt;@Lat2R&lt;/span&gt; &lt;span style="color:blue;"&gt;FLOAT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:teal;"&gt;@Lon2R&lt;/span&gt; &lt;span style="color:blue;"&gt;FLOAT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:teal;"&gt;@DistR&lt;/span&gt; &lt;span style="color:blue;"&gt;FLOAT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:teal;"&gt;@Dist&lt;/span&gt; &lt;span style="color:blue;"&gt;FLOAT&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:green;mso-ansi-language:EN-US;"&gt;-- Convert from degrees to radians&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;SET&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:teal;"&gt;@Lat1R&lt;/span&gt; &lt;span style="color:gray;"&gt;=&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;RADIANS&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:teal;"&gt;@Lat1&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;SET&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:teal;"&gt;@Lon1R&lt;/span&gt; &lt;span style="color:gray;"&gt;=&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;RADIANS&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:teal;"&gt;@Lon1&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;SET&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:teal;"&gt;@Lat2R&lt;/span&gt; &lt;span style="color:gray;"&gt;=&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;RADIANS&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:teal;"&gt;@Lat2&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;SET&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:teal;"&gt;@Lon2R&lt;/span&gt; &lt;span style="color:gray;"&gt;=&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;RADIANS&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:teal;"&gt;@Lon2&lt;/span&gt;&lt;span style="color:gray;"&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:green;mso-ansi-language:EN-US;"&gt;-- Calculate the distance (in radians)&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;SET&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:teal;"&gt;@DistR&lt;/span&gt; &lt;span style="color:gray;"&gt;=&lt;/span&gt; 2 &lt;span style="color:gray;"&gt;*&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;ASIN&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;SQRT&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;POWER&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;SIN&lt;/span&gt;&lt;span style="color:gray;"&gt;((&lt;/span&gt;&lt;span style="color:teal;"&gt;@Lat1R&lt;/span&gt; &lt;span style="color:gray;"&gt;-&lt;/span&gt; &lt;span style="color:teal;"&gt;@Lat2R&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;span style="color:gray;"&gt;/&lt;/span&gt; 2&lt;span style="color:gray;"&gt;),&lt;/span&gt; 2&lt;span style="color:gray;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:gray;"&gt;+&lt;/span&gt;&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;COS&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:teal;"&gt;@Lat1R&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;span style="color:gray;"&gt;*&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;COS&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:teal;"&gt;@Lat2R&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;span style="color:gray;"&gt;*&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;POWER&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;SIN&lt;/span&gt;&lt;span style="color:gray;"&gt;((&lt;/span&gt;&lt;span style="color:teal;"&gt;@Lon1R&lt;/span&gt; &lt;span style="color:gray;"&gt;-&lt;/span&gt; &lt;span style="color:teal;"&gt;@Lon2R&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;span style="color:gray;"&gt;/&lt;/span&gt; 2&lt;span style="color:gray;"&gt;),&lt;/span&gt; 2&lt;span style="color:gray;"&gt;))));&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:green;mso-ansi-language:EN-US;"&gt;-- Convert distance from radians to kilometers&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:green;mso-ansi-language:EN-US;"&gt;-- Explanation: Distance in radians = distance in nautical miles * (pi /
(180 * 60)), so&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:green;mso-ansi-language:EN-US;"&gt;--&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;distance in
nautical miles = distance in radians * 180 * 60 / pi&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:green;mso-ansi-language:EN-US;"&gt;--&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;One nautical mile
is 1.852 kilometers, so&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:green;mso-ansi-language:EN-US;"&gt;--&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;distance in km
= (distance in radians * 180 * 60 / pi) * 1.852&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:green;mso-ansi-language:EN-US;"&gt;--&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;And since 180 * 60
* 1.852 = 20001.6, this can be simplified to&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:green;mso-ansi-language:EN-US;"&gt;--&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;distance in km
= distance in radians * 20001.6 / pi&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;SET&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:teal;"&gt;@Dist&lt;/span&gt; &lt;span style="color:gray;"&gt;=&lt;/span&gt; &lt;span style="color:teal;"&gt;@DistR&lt;/span&gt; &lt;span style="color:gray;"&gt;*&lt;/span&gt; 20001.6 &lt;span style="color:gray;"&gt;/&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;PI&lt;/span&gt;&lt;span style="color:gray;"&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;RETURN&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:teal;"&gt;@Dist&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;END&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:gray;mso-ansi-language:EN-US;"&gt;;&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;GO&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;To test its performance, I used a table that Microsoft included as part of the product samples with SQL Server 2005 (I believe these samples are still available on &lt;a href="http://www.microsoft.com/en-us/download/details.aspx?id=10679"&gt;CodePlex&lt;/a&gt;). This table includes geographic data for almost 22,993 places in the United States of America. For my test, I chose to calculate the distance between each pair of places in the state Texas; since there are 1,276 places in this state, the function will be invoked 1,276 * 1,276 = 1,628,176 times. To make sure that my test is not influenced by the time to send results to the client or render them on my screen, I included the MAX function, so that only a single number is sent to the client.&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;SET&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:blue;"&gt;STATISTICS&lt;/span&gt; &lt;span style="color:blue;"&gt;TIME&lt;/span&gt; &lt;span style="color:blue;"&gt;ON&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:fuchsia;"&gt;MAX&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:teal;"&gt;dbo&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;Distance&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:teal;"&gt;a&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;Lat&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; &lt;span style="color:teal;"&gt;a&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;Lon&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; &lt;span style="color:teal;"&gt;b&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;Lat&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; &lt;span style="color:teal;"&gt;b&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;Lon&lt;/span&gt;&lt;span style="color:gray;"&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;FROM&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:teal;"&gt;dbo&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;Place&lt;/span&gt; &lt;span style="color:blue;"&gt;AS&lt;/span&gt; &lt;span style="color:teal;"&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:gray;mso-ansi-language:EN-US;"&gt;CROSS&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:gray;"&gt;JOIN&lt;/span&gt; &lt;span style="color:teal;"&gt;dbo&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;Place&lt;/span&gt; &lt;span style="color:blue;"&gt;AS&lt;/span&gt; &lt;span style="color:teal;"&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;WHERE&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:teal;"&gt;a&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:blue;"&gt;State&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:gray;"&gt;=&lt;/span&gt; &lt;span style="color:red;"&gt;'TX'&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:gray;mso-ansi-language:EN-US;"&gt;AND&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:teal;"&gt;b&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:blue;"&gt;State&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:gray;"&gt;=&lt;/span&gt; &lt;span style="color:red;"&gt;'TX'&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;SET&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:blue;"&gt;STATISTICS&lt;/span&gt; &lt;span style="color:blue;"&gt;TIME&lt;/span&gt; &lt;span style="color:blue;"&gt;OFF&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;This query took over half a minute to finish. 31,449 ms CPU time, and 34,392 ms elapsed time. The time per execution of the user-defined function is decent enough (only about 21 ms), but because of the sheer number of executions, the total running time is still pretty long.&lt;/p&gt;
&lt;p&gt;Before moving to the CLR version of the distance calculation, let’s first try what happens if I avoid the user-defined function and instead place the calculation inline. After all, this proved to be a useful technique in the first part of this series. For this query, the downside of inlining the logic is that it results in a pretty much unmaintainable query – but it does indeed result in an impressive performance boost!&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;SET&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:blue;"&gt;STATISTICS&lt;/span&gt; &lt;span style="color:blue;"&gt;TIME&lt;/span&gt; &lt;span style="color:blue;"&gt;ON&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:fuchsia;"&gt;MAX&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;2 &lt;span style="color:gray;"&gt;*&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;ASIN&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;SQRT&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;POWER&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;SIN&lt;/span&gt;&lt;span style="color:gray;"&gt;((&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;RADIANS&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:teal;"&gt;a&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;Lat&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;span style="color:gray;"&gt;-&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;RADIANS&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:teal;"&gt;b&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;Lat&lt;/span&gt;&lt;span style="color:gray;"&gt;))&lt;/span&gt; &lt;span style="color:gray;"&gt;/&lt;/span&gt; 2&lt;span style="color:gray;"&gt;),&lt;/span&gt; 2&lt;span style="color:gray;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:gray;"&gt;+&lt;/span&gt;&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;COS&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;RADIANS&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:teal;"&gt;a&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;Lat&lt;/span&gt;&lt;span style="color:gray;"&gt;))&lt;/span&gt; &lt;span style="color:gray;"&gt;*&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;COS&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;RADIANS&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:teal;"&gt;b&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;Lat&lt;/span&gt;&lt;span style="color:gray;"&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:gray;"&gt;*&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;POWER&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;SIN&lt;/span&gt;&lt;span style="color:gray;"&gt;((&lt;/span&gt;&lt;span style="color:fuchsia;"&gt;RADIANS&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:teal;"&gt;a&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;Lon&lt;/span&gt;&lt;span style="color:gray;"&gt;)&lt;/span&gt; &lt;span style="color:gray;"&gt;-&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;RADIANS&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:teal;"&gt;b&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;Lon&lt;/span&gt;&lt;span style="color:gray;"&gt;))&lt;/span&gt; &lt;span style="color:gray;"&gt;/&lt;/span&gt; 2&lt;span style="color:gray;"&gt;),&lt;/span&gt; 2&lt;span style="color:gray;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:gray;"&gt;)))&lt;/span&gt; &lt;span style="color:gray;"&gt;*&lt;/span&gt; 20001.6 &lt;span style="color:gray;"&gt;/&lt;/span&gt; &lt;span style="color:fuchsia;"&gt;PI&lt;/span&gt;&lt;span style="color:gray;"&gt;())&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;FROM&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:teal;"&gt;dbo&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;Place&lt;/span&gt; &lt;span style="color:blue;"&gt;AS&lt;/span&gt; &lt;span style="color:teal;"&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:gray;mso-ansi-language:EN-US;"&gt;CROSS&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:gray;"&gt;JOIN&lt;/span&gt; &lt;span style="color:teal;"&gt;dbo&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;Place&lt;/span&gt; &lt;span style="color:blue;"&gt;AS&lt;/span&gt; &lt;span style="color:teal;"&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;WHERE&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:teal;"&gt;a&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:blue;"&gt;State&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:gray;"&gt;=&lt;/span&gt; &lt;span style="color:red;"&gt;'TX'&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:gray;mso-ansi-language:EN-US;"&gt;AND&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:teal;"&gt;b&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:blue;"&gt;State&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:gray;"&gt;=&lt;/span&gt; &lt;span style="color:red;"&gt;'TX'&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;SET&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:blue;"&gt;STATISTICS&lt;/span&gt; &lt;span style="color:blue;"&gt;TIME&lt;/span&gt; &lt;span style="color:blue;"&gt;OFF&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;The CPU time is way down, from over 31 seconds to less than 8: 7,956 ms. Elapsed time is down even more, because the optimizer can parallelize this plan – only 1,557 ms! That is a very nice reduction, but still no reason to stop. As the amount of data increases, even this version can run into performance problems. For instance, when I simply omitted the WHERE clause to make SQL Server find the maximum distance between any of the almost 23,000 places in the database (involving over 500 million distance computations), the query ran for almost five minutes, with an elapsed time of 282,580 ms, and a CPU time of 2,155,995 ms! That’s a good reason to try to optimize this further.&lt;/p&gt;
&lt;p&gt;And that brings us back to the subject of this post: CLR scalar user-defined functions. I have implemented the same distance calculation as a C# function:&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;using&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; System;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;using&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; System.Data;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;using&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; System.Data.SqlClient;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;using&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; System.Data.SqlTypes;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;using&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; Microsoft.SqlServer.Server;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;public&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:blue;"&gt;partial&lt;/span&gt; &lt;span style="color:blue;"&gt;class&lt;/span&gt; &lt;span style="color:#2B91AF;"&gt;UserDefinedFunctions&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;{&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;[Microsoft.SqlServer.Server.&lt;span style="color:#2B91AF;"&gt;SqlFunction&lt;/span&gt;(IsDeterministic = &lt;span style="color:blue;"&gt;true&lt;/span&gt;)]&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color:#2B91AF;"&gt;SqlDouble&lt;/span&gt;
DistCLR&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;(&lt;span style="color:#2B91AF;"&gt;SqlDouble&lt;/span&gt;
Lat1, &lt;span style="color:#2B91AF;"&gt;SqlDouble&lt;/span&gt; Lon1,&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#2B91AF;"&gt;SqlDouble&lt;/span&gt;
Lat2, &lt;span style="color:#2B91AF;"&gt;SqlDouble&lt;/span&gt; Lon2)&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:green;"&gt;// This is
just a wrapper for the T-SQL interface.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:green;"&gt;// Call the
function that does the real work.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;double&lt;/span&gt;
Dist = SpatialDist(Lat1.Value, Lon1.Value,&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Lat2.Value,
Lon2.Value);&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;return&lt;/span&gt; &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2B91AF;"&gt;SqlDouble&lt;/span&gt;(Dist);&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color:blue;"&gt;double&lt;/span&gt;
SpatialDist&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;(&lt;span style="color:blue;"&gt;double&lt;/span&gt;
Lat1, &lt;span style="color:blue;"&gt;double&lt;/span&gt; Lon1,&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;double&lt;/span&gt;
Lat2, &lt;span style="color:blue;"&gt;double&lt;/span&gt; Lon2)&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:green;"&gt;// Convert
degrees to radians&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;double&lt;/span&gt;
Lat1R = Lat1 * &lt;span style="color:#2B91AF;"&gt;Math&lt;/span&gt;.PI / 180;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;double&lt;/span&gt;
Lon1R = Lon1 * &lt;span style="color:#2B91AF;"&gt;Math&lt;/span&gt;.PI / 180;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;double&lt;/span&gt;
Lat2R = Lat2 * &lt;span style="color:#2B91AF;"&gt;Math&lt;/span&gt;.PI / 180;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;double&lt;/span&gt;
Lon2R = Lon2 * &lt;span style="color:#2B91AF;"&gt;Math&lt;/span&gt;.PI / 180;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:green;"&gt;// Calculate
distance in radians&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;double&lt;/span&gt;
DistR =&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;2 * &lt;span style="color:#2B91AF;"&gt;Math&lt;/span&gt;.Asin(&lt;span style="color:#2B91AF;"&gt;Math&lt;/span&gt;.Sqrt(&lt;span style="color:#2B91AF;"&gt;Math&lt;/span&gt;.Pow(&lt;span style="color:#2B91AF;"&gt;Math&lt;/span&gt;.Sin((Lat1R - Lat2R) / 2), 2)&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;+ (&lt;span style="color:#2B91AF;"&gt;Math&lt;/span&gt;.Cos(Lat1R)
* &lt;span style="color:#2B91AF;"&gt;Math&lt;/span&gt;.Cos(Lat2R)&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;* &lt;span style="color:#2B91AF;"&gt;Math&lt;/span&gt;.Pow(&lt;span style="color:#2B91AF;"&gt;Math&lt;/span&gt;.Sin((Lon1R - Lon2R) / 2), 2))));&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:green;"&gt;// Convert
from radians to kilometers&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;double&lt;/span&gt;
Dist = DistR * 20001.6 / &lt;span style="color:#2B91AF;"&gt;Math&lt;/span&gt;.PI;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;return&lt;/span&gt;
Dist;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;}&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;The SQL for testing this is almost identical to the SQL for testing the T-SQL scalar user-defined function – only the function name is changed.&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;SET&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:blue;"&gt;STATISTICS&lt;/span&gt; &lt;span style="color:blue;"&gt;TIME&lt;/span&gt; &lt;span style="color:blue;"&gt;ON&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;SELECT&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:fuchsia;"&gt;MAX&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:teal;"&gt;dbo&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;DistCLR&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:teal;"&gt;a&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;Lat&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; &lt;span style="color:teal;"&gt;a&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;Lon&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; &lt;span style="color:teal;"&gt;b&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;Lat&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt; &lt;span style="color:teal;"&gt;b&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;Lon&lt;/span&gt;&lt;span style="color:gray;"&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;FROM&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:teal;"&gt;dbo&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;Place&lt;/span&gt; &lt;span style="color:blue;"&gt;AS&lt;/span&gt; &lt;span style="color:teal;"&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:gray;mso-ansi-language:EN-US;"&gt;CROSS&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:gray;"&gt;JOIN&lt;/span&gt; &lt;span style="color:teal;"&gt;dbo&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:teal;"&gt;Place&lt;/span&gt; &lt;span style="color:blue;"&gt;AS&lt;/span&gt; &lt;span style="color:teal;"&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;WHERE&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:teal;"&gt;a&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:blue;"&gt;State&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:gray;"&gt;=&lt;/span&gt; &lt;span style="color:red;"&gt;'TX'&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:gray;mso-ansi-language:EN-US;"&gt;AND&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:teal;"&gt;b&lt;/span&gt;&lt;span style="color:gray;"&gt;.&lt;/span&gt;&lt;span style="color:blue;"&gt;State&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:gray;"&gt;=&lt;/span&gt; &lt;span style="color:red;"&gt;'TX'&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal" style="mso-layout-grid-align:none;text-autospace:none;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;mso-ansi-language:EN-US;"&gt;SET&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;mso-ansi-language:EN-US;"&gt; &lt;span style="color:blue;"&gt;STATISTICS&lt;/span&gt; &lt;span style="color:blue;"&gt;TIME&lt;/span&gt; &lt;span style="color:blue;"&gt;OFF&lt;/span&gt;&lt;span style="color:gray;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;The results show that this version is even faster than the T-SQL query with the computation inline, although only marginally. The CPU time is 7,798 ms, and the elapsed time is 1,459 ms. This means that the distance of the maximum calculation across all the places in the United States should also become slightly faster, and indeed it does – the elapsed time is 257,081 ms, and the CPU time is 2,010,774 ms. Still very slow, so if I had to tackle this problem for a real client I would start looking for other optimizations – but in the context of this blog post, I only wanted to show that using CLR scalar user-defined functions for complex computations can sometimes perform better than trying to do those computations in T-SQL only.&lt;/p&gt;
&lt;font size="+1"&gt;
&lt;p&gt;&lt;b&gt;Bottom line&lt;/b&gt;&lt;/p&gt;
&lt;/font&gt;
  
&lt;p&gt;In the first two parts of this series, I have shown that T-SQL scalar user-defined functions, both with and without data access, are terrible for performance. In this part, I have looked at CLR scalar user-defined functions without data access. As a rule of thumb, those are bad for performance too – but unlike their T-SQL counterparts, when complex calculations are involved, the performance hit of having to invoke the function for each individual row processed by a query can sometimes be offset by the performance gain by moving the complex calculation to the faster CLR environment. If you consider embedding a complex calculation in a CLR scalar user-defined function, I recommend extended performance testing of both the UDF and the equivalent query with the same logic in inlined T-SQL.&lt;/p&gt;
  
&lt;p&gt;Of course, performance is not always the only deciding factor. Maybe you already have the CLR function because it’s also called from your .Net code; in that case, you can save a lot of development and maintenance effort by reusing that component in your T-SQL code. Maybe you need to do something that is only possible from CLR code (like calling a web service – as long as you are aware that this will have a REALLY detrimental effect on performance!), or something that is simply so much easier in CLR code (like using standard methods for regular expression pattern matching, that would be extremely complicated to code in T-SQL code). Or maybe your UDF will only be called five times per day, and never in a query that processes more than a single row. At the end of the day, &lt;b&gt;&lt;i&gt;you&lt;/i&gt;&lt;/b&gt; will have to make your decision, based on all the factors that are relevant in your specific scenario.&lt;/p&gt;
  
&lt;p&gt;The next part of this series will look at CLR scalar user-defined functions with data access; after that, we can finally start to cover the various kinds of table-valued user-defined functions available in SQL Server (the good and the ugly).&lt;/p&gt;</description></item><item><title>T-SQL User-Defined Functions: the good, the bad, and the ugly (part 2)</title><link>http://sqlblog.com/blogs/hugo_kornelis/archive/2012/05/26/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-2.aspx</link><pubDate>Sat, 26 May 2012 14:56:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43590</guid><dc:creator>Hugo Kornelis</dc:creator><description>&lt;p&gt;In &lt;a href="http://sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx"&gt;a previous blog post&lt;/a&gt;, I demonstrated just how much you can hurt your performance by encapsulating expressions and computations in a user-defined function (UDF). I focused on scalar functions that didn’t include any data access. In this post, I will complete the discussion on scalar UDFs by covering the effect of data access in a scalar UDF. Note that, like the previous post, this all applies to T-SQL user-defined functions only. SQL Server also supports CLR user-defined functions (written in a .Net language like C# or VB.Net); those are not in the scope of this blog post.&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Data access&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;So far, I have been looking at an example of a UDF that only does a calculation. A very simple calculation, but this UDF stood model for other, probably more complex UDFs that manipulate their arguments without reading additional data. However, in a database system, these are not the most common UDFs – in my experience, a majority of the UDFs in any database will read some data from some tables. Are these UDFs that do data access as bad as those that don’t? Let’s find out. In the code below, I create a new UDF that doesn’t compute the triple value, but instead looks it up in a table that holds the triple values of all numbers between -100,000 and 100,000. This mimics what I think is a rather common data access pattern in a UDF: reading a single row from a lookup table, based on the primary key value. &lt;/p&gt;    &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;CREATE&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;TABLE&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;Triples&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;&lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#008080"&gt;Value&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;int&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#808080"&gt;NOT&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#808080"&gt;NULL&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;PRIMARY&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;KEY&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;,&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Triple&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;int&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;NOT&lt;/font&gt;&lt;/span&gt; &lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;NULL);&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;" color="#008000"&gt;-- Triples of numbers 1 - 100,000&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;WITH&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;Digits&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;AS &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;SELECT&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;d&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;FROM &lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;VALUES &lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;0&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;),(&lt;/font&gt;&lt;/span&gt;1&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;),(&lt;/font&gt;&lt;/span&gt;2&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;),(&lt;/font&gt;&lt;/span&gt;3&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;),(&lt;/font&gt;&lt;/span&gt;4&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;),(&lt;/font&gt;&lt;/span&gt;5&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;),(&lt;/font&gt;&lt;/span&gt;6&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;),(&lt;/font&gt;&lt;/span&gt;7&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;),(&lt;/font&gt;&lt;/span&gt;8&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;),(&lt;/font&gt;&lt;/span&gt;9&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;))&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;d&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;d&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;))&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;INSERT&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;INTO&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Triples&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt; &lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Value&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;,&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Triple&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;)&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;SELECT&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; 10000 &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;*&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;tt&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;d&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;+&lt;/font&gt;&lt;/span&gt; 1000 &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;*&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;st&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;d&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;+&lt;/font&gt;&lt;/span&gt; 100 &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;*&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;h&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;d&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;+&lt;/font&gt;&lt;/span&gt; 10 &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;*&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;t&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;d&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;+&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;s&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;d&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;+&lt;/font&gt;&lt;/span&gt; 1&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;,&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt;10000 &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;*&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;tt&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;d&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;+&lt;/font&gt;&lt;/span&gt; 1000 &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;*&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;st&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;d&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;+&lt;/font&gt;&lt;/span&gt; 100 &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;*&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;h&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;d&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;+&lt;/font&gt;&lt;/span&gt; 10 &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;*&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;t&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;d&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;+&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;s&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;d&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;+&lt;/font&gt;&lt;/span&gt; 1&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;)&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;*&lt;/font&gt;&lt;/span&gt; 3&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;FROM&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Digits&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;s&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;,&lt;/font&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Digits&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;t&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;,&lt;/font&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Digits&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;h&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;,&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Digits&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;st&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;,&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Digits&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;tt&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;" color="#008000"&gt;-- Triples of numbers -1 - -100,000&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;INSERT&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;INTO&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Triples&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt; &lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Value&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;,&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Triple&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;)&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;SELECT&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;-&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Value&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;,&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;-&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;Triple&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;FROM&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Triples&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;" color="#008000"&gt;-- And add the number 0&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;INSERT&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;INTO&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Triples&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt; &lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Value&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;,&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Triple&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;)&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;VALUES &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt;0&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;,&lt;/font&gt;&lt;/span&gt; 0&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;);&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;" color="#0000ff"&gt;go&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;CREATE&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;FUNCTION&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;TripFromTbl&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;@Input&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;int&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;)&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;RETURNS&lt;/font&gt;&lt;/span&gt; &lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#0000ff"&gt;int&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;WITH&lt;/font&gt;&lt;/span&gt; &lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#0000ff"&gt;SCHEMABINDING&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;" color="#0000ff"&gt;AS&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;BEGIN&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;DECLARE&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;@Result&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;int&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;SELECT&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;@Result&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;=&lt;/font&gt;&lt;/span&gt; &lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;Triple&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;FROM&lt;/font&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;Triples&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;WHERE&lt;/font&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Value&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;=&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;@Input&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;RETURN&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;@Result&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt; &lt;font face="Consolas"&gt;&lt;span style="text-align:left;list-style-type:disc;font-family:;color:;mso-ansi-language:en-us;mso-fareast-font-family:'Times New Roman';mso-fareast-language:nl;mso-bidi-language:ar-sa;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;END&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="text-align:left;list-style-type:disc;font-family:;color:;mso-ansi-language:en-us;mso-fareast-font-family:'Times New Roman';mso-fareast-language:nl;mso-bidi-language:ar-sa;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;  &lt;p&gt;To compare the performance of this UDF versus the inline equivalent, I would normally replace the UDF call with a correlated subquery. But my test query has embedded the call to the UDF in an aggregate function, and SQL Server apparently doesn’t like to have a subquery as the argument to an aggregate function – so I have to make the code a bit more complex to work around that limitation. (I normally would have rewritten the query as a join, but that would also be an optimization, and in this case I wanted to stay as close as possible to the original and see what the optimizer does – the CTE is the direct replacement of &lt;font face="Consolas"&gt;SELECT dbo.TripFromTbl(DataVal) FROM dbo.LargeTable;&lt;/font&gt;).&lt;/p&gt;    &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;SELECT&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span&gt;&lt;font color="#ff00ff"&gt;MAX&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#008080"&gt;TripFromTbl&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#008080"&gt;DataVal&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#808080"&gt;))&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt; &lt;/font&gt;&lt;span&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;MaxTriple&lt;/font&gt;&lt;/span&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;&lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;FROM&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#008080"&gt;LargeTable&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;WITH&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;TheTrips&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;AS&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;SELECT &lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;SELECT&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;t&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;Triple&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;FROM&lt;/font&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Triples&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt; &lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;t&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;WHERE&lt;/font&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;t&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Value&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;=&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;l&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;DataVal&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;)&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt; &lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;TheTrip&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;FROM&lt;/font&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;LargeTable&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;l&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;)&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;SELECT&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#ff00ff"&gt;MAX&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;TheTrip&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;)&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt; &lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;MaxTriple&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt; &lt;font face="Consolas"&gt;&lt;span style="text-align:left;list-style-type:disc;font-family:;color:;mso-ansi-language:en-us;mso-fareast-font-family:'Times New Roman';mso-fareast-language:nl;mso-bidi-language:ar-sa;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;FROM&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="text-align:left;list-style-type:disc;font-family:;mso-ansi-language:en-us;mso-fareast-font-family:'Times New Roman';mso-fareast-language:nl;mso-bidi-language:ar-sa;"&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="text-align:left;mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="text-align:left;color:;"&gt;&lt;font color="#008080"&gt;TheTrips&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="text-align:left;color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;  &lt;p&gt;Let’s first take a look at the execution plans. More lies? Yup! But in this case, the worst culprit is not the execution plan; we’ll see far worse lies in a bit. But let’s not get ahead of ourselves. I selected the two queries, hit the execute button, and after waiting 7½ minutes, I was able to make this screenshot of the execution plans for the queries above:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/hugo_kornelis/image_5187E11B.png"&gt;&lt;img src="http://sqlblog.com/blogs/hugo_kornelis/image_thumb_693F1881.png" style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" alt="image" border="0" height="346" width="1310"&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The plan for the query without UDF is pretty smart – though not optimal. The optimizer has reversed the order in which tables are accessed. It will first read the Triples table, and if you drill down in the properties of the Clustered Index Seek operator, you will see that it has used its knowledge of the CHECK constraint on the DataVal column that will be used in the join iterator – only rows with Value &amp;gt;=1 and &amp;lt; 10 are read. In the parallel part of the plan, the large table is then read entirely and joined to the rows from the Triples table. A hash match join iterator is used, so that the table is read only once, at the cost of some CPU and memory overhead. The iterator uses right outer join semantics, to ensure that rows from the LargeTable are not lost if a value is missing from the Triples table – we know this is not the case, but the optimizer doesn’t. The results are then aggregated (to find the maximum triple in each thread), and then those maximums are aggregated again to find the maximum between all threads.&lt;/p&gt;  &lt;p&gt;This is not an optimal plan. The value coming from the Triples table will be the same for all rows with the same DataVal in LargeTable, so instead of reading them all, then aggregating them back to a single row per Triple value, it would suffice to read only a single row to check for the existence of a particular DataValue in LargeTable. But that is apparently not a transformation that the optimizer is currently able to make – yet? (Are you reading, &lt;a href="http://blogs.msdn.com/b/conor_cunningham_msft/"&gt;Conor&lt;/a&gt;?)&lt;/p&gt;  &lt;p&gt;The execution plan for the query with UDF is a lot simpler. It is, in fact, exactly the same as it was for the earlier versions of the UDF. And even though SQL Server cannot take advantage of parallelism for this query, it is still considered cheaper than the version without UDF: 44% of the total batch. Lies, of course – to see how bad the lies are in this case, I disabled the actual execution plan option and added the &lt;font face="Consolas"&gt;SET STATISTICS TIME ON&lt;/font&gt; statement, but in this case I also added a &lt;font face="Consolas"&gt;SET STATISTICS IO ON&lt;/font&gt; statement to see how much I/O the two alternatives use. I then clicked the Execute button and waited for another 7½ minutes.&lt;/p&gt;  &lt;p&gt;The output of the statistics IO is clear. For the version without UDF, there are 21,394 logical reads on the LargeTable (slightly more than its 21,088 pages; the parallelism causes a few pages to be read more than once), 2 reads on the Triples table, and it also mentions two WorkTables, but they have no logical reads. Pretty good. But the version with UDF again appears to win hands down: it uses 21,088 logical reads on LargeTable (obviously) – and nothing more! According to this output, the query with UDF manages to read all those triple values from the Triples table without ever accessing it! More lies? You bet! In this case, the lie is that the statistics io output never includes any I/O that is done within a UDF. So if I rewrote the UDF to do twenty table scans on a table with a billion rows each time it is called, the statistics io output would still insist that that table wasn’t read at all – though the execution time of the UDF would tell a quite different story. To really see the data access done by a UDF, you’ll have to have a profiler trace running while executing the query that invokes it. If you repeat this query with an active profiler trace that includes the relevant events, you’ll get an enormous lot of output – so please don’t do this on a production box! In the collected output, you’ll see a block that starts with an SP:Starting event (the function is invoked), then has two sets of SP:StmtStarting and SP:StmtCompleted events (the two executable statements in the function), and finally an SP:Completed event (the function has ended) – and this block is then repeated ten million times! In the &lt;i&gt;Reads&lt;/i&gt; column of SP:StmtCompleted, you can also see the number of logical reads: only 2 per execution of the function, since all it does is a lookup on the clustered index key in a small table. And the best news is that you don’t even have to do any of the math yourself, because when the query finally finishes, the SQL:StmtCompleted event will show you the total I/O in the relevant columns – in this case the &lt;i&gt;Reads&lt;/i&gt; column, which shows a grand total of 20,021,088 reads. That’s 20 million for the UDF (2 reads in each of the 10 million executions) that STATISTICS IO doesn’t report, plus the 21,088 reads on the LargeTable table that STATISTICS IO does report.&lt;/p&gt;  &lt;p&gt;(Note: If you need to do serious data collection for trouble-shooting a potential UDF issue, I recommend only including the SQL:StmtCompleted event with the Reads column and not including SP:StmtStarted, SP:StmtCompleted, SP:Starting, and SP:Completed. That makes the trace much more lightweight, and still gives you the information you need. Only include the other events if you need to drill down to the level of statements within the UDF, and if you do, then only run tests on very small numbers of rows).&lt;/p&gt;  &lt;p&gt;So, time for the ultimate measure (and the only measure that we can get a truthful report on without having to go outside Management Studio): the actual execution times. For the version without UDF, the CPU time is 7021 ms, and the elapsed time is 1406 ms. And the version with UDF took 488,470 ms CPU and 494,533 ms elapsed – a 70x increase in CPU, and even a 350x increase in elapsed time, from 1½ seconds to over 8 minutes! Do you now understand why database consultants have trouble suppressing their smile when their new customer turns out to have littered the database code with UDFs? It’s the ultimate low-hanging fruit!&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Lies, damned lies, and estimates&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;The original version of the UDF, that didn’t use data access, already profited enormously from a rewrite that capitalized on the fact that there are only 10 distinct values for the argument with which it is called. This version would profit even more – rewrite the query to the one below, and the execution time is down to 3838 ms CPU, 3871 ms elapsed – still no parallelism anywhere in the plan, but nevertheless a great improvement.&lt;/p&gt;    &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;SELECT&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span&gt;&lt;font color="#ff00ff"&gt;MAX&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#008080"&gt;TripFromTbl&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#008080"&gt;DataVal&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#808080"&gt;))&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt; &lt;/font&gt;&lt;span&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;MaxTriple&lt;/font&gt;&lt;/span&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;&lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;FROM&lt;span&gt;&amp;nbsp; &lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;SELECT&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;DISTINCT&lt;/font&gt;&lt;/span&gt; &lt;/font&gt;&lt;span&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;DataVal&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;FROM&lt;/font&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;LargeTable&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;)&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;d&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p&gt;The UDF does not contain any elements that would make it non deterministic, and indeed, the IsDeterministic property of this UDF is 1. So that is not the reason why the optimizer would not consider this transformation. So what is the reason? This time, it is not a zero-cost assumption for the UDF – take a look at the simple query below and the associated estimated execution plan:&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;SELECT&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;TripFromTbl&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;3&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;);&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/hugo_kornelis/image_75CCC59D.png"&gt;&lt;img src="http://sqlblog.com/blogs/hugo_kornelis/image_thumb_54D952F6.png" style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" alt="image" border="0" height="330" width="493"&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;If you drill down the properties of the iterator, you will see that the estimated subtree cost for the UDF is 0,0032831. Not entirely accurate – it is the same cost I get for a query that directly does the corresponding select from the Triples table, so the overhead for invoking the UDF is not taken into account; but I think we can safely assume that this overhead is minimal in relation to the I/O cost anyway.&lt;/p&gt;  &lt;p&gt;Since the UDF is executed once from the main query, I would expect the estimated operator cost for the Compute Scalar in the query to be about the same number – but it isn’t. This cost shows up as only 0,0000001. According to the query plan, the iterator that invokes the UDF costs less than 1/100&lt;sup&gt;th&lt;/sup&gt; percent of that UDF itself. Clearly, in this case the optimizer does know something about the cost of the UDF, but still refuses to take this into account. “Yes, I know that this UDF is not free, but for the purpose of optimization, I’ll assume it is anyway”. Why? I have no idea – but I did &lt;a href="https://connect.microsoft.com/SQLServer/feedback/details/744019/dont-ignore-the-cost-of-user-defined-functions"&gt;report it as a bug on the Connect website&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&lt;b&gt;The remedy&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;In the previous post, I told you to avoid using scalar UDFs that don’t do any data access. In this post, I showed that the performance hit of scalar UDFs that do include data access is even far worse, so you won’t be surprised when I tell you that you should avoid these as well, maybe even more – with the same exceptions (a SET statement without subquery, so that the UDF is processed only once; maybe a SELECT statement on a small table in a part of your application that is not on a time-critical path).&lt;/p&gt;  &lt;p&gt;If the logic in the UDF is relatively simple, you can often replace the call to the UDF with a simple subquery, possibly with a CASE expression somewhere to mimic an IF … ELSE in the UDF. This is not possible if the UDF is called inside an aggregate function, as we saw at the start of this post. And if the UDF is complex, replacing it with a single subquery may also prove to be too hard, or it results in a monster query that nobody will be able to maintain, or that due to its sheer complexity manage to throw off the optimizer. In cases like that, the best advice is to bite the bullet and do the work of completely rewriting the original query without using the UDF. Depending on the complexity of the problem, this may eventually result in breaking up the query in multiple steps, using temporary tables or table variables to store intermediate results. Not my first choice, but almost bound to perform better than any solution that calls a scalar user-defined function with data access.&lt;/p&gt;  &lt;p&gt;For the query I used in this blog post, my actual workaround would not be the complicated construction above, but a simple rewrite with a join:&lt;/p&gt;    &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;SELECT&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;&lt;font color="#ff00ff"&gt;MAX&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#008080"&gt;t&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#008080"&gt;Triple&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#808080"&gt;)&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/font&gt;&lt;span&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;MaxTriple&lt;/font&gt;&lt;/span&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;&lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;FROM&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#008080"&gt;LargeTable&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&lt;/font&gt;&lt;span&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;l&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#808080"&gt;&lt;font style="font-size:9.5pt;"&gt;INNER&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;JOIN&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Triples&lt;/font&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;t&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;ON&lt;/font&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;t&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Value&lt;/font&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;=&lt;/font&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;l&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;DataVal&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;This rewrite has several advantages over the original version. The most obvious is that it’s much easier to understand and maintain. A second advantage is that the execution plan does not have to take into account the possibility that values may be missing from the dbo.Triples table (and indeed, the only difference between the plan for this query and the plan for the first query without UDF is that the Hash Match join iterator has been changed from outer to inner join). This also gives the optimizer more options to find better plans – it doesn’t in this case and both queries perform equal, but if you add a nonclustered index on the DataVal column in the LargeTable, this query will benefit the most.&lt;/p&gt;  &lt;p&gt;Or, if performance is really important, I would use a version that forces the optimizer to first do a DISTINCT on all the DataVal values before joining to the Triples table – less obvious to read and maintain, but in this specific case (because there are so few distinct DataVal values and so many rows in LargeTable) it is about 50% faster than the alternative:&lt;/p&gt;    &lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;SELECT&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;&lt;font color="#ff00ff"&gt;MAX&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#008080"&gt;t&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#008080"&gt;Triple&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#808080"&gt;)&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt; &lt;/font&gt;&lt;span&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;MaxTriple&lt;/font&gt;&lt;/span&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;&lt;p style="list-style-type:disc;margin-top:0cm;margin-left:0cm;margin-right:0cm;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size:9.5pt;"&gt;FROM&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span&gt;&lt;font color="#808080"&gt;(&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;SELECT&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;DISTINCT&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#008080"&gt;DataVal&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;FROM&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#008080"&gt;LargeTable&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#808080"&gt;)&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt; &lt;/font&gt;&lt;span&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;l&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;font face="Consolas"&gt;&lt;span style="font-family:;color:;mso-ansi-language:en-us;"&gt;&lt;font color="#808080"&gt;&lt;font style="font-size:9.5pt;"&gt;INNER&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font style="font-size:9.5pt;"&gt; &lt;span style="color:;"&gt;&lt;font color="#808080"&gt;JOIN&lt;/font&gt;&lt;/span&gt; &lt;span style="color:;"&gt;&lt;font color="#008080"&gt;dbo&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Triples&lt;/font&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;AS&lt;/font&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#008080"&gt;t&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p style="list-style-type:disc;margin-top:0cm;text-autospace:;margin-left:0cm;margin-right:0cm;mso-layout-grid-align:none;" class="MsoNormal" align="left"&gt;&lt;span style="font-family:;mso-ansi-language:en-us;"&gt;&lt;font face="Consolas"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;font style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size:9.5pt;"&gt;&lt;span style="color:;"&gt;&lt;font color="#0000ff"&gt;ON&lt;/font&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;t&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;Value&lt;/font&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;=&lt;/font&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;l&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#808080"&gt;.&lt;/font&gt;&lt;/span&gt;&lt;span style="color:;"&gt;&lt;font color="#008080"&gt;DataVal&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="color:;"&gt;&lt;font style="font-size:9.5pt;" color="#808080"&gt;;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;And a completely different way to tackle the performance impact of a scalar UDF with data access is to rewrite it as an inline table-valued function. As already promised in the first part of this series, I will cover this technique and discuss its benefits and drawbacks later.&lt;/p&gt;  &lt;p&gt;&lt;b&gt;What’s next?&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;I have not yet decided on the next part. My original idea was to limit this series to T-SQL user-defined functions (hence the title). But a comment I received by email has made me reconsider this plan; I am now considering the possibility of discussing the effects of CLR user-defined functions as well (though the title of the blog post series would then be slightly incorrect).&lt;/p&gt;  &lt;p&gt;If I do decide to cover CLR functions too, then the next part will be on the scalar variety of CLR functions (or, if you wish, the CLR variety of scalar functions) to wrap up the discussion on scalar functions. If I decide to leave out CLR, my next post will be about multi-statement table-valued functions. In that post, I will show that, while scalar functions may be bad, multi-statement table-valued functions are downright ugly!&lt;/p&gt;</description></item><item><title>T-SQL User-Defined Functions: the good, the bad, and the ugly (part 1)</title><link>http://sqlblog.com/blogs/hugo_kornelis/archive/2012/05/20/t-sql-user-defined-functions-the-good-the-bad-and-the-ugly-part-1.aspx</link><pubDate>Sun, 20 May 2012 14:08:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:43466</guid><dc:creator>Hugo Kornelis</dc:creator><description>&lt;p&gt;So you thought that encapsulating code in user-defined functions for easy reuse is a good idea? Think again!&lt;/p&gt;  &lt;p&gt;SQL Server supports three types of user-defined functions. Only one of them qualifies as good. The other two – well, the title says it all, doesn’t it?&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;font size="3"&gt;The bad: scalar functions&lt;/font&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;A scalar user-defined function (UDF) is very much like a stored procedure, except that it always returns a single value of a predefined data type – and because of that property, it isn’t invoked with an &lt;font face="Consolas"&gt;EXECUTE&lt;/font&gt; statement, but embedded in an expression where the returned value is immediately used. I won’t explain all the basics, but assume that you are either already familiar with the concept, or that you at least have read the description in Books Online. It is allowed to read (but not modify!) table data from within a scalar UDF, but in this blog posts I will focus on scalar UDFs that include computations and other expressions only, without doing any data access.&lt;/p&gt;  &lt;p&gt;The code below defines and then uses a very simple scalar UDF that simply triples the input:&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;CREATE FUNCTION dbo.Triple(@Input int)     &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RETURNS int      &lt;br&gt;AS      &lt;br&gt;BEGIN;      &lt;br&gt;&amp;nbsp; DECLARE @Result int;      &lt;br&gt;&amp;nbsp; SET @Result = @Input * 3;      &lt;br&gt;&amp;nbsp; RETURN @Result;      &lt;br&gt;END;      &lt;br&gt;go      &lt;br&gt;SELECT DataVal, dbo.Triple(DataVal) AS Triple      &lt;br&gt;FROM&amp;nbsp;&amp;nbsp; dbo.LargeTable;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;This example is obviously overly simple – even the most enthusiastic devotee of isolating and reusing code will never bother to define and use a function for something so simple. But if the calculation in the function is actually very complex, it’s easy to see how code that defines the calculation once and then simply invokes the function every time it’s needed is easier to build, understand, debug, and maintain than code that repeats the complex expression at several locations. In traditional programming languages, like C# or VB.Net, it’s easy to see why using functions to encapsulate and reuse common computations is considered a best practice.&lt;/p&gt;  &lt;p&gt;But SQL Server isn’t a traditional programming language. It’s a declarative language, with an optimizer that has been designed to optimize the execution order within queries to make sure that the results are returned as fast as possible – without impacting correctness, of course. And that optimizer simply cannot optimize code that calls scalar UDFs as well as it can optimize code that has the same logic inlined. Let’s first take a look – in order to test the performance, I’ll create a table with 100,000 rows with random values from 1 to 10 in the DataVal column.&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;CREATE TABLE dbo.LargeTable     &lt;br&gt;&amp;nbsp; (KeyVal int NOT NULL PRIMARY KEY,      &lt;br&gt;&amp;nbsp;&amp;nbsp; DataVal int NOT NULL CHECK (DataVal BETWEEN 1 AND 10)      &lt;br&gt;&amp;nbsp; );&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;WITH Digits     &lt;br&gt;AS (SELECT d FROM (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) AS d(d))      &lt;br&gt;INSERT INTO dbo.LargeTable (KeyVal, DataVal)      &lt;br&gt;SELECT 10000 * tt.d + 1000 * st.d      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; + 100 * h.d + 10 * t.d + s.d + 1,      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 10 * RAND(CHECKSUM(NEWID())) + 1      &lt;br&gt;FROM&amp;nbsp;&amp;nbsp; Digits AS s,&amp;nbsp; Digits AS t,&amp;nbsp; Digits AS h,      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Digits AS st, Digits AS tt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;The code may be a bit complex and you may be tempted to write a simple loop to insert 100,000 rows. But that would take a lot more time – the code above runs in less than 1 second on my laptop, whereas a loop takes almost five seconds. When we need more rows (later), this difference becomes even more noticeable.&lt;/p&gt;  &lt;p&gt;&lt;font size="3"&gt;&lt;b&gt;The first test&lt;/b&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Now it’s time to test. Below are two queries. The first query is designed to calculate the triple of each DataVal value in the table. (Note that I added the MAX aggregate to ensure that the actual performance would not be impacted by the overhead of returning 100,000 rows to SSMS and rendering them in the result display). The second query is exactly the same, except that it doesn’t use the scalar UDF, but includes (“inlines”) the actual formula in the query.&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;SELECT MAX(dbo.Triple(DataVal)) AS MaxTriple     &lt;br&gt;FROM&amp;nbsp;&amp;nbsp; dbo.LargeTable;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;SELECT MAX(3 * DataVal) AS MaxTriple     &lt;br&gt;FROM&amp;nbsp;&amp;nbsp; dbo.LargeTable;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;If you select the two queries, activate the option to include the actual execution plan, hit execute, and then switch to the execution plan tab, you may be pretty happy:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/hugo_kornelis/image_4898D706.png"&gt;&lt;img src="http://sqlblog.com/blogs/hugo_kornelis/image_thumb_4B5E8BF9.png" style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" alt="image" border="0" height="261" width="691"&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I must add that I didn’t get these plans all the time. In my first tests, the plans were equal, with the only difference being the actual content (visible only in the Defined Values property) of the Compute Scalar iterator – the arithmetic formula 3 * DataVal vs. invoking dbo.Triple; in those cases both plans were said to have a cost of 50%. In later tests, the plans changed to the above; the call to dbo.Triple is now hidden several levels deep in the Defined Values property of the Stream Aggregate iterator, and though the same work is still done, the first query is now said to be suddenly slightly cheaper than the second. But either way, whether 50% each or 49% vs 51%, the scalar UDF seems to be a very good choice.&lt;/p&gt;  &lt;p&gt;However, you may not be aware that the “Actual Execution Plan” is a dirty rotten liar. Or maybe I should say that the terms “Actual Execution Plan” and “Estimated Execution Plan” are misleading. There is only one execution plan, it gets created when the queries are compiled, and then the queries are executed. The only difference between the “Actual” and the “Estimated” execution plan is that the estimated plan only tells you the estimates for how many rows flow between iterators and how often iterators are executed, and the actual plan adds the actual data for that. But no “actual operator cost” or “actual subtree cost” is added to the corresponding estimated values – and since those costs are the values that the percentages are based on, the percentages displayed in an actual execution plan are still based only on the estimates.&lt;/p&gt;  &lt;p&gt;To get a better idea of the actual query cost, let’s run these queries again – this time without the execution plan, but with the actual duration displayed. You can enable this display with the option Query / Query Options / Advances / SET STATISTICS TIME. Or you can simply add the statement &lt;font face="Consolas"&gt;SET STATISTICS TIME ON;&lt;/font&gt; at the start of the batch (and &lt;font face="Consolas"&gt;SET STATISTICS TIME OFF;&lt;/font&gt; at the end). Now, if you run the queries, you’ll get some extra information returned (in the Text tab of the results pane) that tells you exactly how long the query took (elapsed time) and how much CPU time it used (CPU time). On my laptop, the query that uses the UDF takes 889 ms CPU and 900 ms elapsed, and the query with the logic inlined takes only a fraction of that: 47 ms CPU and 52 ms elapsed! Not 49% versus 51%, but 95% versus 5%.&lt;/p&gt;  &lt;p&gt;&lt;font size="3"&gt;&lt;b&gt;Why?&lt;/b&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;This huge performance difference is caused by the overhead of calling and executing a scalar UDF. The computation of 3 * DataVal in the second query is entirely executed inside an iterator (the Compute Scalar), which is very efficient. The computation of dbo.Triple(DataVal) in the first query is also executed in an iterator (the Stream Aggregate, in this case) – but since this is a call to a separate module, SQL Server will have to invoke this module for each of the 100,000 rows flowing through that iterator. Each of those 100,000 calls introduces some overhead: start up the execution, step through the two executable statements of the function body, and clean up afterwards. Some sources claim that the function text is interpreted (compiled) on each call; I found that this is –at least on SQL Server 2012– not the case; when executing this code with a profiler trace running, only a single cache hit (or cache insert if the function is not in the procedure cache) event is fired.&lt;/p&gt;  &lt;p&gt;This overhead is invisible in the “Actual Execution Plan”, but the execution time and the profiler trace tell a different story. And so does the “Estimated Execution Plan” – if I select the query that uses the function and then request at “Estimated Execution Plan”, I get two execution plans: one for the query that we saw before, and one for the function body, with two iterators that represent the executable statements: a SET with a calculation, and a RETURN.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/hugo_kornelis/image_6A34FFD7.png"&gt;&lt;img src="http://sqlblog.com/blogs/hugo_kornelis/image_thumb_29268073.png" style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" alt="image" border="0" height="317" width="550"&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;But note that, again, the execution plan is lying. First, it implies that the UDF is invoked only once, which is not the case. Second, look at the cost. You may think that the 0% is the effect of rounding down, since a single execution of the function costs so little in relation to the cost of accessing and aggregating 100,000 rows. But if you check the properties of the iterators of the plan for the function, you’ll see that all operator and subtree costs are actually estimated to be exactly 0. This lie is maybe the worst of all – because it’s not just the plan lying to us, it is SQL Server lying to itself. This cost estimate of 0 is actually used by the query optimizer, so all plans it produces are based on the assumption that executing the function is free. As a result, the optimizer will not even consider optimizations it might use if it knew how costly calling a scalar UDF actually is.&lt;/p&gt;  &lt;p&gt;&lt;font size="3"&gt;&lt;b&gt;Determinism&lt;/b&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;You may have wondered why SQL Server even bothers to invoke the UDF 100,000 times. Based on the CHECK constraint, there can never be more than 10 distinct values in the DataVal column – so why doesn’t the optimizer transform the execution plan to first get the distinct values of DataVal, then call the UDF only for those? Surely, that would be more efficient? Yes, it would, as we can easily verify by making that transformation ourselves:&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;SET STATISTICS TIME ON;     &lt;br&gt;SELECT MAX(dbo.Triple(DataVal)) AS MaxTriple      &lt;br&gt;FROM&amp;nbsp; (SELECT DISTINCT DataVal      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM&amp;nbsp;&amp;nbsp; dbo.LargeTable) AS d;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;SELECT MAX(3 * DataVal) AS MaxTriple     &lt;br&gt;FROM&amp;nbsp; (SELECT DISTINCT DataVal      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM&amp;nbsp;&amp;nbsp; dbo.LargeTable) AS d;      &lt;br&gt;SET STATISTICS TIME OFF;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;If you check the returned execution times, you will see that this technique even helps the performance of the query without function, if only by a little bit – 47 ms CPU and 50 ms elapsed on my laptop. For the version with scalar UDF, the saving is significant, as it is now almost as efficient as the version without scalar UDF: 62 ms CPU and 51 ms elapsed.&lt;/p&gt;  &lt;p&gt;So why does the optimizer not make this transformation by itself? There are two reasons for that. The first is that with this version of the UDF, it can’t guarantee that this transformation won’t change result, because of a property called “determinism”. If a function is deterministic, we can be sure that when it is invoked multiple times with the same arguments, it will always return the same result. If a function is not deterministic, it might return different results, even when the same parameters are passed in. Our scalar UDF is not deterministic, as this query shows:&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;SELECT OBJECTPROPERTY(OBJECT_ID('dbo.Triple'), 'IsDeterministic');&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;You can check Books Online for a list of all the requirements a function has to meet to be deterministic. In our case, the only problem is that the UDF is not schemabound, so let’s remedy that:&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;ALTER FUNCTION dbo.Triple(@Input int)     &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RETURNS int      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WITH SCHEMABINDING      &lt;br&gt;AS      &lt;br&gt;BEGIN;      &lt;br&gt;&amp;nbsp; DECLARE @Result int;      &lt;br&gt;&amp;nbsp; SET @Result = @Input * 3;      &lt;br&gt;&amp;nbsp; RETURN @Result;      &lt;br&gt;END;      &lt;br&gt;go      &lt;br&gt;SELECT OBJECTPROPERTY(OBJECT_ID('dbo.Triple'), 'IsDeterministic');&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;The function is now marked as deterministic – but if you rerun the previous tests, you’ll see that this does not affect plan choice for these queries at all! The optimizer still won’t shuffle the plan of the first query to match that of the second, even though they are now (with the function marked deterministic) guaranteed to be equivalent. That is because there is a second reason why the optimizer won’t make this change – and that is that the optimizer thinks that invoking the function has a zero cost. Why would it even consider a complicated plan transform that saves 99,990 function calls if it thinks that those calls are free? After all, zero multiplied by 99,990 is still zero. Unfortunately, whereas we can affect determinism of a function, we cannot influence the cost estimate the optimizer uses for it.&lt;/p&gt;  &lt;p&gt;This same zero cost estimate leads to more bad plan choices. For instance, in the query below, the optimizer will happily invoke the scalar UDF two times for each row: once for the WHERE and once for the SELECT:&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;SELECT 1 - dbo.Triple(DataVal)     &lt;br&gt;FROM&amp;nbsp;&amp;nbsp; dbo.LargeTable      &lt;br&gt;WHERE&amp;nbsp; dbo.Triple(DataVal) &amp;gt; 20;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="3"&gt;&lt;b&gt;It gets worse&lt;/b&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Unfortunately, these two (overhead times the number of rows and bad cost estimate affecting plan choice) are not the only problems with scalar UDFs. There is a third problem: SQL Server will never use parallelism in a plan that uses scalar UDFs. This becomes only visible with larger tables, so let’s get rid of our 100,000 test rows and replace them with ten million fresh ones:&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;TRUNCATE TABLE dbo.LargeTable;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;WITH Digits     &lt;br&gt;AS (SELECT d FROM (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) AS d(d))      &lt;br&gt;INSERT INTO dbo.LargeTable (KeyVal, DataVal)      &lt;br&gt;SELECT 1000000 * sm.d      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; + 100000 * ht.d + 10000 * tt.d + 1000 * st.d      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; + 100 * h.d + 10 * t.d + s.d + 1,      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 10 * RAND(CHECKSUM(NEWID())) + 1      &lt;br&gt;FROM&amp;nbsp;&amp;nbsp; Digits AS s,&amp;nbsp; Digits AS t,&amp;nbsp; Digits AS h,      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Digits AS st, Digits AS tt, Digits AS ht,      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Digits AS sm;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;If we now execute our original queries again, we will see two changes over the first time, when we used 100,000 rows. The first change is that now the plans are not the same; the plan for the query with scalar UDF is still the same, but the plan for the query without scalar UDF introduces parallelism.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/hugo_kornelis/image_43F2A67F.png"&gt;&lt;img src="http://sqlblog.com/blogs/hugo_kornelis/image_thumb_66D3682F.png" style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" alt="image" border="0" height="257" width="1025"&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The second change is maybe not really a change – it’s the observation that the percentages in the plan are still way off. On my laptop, the query with UDF takes 40108 ms CPU and 43760 ms elapsed to process all million rows; the query without UDF does the same in 4397 ms CPU and 808 ms elapsed. Based on CPU usage, the UDF version takes 90% of the batch (making the difference slightly less than in the non-parallel version – this is caused by the overhead of synchronizing over all the threads and combining the results); based on elapsed time, it’s even 98% (based on all cores in my laptop working instead of just one).&lt;/p&gt;  &lt;p&gt;I made another interesting (and slightly disturbing) observation when I looked at the execution plans of the queries that force the optimizer to first find the distinct values of DataVal and then only invoke compute the triple of those distinct value:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sqlblog.com/blogs/hugo_kornelis/image_4C92FF0B.png"&gt;&lt;img src="http://sqlblog.com/blogs/hugo_kornelis/image_thumb_0465432F.png" style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="image" alt="image" border="0" height="256" width="1189"&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The version without UDF uses the parallel part of the plan to read all rows and find the distinct DataVal values, then computes the triple for those distinct values in the serial part. I would have expected a similar plan for the version with UDF (since the UDF would only be called in the serial part), but apparently, the mere presence of a scalar UDF in the query prevents any form of parallelism for the entire execution plan!&lt;/p&gt;  &lt;p&gt;&lt;font size="3"&gt;&lt;b&gt;The remedy&lt;/b&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;If you care about performance, you should avoid the use of scalar UDFs, except in situations where their performance hit doesn’t hurt. For instance, in a SET statement without subquery, a UDF does not hurt you, because it will be invoked only once. And in a SELECT statement that processes only a very small table and is not part of a time-critical part of your system, the performance hit doesn’t really matter much (but don’t think that it’s safe to use a scalar UDF in a query that returns only a few rows from a large table – sometimes the optimizer will produce a plan where the evaluation of the UDF is pushed down to a part of the plan that is executed before the majority of the rows is filtered out!)&lt;/p&gt;  &lt;p&gt;The obvious workaround is to not use a scalar UDF at all, but instead inline the code. For the Triple function I used here, this is dead simple. If you have a UDF that contains multiple statements, calculating and storing intermediate results in variables, doing conditional logic based on IF … ELSE blocks,etc – this can be quite hard. You may have to use complicated CASE expressions, and you may have to repeat expressions multiple times (or use CTEs to avoid that duplication). But the performance gain will make up for the effort! Just don’t forget to carefully comment and document the sometimes hideous queries this may result in. As an example of what I mean, look at this scalar UDF and the corresponding inline rewrite (and if you want to know what the use of this UDF is, there is none; it’s just some nonsense I made up).&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;CREATE FUNCTION dbo.Nonsense(@Input int)     &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RETURNS int      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WITH SCHEMABINDING      &lt;br&gt;AS      &lt;br&gt;BEGIN;      &lt;br&gt;&amp;nbsp; DECLARE @Result int,      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @BaseDate date,      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @YearsAdded date,      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @WeekDiff int;      &lt;br&gt;&amp;nbsp; SET @BaseDate = '20000101';      &lt;br&gt;&amp;nbsp; SET @YearsAdded = DATEADD(year, @Input, @BaseDate);      &lt;br&gt;&amp;nbsp; IF @Input % 2 = 0      &lt;br&gt;&amp;nbsp; BEGIN;      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SET @Result = DATEDIFF(day, @YearsAdded, @BaseDate)      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - DATEDIFF(month, @YearsAdded, @BaseDate);      &lt;br&gt;&amp;nbsp; END;      &lt;br&gt;&amp;nbsp; ELSE      &lt;br&gt;&amp;nbsp; BEGIN;      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SET @WeekDiff = DATEDIFF(week, @BaseDate, @YearsAdded);      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SET @Result = (100 + @WeekDiff) * (@WeekDiff - 100);      &lt;br&gt;&amp;nbsp; END;      &lt;br&gt;&amp;nbsp; RETURN @Result;      &lt;br&gt;END;      &lt;br&gt;go&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;SELECT KeyVal, DataVal,     &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dbo.Nonsense(DataVal)      &lt;br&gt;FROM&amp;nbsp;&amp;nbsp; dbo.LargeTable      &lt;br&gt;WHERE&amp;nbsp; KeyVal &amp;lt;= 100;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;WITH MyCTE     &lt;br&gt;AS (SELECT KeyVal, DataVal,      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CAST('20000101' AS date) AS BaseDate,      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DATEADD(year, DataVal, CAST('20000101' AS date)) AS YearsAdded      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM&amp;nbsp;&amp;nbsp; dbo.LargeTable)      &lt;br&gt;SELECT KeyVal, DataVal,      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CASE WHEN DataVal % 2 = 0      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; THEN DATEDIFF(day, YearsAdded, BaseDate)      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - DATEDIFF(month, YearsAdded, BaseDate)      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ELSE (100 + DATEDIFF(week, BaseDate, YearsAdded))      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * (DATEDIFF(week, BaseDate, YearsAdded) - 100)      &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; END      &lt;br&gt;FROM&amp;nbsp;&amp;nbsp; MyCTE      &lt;br&gt;WHERE&amp;nbsp; KeyVal &amp;lt;= 100;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;The query with the logic inlined may not look pretty – but if I execute the query for all ten million rows in the table (again using the MAX aggregate to reduce I/O and rendering overhead), the performance difference makes it worth it: over a minute for the UDF version, versus less than 4 seconds for the inlined version!&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;font size="3"&gt;What’s next?&lt;/font&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;In the next part of this series, I’ll look at how data access in a scalar UDF changes the situation – to the worse! After that, I’ll check the two types of table-valued functions. Where scalar UDFs are good, table-valued UDFs can be downright ugly – or they can be good, depending on the type. I will also present a way to replace scalar functions with inline table-valued functions, so that you can encapsulate and reuse code without paying the gigantic performance penalty of scalar UDFs – but at the cost of complicating your query. So stay tuned!&lt;/p&gt;</description></item><item><title>Performance impact: SQL trace and user defined scalar functions</title><link>http://sqlblog.com/blogs/linchi_shea/archive/2009/06/15/performance-impact-sql-trace-and-user-defined-scalar-functions.aspx</link><pubDate>Mon, 15 Jun 2009 17:21:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:14682</guid><dc:creator>Linchi Shea</dc:creator><description>&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;FONT face="Times New Roman" size=3&gt;Certain things just don’t go well together! No, not talking about liberals and Republicans. Rather, I’m talking about user defined scalar functions and SQL traces. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;FONT face="Times New Roman" size=3&gt;If you run SQL Trace or SQL Profiler often, you’d find user defined scalar functions to be rather annoying in that 90% of your trace file can be easily taken up by functional calls if you trace for SP:Starting and/or SP:Completed. And it can be much worse if you trace for SP:StmtStarting and/or SP:StmtCompleted.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;FONT face="Times New Roman" size=3&gt;Burying useful trace data in an avalanche of functional calls is but a minor issue compared to the adverse performance impact you may experience when combining a SQL trace and user defined scalar functions, perhaps inadvertently.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;FONT face="Times New Roman" size=3&gt;First, an anecdote. Some time ago, I was at a site where a stored procedure consistently performed much worse on the production server than it did on the QA server with the same database and with the production server supposedly being much better equipped than the QA server. The proc executed with the same query plan, and a trace confirmed that it was going through the same steps in both prod and QA. The proc ran for less than one second in QA, but took five seconds to complete in prod.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;FONT face="Times New Roman" size=3&gt;Just when we started to suspect whether the production server was really better than the QA server, it was found that there was a trace running on the production server. Turning off the trace on the production led to immediate improvement of the stored procedure on the production server. In fact, it now performed faster in prod than it did in QA. Furthermore, if we took out the scalar function calls in the stored procedure, it would run faster in prod than in QA regardless of whether that trace was running or not.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;FONT face="Times New Roman" size=3&gt;Now, let’s look at some controlled test results on the performance impact of a SQL trace on a stored procedure that calls a user defined scalar function.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;B style="mso-bidi-font-weight:normal;"&gt;&lt;FONT size=3&gt;&lt;FONT face="Times New Roman"&gt;The test setup&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;FONT face="Times New Roman" size=3&gt;The scalar function is a dummy function in that it doesn’t really do anything. It just returns the input parameter:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;"&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';"&gt;create function dbo.fn_Dummy (@c varchar(20))&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;"&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';"&gt;returns varchar(20)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;"&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';"&gt;as&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;"&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;begin&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;"&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;declare @a varchar(20);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;"&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;select @a = @c;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;"&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;return (@a);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;"&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;end;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;"&gt;&lt;SPAN style="FONT-SIZE:10pt;FONT-FAMILY:'Courier New';"&gt;go&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;FONT face="Times New Roman" size=3&gt;The test table is named &lt;I style="mso-bidi-font-style:normal;"&gt;customer&lt;/I&gt; and its definition is as follows:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;CREATE TABLE customer&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;c_id&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;int,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;c_first&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;char(20),&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;c_middle&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;char(20),&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;c_last&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;char(20),&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;c_data&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;char(500)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;FONT face="Times New Roman" size=3&gt;The customer table is populated with 50,000 rows as follows:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;declare @i int&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;set @i = 1&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;begin tran&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;while @i &amp;lt;= 50000&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;begin&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;insert customer(c_id, c_first, c_middle, c_last, c_data)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;select @i, CAST(@i as CHAR(20)), &lt;BR&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;CAST(@i as CHAR(20)),&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;CAST(@i as CHAR(20)),&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;CAST(@i as CHAR(500))&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;set @i = @i + 1&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;end&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;commit tran&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;go&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;create clustered index ci_customer on customer(c_id)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:blue;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;FONT face="Times New Roman" size=3&gt;Two stored procedures are used in the tests: p_test and p_testUDF. They are identical except that p_test does NOT call the scalar function.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;create proc p_test&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;as&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;set nocount on&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/SPAN&gt;-- does not call fn_Dummy()&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;select max(DATALENGTH(&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;c.c_first +&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;c.c_middle +&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;c.c_last&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/SPAN&gt;)),&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;COUNT(*)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/SPAN&gt;from customer c&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;where c_id &amp;lt;= 50000;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;go&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;SPAN style="COLOR:black;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;create proc p_testUDF&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;as&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;set nocount on&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/SPAN&gt;-- does call fn_Dummy()&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;select max(DATALENGTH(&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;dbo.fn_Dummy(c.c_first) +&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;dbo.fn_Dummy(c.c_middle) +&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;dbo.fn_Dummy(c.c_last) )),&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;COUNT(*)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;mso-layout-grid-align:none;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;SPAN style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/SPAN&gt;from customer c&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;where c_id &amp;lt;= 50000;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND:#e6e6e6;MARGIN:0in 0in 0pt;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:black;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;go&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;SPAN style="FONT-SIZE:10pt;COLOR:gray;FONT-FAMILY:'Courier New';mso-no-proof:yes;"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;B style="mso-bidi-font-weight:normal;"&gt;&lt;SPAN style="COLOR:black;"&gt;&lt;FONT size=3&gt;&lt;FONT face="Times New Roman"&gt;The tests&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;SPAN style="COLOR:black;"&gt;&lt;FONT size=3&gt;&lt;FONT face="Times New Roman"&gt;The key test parameters include:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;SPAN style="COLOR:black;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoList3 style="MARGIN:0in 0in 0pt 0.5in;TEXT-INDENT:-0.25in;tab-stops:list .5in;"&gt;&lt;SPAN style="FONT-FAMILY:Symbol;mso-fareast-font-family:Symbol;mso-bidi-font-family:Symbol;"&gt;&lt;SPAN style="mso-list:Ignore;"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face="Times New Roman"&gt;&lt;B style="mso-bidi-font-weight:normal;"&gt;With scalar function calls vs. without scalar function calls&lt;/B&gt;. This is controlled by calling either p_test or calling p_testUDF. The former makes no scalar function calls.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoList3 style="MARGIN:0in 0in 0pt 0.5in;TEXT-INDENT:-0.25in;tab-stops:list .5in;"&gt;&lt;SPAN style="FONT-FAMILY:Symbol;mso-fareast-font-family:Symbol;mso-bidi-font-family:Symbol;"&gt;&lt;SPAN style="mso-list:Ignore;"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face="Times New Roman"&gt;&lt;B style="mso-bidi-font-weight:normal;"&gt;SQL trace configurations (i.e. level of tracing details)&lt;/B&gt;. Four different SQL traces are configured with different levels of details being traced:&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoList3 style="MARGIN:0in 0in 0pt 1in;TEXT-INDENT:-0.25in;tab-stops:list 1.0in;"&gt;&lt;SPAN style="FONT-FAMILY:'Courier New';mso-fareast-font-family:'Courier New';"&gt;&lt;SPAN style="mso-list:Ignore;"&gt;&lt;FONT size=3&gt;o&lt;/FONT&gt;&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face="Times New Roman"&gt;&lt;B style="mso-bidi-font-weight:normal;"&gt;No Trace&lt;/B&gt;. This is the test baseline when no trace is configured.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoList3 style="MARGIN:0in 0in 0pt 1in;TEXT-INDENT:-0.25in;tab-stops:list 1.0in;"&gt;&lt;SPAN style="FONT-FAMILY:'Courier New';mso-fareast-font-family:'Courier New';"&gt;&lt;SPAN style="mso-list:Ignore;"&gt;&lt;FONT size=3&gt;o&lt;/FONT&gt;&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face="Times New Roman"&gt;&lt;B style="mso-bidi-font-weight:normal;"&gt;Default Trace. &lt;/B&gt;This comes off the default trace template defined by SQL Server 2005. It basically traces for RPC:Completed and SQL:BatchCompleted. This is the least detailed trace of the tested trace configurations.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoList3 style="MARGIN:0in 0in 0pt 1in;TEXT-INDENT:-0.25in;tab-stops:list 1.0in;"&gt;&lt;SPAN style="FONT-FAMILY:'Courier New';mso-fareast-font-family:'Courier New';"&gt;&lt;SPAN style="mso-list:Ignore;"&gt;&lt;FONT size=3&gt;o&lt;/FONT&gt;&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face="Times New Roman"&gt;&lt;B style="mso-bidi-font-weight:normal;"&gt;SP Trace&lt;/B&gt;. This trace configuration includes the events covered by the Default Trace plus SP:Completed.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoList3 style="MARGIN:0in 0in 0pt 1in;TEXT-INDENT:-0.25in;tab-stops:list 1.0in;"&gt;&lt;SPAN style="FONT-FAMILY:'Courier New';mso-fareast-font-family:'Courier New';"&gt;&lt;SPAN style="mso-list:Ignore;"&gt;&lt;FONT size=3&gt;o&lt;/FONT&gt;&lt;SPAN style="FONT:7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;FONT face="Times New Roman"&gt;&lt;B style="mso-bidi-font-weight:normal;"&gt;Stmt Trace&lt;/B&gt;. This trace configuration include the events covered by the SP trace plus SP:StmtCompleted. This is the most detailed trace of the tested trace configurations.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoList3 style="MARGIN:0in 0in 0pt 0.5in;TEXT-INDENT:0in;tab-stops:.5in;mso-list:none;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoList3 style="MARGIN:0in 0in 0pt 0.5in;TEXT-INDENT:0in;tab-stops:.5in;mso-list:none;"&gt;&lt;FONT face="Times New Roman" size=3&gt;So these four trace configurations are progressively more detailed.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoList3 style="MARGIN:0in 0in 0pt 0.15in;TEXT-INDENT:0in;tab-stops:.5in;mso-list:none;"&gt;&lt;B style="mso-bidi-font-weight:normal;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;B style="mso-bidi-font-weight:normal;"&gt;&lt;FONT size=3&gt;&lt;FONT face="Times New Roman"&gt;The test results&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;FONT face="Times New Roman" size=3&gt;All the test results are recorded only after multiple runs of the same tests. And since the customer table is about 2GB in size and the SQL Server buffer pool has 6GB allocated, all the test results are taken when the table is fully cached in the buffer pool.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;FONT face="Times New Roman" size=3&gt;The key metric is the response time of the test proc: either p_test or p_testUDF as defined above.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;FONT face="Times New Roman" size=3&gt;As always, it’s better to present the test results in a chart format.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&amp;nbsp;&lt;/P&gt;&lt;IMG src="http://sqlblog.com/blogs/linchi_shea/attachment/14682.ashx"&gt; &lt;SPAN style="FONT-SIZE:12pt;FONT-FAMILY:'Times New Roman';mso-fareast-font-family:'Times New Roman';mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;"&gt;&lt;BR style="PAGE-BREAK-BEFORE:always;mso-special-character:line-break;"&gt;&lt;/SPAN&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;&lt;o:p&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;FONT face="Times New Roman" size=3&gt;A number of things stand out rather strikingly from these two charts.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;FONT face="Times New Roman" size=3&gt;First, when a proc calls a scalar UDF, the level of the details you trace can have a huge negative impact on the proc performance. In particular, if you do statement level tracing (e.g. tracing for SP:StmtCompleted or SP:StmtStarting), you could see your proc performing several times worse. In my tests, the proc takes 10 times longer to complete when the statement level trace is enabled.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;FONT face="Times New Roman" size=3&gt;Secondly, the exact degree of the impact depends, not surprisingly, on the number of calls to the scalar function, which is in turn dependent on the number of rows and the number of columns the scalar function is applied to. In my tests, the number of rows is set to 50,000. This may sound like a lot of rows to apply a scalar function to. And it is actually a lot of rows in light of the impact we are seeing. However and unfortunately, this is not uncommon in the real world applications.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;FONT face="Times New Roman" size=3&gt;Thirdly, and from the second chart, it is clear that the proc that does not call the scalar function (i.e. p_test) is insensitive to the trace configuration. This does not mean that any proc that does not call a scalar function is completely unaffected by how you configure a trace. Obviously, for a complex proc, a statement level trace would have to step into its inner steps and may have an impact. What the second chart does show is that it is a solid baseline in that the impact seen in the first chart is caused only by the change in the trace configuration.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;FONT face="Times New Roman" size=3&gt;Another point to highlight is that when you trace at the SQL batch or RPC level (e.g. RPC:Completed), the impact is rather small even with scalar UDF calls. In my tests, when the default trace is enabled, the elapsed time of p_testUDF increases from 576ms to 750ms consistently. That is a ~30% increase. But it is arguably negligible when you compare that with an increase from 576ms to 6436ms when the statement level trace is applied.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;FONT face="Times New Roman" size=3&gt;The key takeaway here is that you must be extra careful when you trace at the stored procedure level (e.g. tracing for SP:Starting), and you must be extraordinarily careful when you trace at the statement level.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN:0in 0in 0pt;"&gt;&lt;/o:p&gt;&amp;nbsp;&lt;/P&gt;</description></item></channel></rss>