{"id":872,"date":"2010-04-28T00:00:00","date_gmt":"2010-04-28T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/showplan-operator-of-the-week-compute-scalar\/"},"modified":"2021-08-16T15:02:17","modified_gmt":"2021-08-16T15:02:17","slug":"showplan-operator-of-the-week-compute-scalar","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/learn\/showplan-operator-of-the-week-compute-scalar\/","title":{"rendered":"Showplan Operator of the Week &#8211; Compute Scalar"},"content":{"rendered":"<div id=\"pretty\">\n<p class=\"MsoNormal\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1018-F1.JPG\" width=\"36\" height=\"36\" alt=\"1018-F1.JPG\" \/>Compute Scalar<\/p>\n<p class=\"start\">In the past two weeks, I&#8217;ve talked about two of the most important showplan operators, <a href=\"http:\/\/www.simple-talk.com\/sql\/learn-sql-server\/showplan-operator-of-the-week---concatenation\/\">Concatenation<\/a> and <a href=\"http:\/\/www.simple-talk.com\/sql\/learn-sql-server\/showplan-operator-of-the-week---assert\/\">Assert<\/a>. It is useful to know about such Showplan Operators if you are programming in SQL Server, because they are used by SQL Server&#8217;s Query Optimizer (QO) &#160;to perform a particular operation within a query plan. Each physical operation in the Query Plan is performed by an operator.&#160; When you look at a graphical execution plan, you will see each operator represented by an icon. This week we&#8217;ll be featuring the <b>compute scalar<\/b> showplan operator. This operator is very common, and we can see it in many execution plans.<\/p>\n<p>As is obvious from its name, <b>Compute Scalar<\/b> performs a scalar computation and returns a computed value. This calculation can be as simple as a conversion of value, or a concatenation of values.<\/p>\n<p>Most of the time, it is ignored by SQL users because it represents a minimal cost when compared to the cost of the entire execution plan, but, it can become well-worth looking at when we are dealing with cursors and some huge loops, and especially if you are having a CPU problem.<\/p>\n<p>To start with, let&#8217;s take a simple use of <b>Compute Scalar<\/b>. One simple conversion of data from <b>Int<\/b> to <b>Char <\/b>can be done without much problem but, if we execute this conversion one million times, &#160;it becomes a different matter. If we change the query so as to not execute this conversion step, we will have an optimization in CPU use, and a consequential improvement in the speed of execution.<\/p>\n<p>Let&#8217;s take the following query as a sample:<\/p>\n<p>The following script will create a table TabTeste and populate with some garbage data.<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">USE tempdb\nGO\nCREATE TABLE TABTeste(ID&#160;&#160; Int Identity(1,1) PRIMARY KEY, \n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Nome VarChar(250)&#160;&#160;&#160;&#160;&#160; DEFAULT NewID())\nGO\nSET NOCOUNT ON\nGO\nINSERT INTO TABTeste DEFAULT VALUES\nGO 10000\nNow, the code bellow will pass to the loop one million of times.\nDECLARE @I Int\nSET @I = 0\nWHILE @I &lt; 1000000\nBEGIN\n&#160; IF EXISTS(SELECT ID FROM TABTeste WHERE ID = @I)\n&#160; BEGIN\n&#160;&#160;&#160; PRINT 'Entrou no IF'\n&#160; END\n&#160; SET @I = @I + 1;\nEND\nGO\n<\/pre>\n<p><b>Graphical execution plan:<\/b><\/p>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1018-F2.JPG\" alt=\"1018-F2.JPG\" \/><\/p>\n<p>As we can see, the Operator <b>Compute Scalar<\/b> is used, let&#8217;s take a look at the text execution plan to see more details about that operation.<\/p>\n<p><b>Text execution plan:<\/b><\/p>\n<div class=\"scroller\">\n<pre>|--Compute Scalar(DEFINE:([Expr1003]=CASE WHEN [Expr1004] THEN (1) ELSE (0) END))\n&#160;&#160;&#160;&#160;&#160;&#160;&#160; |--Nested Loops(Left Semi Join, DEFINE:([Expr1004] = [PROBE VALUE]))\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; |--Constant Scan\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; |--Clustered Index Seek(OBJECT:([tempdb].[dbo].[TABTeste].[PK__TABTeste__3214EC27096F09E1]), SEEK:([tempdb].[dbo].[TABTeste].[ID]=[@I]) ORDERED FORWARD)\n\n<\/pre>\n<\/div>\n<p>This plan is using the Compute Scalar to check if the Nested Loop returns any rows, on the other words; it is doing the IF EXISTS Job.<\/p>\n<p>If we look at the profiler results we can see the column CPU which show us how much CPU the query above uses.<\/p>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1018-F3.JPG\" alt=\"1018-F3.JPG\" \/><\/p>\n<p>Now let&#8217;s change the code to remove the Compute Scalar operator.<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">DECLARE @I Int, @Var Int\nSET @I = 0\nWHILE @I &lt; 1000000\nBEGIN\n&#160; SELECT @Var = ID FROM TABTeste WHERE ID = @I\n&#160; IF @@ROWCOUNT &gt; 0\n&#160; BEGIN\n&#160;&#160;&#160; PRINT 'Entrou no IF'\n&#160; END\n&#160; SET @I = @I + 1;\nEND\nGO\n<\/pre>\n<p><b>Graphical execution plan:<\/b><\/p>\n<p class=\"illustration\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1018-F4.JPG\" width=\"430\" height=\"420\" alt=\"1018-F4.JPG\" \/><\/p>\n<p><b>Text execution plan:<\/b><\/p>\n<div class=\"scroller\">\n<pre>&#160;&#160;&#160;&#160;&#160;&#160;&#160;|--Clustered Index Seek(OBJECT:([tempdb].[dbo].[TABTeste].[PK__TABTeste__3214EC27096F09E1]), SEEK:([tempdb].[dbo].[TABTeste].[ID]=[@I]) ORDERED FORWARD)\n\n<\/pre>\n<\/div>\n<p>Now that SQL Server does not use the Compute Scalar, let&#8217;s take a look at the CPU costs.<\/p>\n<pre><\/pre>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1018-F5.JPG\" alt=\"1018-F5.JPG\" \/><\/p>\n<p>As you can see, SQL Server uses less CPU and finishes the execution of the query faster than it does with the first query. I&#8217;m not trying to show you the better way to check whether a particular value exists, I&#8217;m just showing the <b>Compute Scalar<\/b> behavior. &#160;However, if you have never seen this kind of validation using @@RowCount, it may be that it could help you a little bit in your coding. Some time ago I changed one procedure that uses a lot of <b>IF Exists<\/b> in much the same way, with very satisfactory result for the performance of the procedure.<\/p>\n<p>Let&#8217;s take a look at more practical examples&#160; of <b>Compute Scalar<\/b>.<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">DECLARE @Tab TABLE(ID SmallInt PRIMARY KEY)  \nSELECT 'Fabiano' + ' - ' + 'Amorim' FROM @Tab\n<\/pre>\n<p><b>Graphical execution plan:<\/b><\/p>\n<p class=\"illustration\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1018-F6.JPG\" width=\"401\" height=\"121\" alt=\"1018-F6.JPG\" \/><\/p>\n<p><b>Text execution plan:<\/b><\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">&#160; |--Compute Scalar(DEFINE:([Expr1003]='Fabiano - Amorim'))\n&#160;&#160;&#160;&#160;&#160;&#160; |--Clustered Index Scan(OBJECT:(@Tab))\n<\/pre>\n<p>The plan was generated using the <b>Compute Scalar<\/b> just to make the concatenation between &#8220;Fabiano&#8221;, &#8220;-&#8221; and &#8220;Amorim&#8221;: Quite simple.<\/p>\n<p>Now we&#8217;ll see one very interesting behavior of <b>Compute Scalar<\/b> &#160;that it changes in SQL Server 2005\/2008.<\/p>\n<p>Consider the following query:<\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">DECLARE @Tab TABLE(ID SmallInt PRIMARY KEY)  \nDECLARE @ID_Int Integer\nSELECT *\n&#160; FROM @Tab\n&#160;WHERE ID = @ID_Int\n<\/pre>\n<p>Notice that the Column ID is a <b>SmallInt<\/b> type, and the variable <b>@ID_Int<\/b> is a Integer, that means SQL Server as to convert the value of <b>@ID_Int <\/b>to be able to compare the value with ID Column.<\/p>\n<p>At SQL Server 2000 we have the following plan.<\/p>\n<p><b>SQL 2000 Graphical execution plan:<\/b><\/p>\n<p class=\"illustration\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1018-F7.JPG\" width=\"418\" height=\"188\" alt=\"1018-F7.JPG\" \/><\/p>\n<p><b>SQL 2000 Text execution plan:<\/b><\/p>\n<div class=\"scroller\">\n<pre>&#160; |--Nested Loops(Inner Join, OUTER REFERENCES:([Expr1002], [Expr1003], [Expr1004]))\n&#160;&#160;&#160;&#160;&#160;&#160; |--Compute Scalar(DEFINE:([Expr1002]=Convert([@ID_Int])-1, [Expr1003]=Convert([@ID_Int])+1, [Expr1004]=If (Convert([@ID_Int])-1=NULL) then 0 else 6|If (Convert([@ID_Int])+1=NULL) then 0 else 10))&#160;&#160;&#160;&#160;&#160;&#160; |&#160;&#160;&#160; |--Constant Scan\n&#160;&#160;&#160;&#160;&#160;&#160; |--Clustered Index Seek(OBJECT:(@Tab), SEEK:(@Tab.[ID] &gt; [Expr1002] AND @Tab.[ID] &lt; [Expr1003]),&#160; WHERE:(Convert(@Tab.[ID])=[@ID_Int]) ORDERED FORWARD)\n\n<\/pre>\n<\/p>\n<\/div>\n<p>Wow, it&#8217;s a quite hard work, don&#8217;t you think? Now let&#8217;s take a look what happens if we run this code at SQL 2005\/2008.<\/p>\n<p><b>SQL 2005\/2008 Graphical execution plan:<\/b><\/p>\n<p class=\"illustration\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1018-F8.JPG\" width=\"323\" height=\"135\" alt=\"1018-F8.JPG\" \/><\/p>\n<p><b>SQL 2005\/2008 Text execution plan:<\/b><\/p>\n<pre class=\"theme:ssms2012 lang:tsql\">|--Clustered Index Seek(OBJECT:(@Tab), SEEK:([ID]=[@ID_Int]) ORDERED FORWARD)  \n<\/pre>\n<p>Yep, now we have a much more simple plan (which was nothing about the band). But wait a minute, what is this? Now SQL Server does not convert the value!<\/p>\n<p>Let&#8217;s look at the execution plan to understand what is going on with the <b>Clustered Index Seek<\/b> show plan operator.<\/p>\n<p><b>Graphical execution plan:<\/b><\/p>\n<p class=\"illustration\"><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/1018-F9.JPG\" alt=\"1018-F9.JPG\" \/><\/p>\n<p>As we can see, the SQL Server Dev Team has changed the Engine to use a function called &#8220;<b>Scalar Operator<\/b>&#8221; to convert the value to the appropriate datatype, that&#8217;s interesting.<\/p>\n<p>That&#8217;s all folks, I see you next week with more &#8220;Showplan Operators&#8221;.<\/p>\n<div class=\"note\">\n<p class=\"note\">If you missed last week&#8217;s thrilling Showplan Operator, Concatenation, you can see it <a href=\"http:\/\/www.simple-talk.com\/sql\/learn-sql-server\/showplan-operator-of-the-week---concatenation\/\">here.<\/a><\/p>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>The third part of Fabiano&#8217;s mission to describe the major Showplan Operators used by SQL Server&#8217;s Query Optimiser continues with the &#8216;Compute Scalar&#8217; operator. Fabiano shows how a tweak to  SQL to avoid a &#8216;Compute Scalar&#8217; step can improve its performance.&hellip;<\/p>\n","protected":false},"author":65554,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143525],"tags":[4178,5178,5177,4149,5084,5162,4150,4151],"coauthors":[],"class_list":["post-872","post","type-post","status-publish","format-standard","hentry","category-learn","tag-bi","tag-compute-scalar","tag-fabiano-amorim","tag-learn-sql-server","tag-optimiser","tag-showplan","tag-sql","tag-sql-server"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/872","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/65554"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=872"}],"version-history":[{"count":4,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/872\/revisions"}],"predecessor-version":[{"id":92146,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/872\/revisions\/92146"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=872"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=872"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=872"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=872"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}