Click here to monitor SSC
Av rating:
Total votes: 16
Total comments: 1


Fabiano Amorim
Showplan Operator of the Week - Compute Scalar
28 April 2010

 The third part of Fabiano's mission to describe the major Showplan Operators used by SQL Server's Query Optimiser continues with the 'Compute Scalar' operator. Fabiano shows how a tweak to  SQL to avoid a 'Compute Scalar' step can improve its performance.

Compute Scalar

In the past two weeks, I’ve talked about two of the most important showplan operators, Concatenation and Assert. It is useful to know about such Showplan Operators if you are programming in SQL Server, because they are used by SQL Server's Query Optimizer (QO)  to perform a particular operation within a query plan. Each physical operation in the Query Plan is performed by an operator.  When you look at a graphical execution plan, you will see each operator represented by an icon. This week we’ll be featuring the compute scalar showplan operator. This operator is very common, and we can see it in many execution plans.

As is obvious from its name, Compute Scalar 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.

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.

To start with, let’s take a simple use of Compute Scalar. One simple conversion of data from Int to Char can be done without much problem but, if we execute this conversion one million times,  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.

Let’s take the following query as a sample:

The following script will create a table TabTeste and populate with some garbage data.

USE tempdb

GO

CREATE TABLE TABTeste(ID   Int Identity(1,1) PRIMARY KEY,

                      Nome VarChar(250)      DEFAULT NewID())

GO

SET NOCOUNT ON

GO

INSERT INTO TABTeste DEFAULT VALUES

GO 10000

Now, the code bellow will pass to the loop one million of times.

DECLARE @I Int

SET @I = 0

WHILE @I < 1000000

BEGIN

  IF EXISTS(SELECT ID FROM TABTeste WHERE ID = @I)

  BEGIN

    PRINT 'Entrou no IF'

  END

  SET @I = @I + 1;

END

GO

Graphical execution plan:

As we can see, the Operator Compute Scalar is used, let’s take a look at the text execution plan to see more details about that operation.

Text execution plan:

|--Compute Scalar(DEFINE:([Expr1003]=CASE WHEN [Expr1004] THEN (1) ELSE (0) END))
        |--Nested Loops(Left Semi Join, DEFINE:([Expr1004] = [PROBE VALUE]))
             |--Constant Scan
             |--Clustered Index Seek(OBJECT:([tempdb].[dbo].[TABTeste].[PK__TABTeste__3214EC27096F09E1]), SEEK:([tempdb].[dbo].[TABTeste].[ID]=[@I]) ORDERED FORWARD)

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.

If we look at the profiler results we can see the column CPU which show us how much CPU the query above uses.

Now let’s change the code to remove the Compute Scalar operator.

DECLARE @I Int, @Var Int

SET @I = 0

WHILE @I < 1000000

BEGIN

  SELECT @Var = ID FROM TABTeste WHERE ID = @I

  IF @@ROWCOUNT > 0

  BEGIN

    PRINT 'Entrou no IF'

  END

  SET @I = @I + 1;

END

GO

Graphical execution plan:

Text execution plan:

       |--Clustered Index Seek(OBJECT:([tempdb].[dbo].[TABTeste].[PK__TABTeste__3214EC27096F09E1]), SEEK:([tempdb].[dbo].[TABTeste].[ID]=[@I]) ORDERED FORWARD)

Now that SQL Server does not use the Compute Scalar, let’s take a look at the CPU costs.


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’m not trying to show you the better way to check whether a particular value exists, I’m just showing the Compute Scalar behavior.  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 IF Exists in much the same way, with very satisfactory result for the performance of the procedure.

Let’s take a look at more practical examples  of Compute Scalar.

DECLARE @Tab TABLE(ID SmallInt PRIMARY KEY)

SELECT 'Fabiano' + ' - ' + 'Amorim' FROM @Tab

Graphical execution plan:

Text execution plan:

  |--Compute Scalar(DEFINE:([Expr1003]='Fabiano - Amorim'))

       |--Clustered Index Scan(OBJECT:(@Tab))

The plan was generated using the Compute Scalar just to make the concatenation between “Fabiano”, “-” and “Amorim”: Quite simple.

Now we’ll see one very interesting behavior of Compute Scalar  that it changes in SQL Server 2005/2008.

Consider the following query:

DECLARE @Tab TABLE(ID SmallInt PRIMARY KEY)

DECLARE @ID_Int Integer

SELECT *

  FROM @Tab

 WHERE ID = @ID_Int

Notice that the Column ID is a SmallInt type, and the variable @ID_Int is a Integer, that means SQL Server as to convert the value of @ID_Int to be able to compare the value with ID Column.

At SQL Server 2000 we have the following plan.

SQL 2000 Graphical execution plan:

SQL 2000 Text execution plan:

  |--Nested Loops(Inner Join, OUTER REFERENCES:([Expr1002], [Expr1003], [Expr1004]))

       |--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))
       |    |--Constant Scan        |--Clustered Index Seek(OBJECT:(@Tab), SEEK:(@Tab.[ID] > [Expr1002] AND @Tab.[ID] < [Expr1003]),  WHERE:(Convert(@Tab.[ID])=[@ID_Int]) ORDERED FORWARD)

Wow, it’s a quite hard work, don’t you think? Now let’s take a look what happens if we run this code at SQL 2005/2008.

SQL 2005/2008 Graphical execution plan:

SQL 2005/2008 Text execution plan:

|--Clustered Index Seek(OBJECT:(@Tab), SEEK:([ID]=[@ID_Int]) ORDERED FORWARD)

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!

Let’s look at the execution plan to understand what is going on with the Clustered Index Seek show plan operator.

Graphical execution plan:

As we can see, the SQL Server Dev Team has changed the Engine to use a function called “Scalar Operator” to convert the value to the appropriate datatype, that’s interesting.

That’s all folks, I see you next week with more “Showplan Operators”.

If you missed last week's thrilling Showplan Operator, Concatenation, you can see it here.



This article has been viewed 6264 times.
Fabiano Amorim

Author profile: Fabiano Amorim

Fabiano is fascinated by the SQL Server Query Processor and the way it works to optimize queries, procedures and functions. He graduated as a Technical Processor from Colégio Bezerra de Menezes, SP- Brazil, and has worked for several years with SQL Server, focusing in creating Data Warehouses and optimizing T-SQL codes for many companies in Brazil and Argentina. Fabiano is a SQL Server MVP, MCP for SQL Server 2000, MCTS and MCITP Data Base Developer for SQL Server 2005 and 2008. He also is actively involved in SQL Server community though forums such as MSDN and TechNet Brazil, writes articles for Simple-Talk and SQL Server Magazine Brazil, and he also presents online Webcasts and In-Person events for Microsoft Brazil. His blog is on http://blogfabiano.com

Search for other articles by Fabiano Amorim

Rate this article:   Avg rating: from a total of 16 votes.


Poor

OK

Good

Great

Must read
 
Have Your Say
Do you have an opinion on this article? Then add your comment below:
You must be logged in to post to this forum

Click here to log in.


Subject: 2008\2005 behavior
Posted by: chandan_jha18 (view profile)
Posted on: Monday, October 17, 2011 at 2:15 AM
Message: Hi,

I appreciate the great series you have written on execution plans. It helps amateurs like me to understand things in a better way.

In the last portion of yuor post, you mentioned that in 2005\2008, the engineering team has got rid of scalar operator and instead we saw a conversion in the index seek itself. Is it not going to be costly? Will it beneficial for us in case we compare both as 'int' datatype only?

Regards
Chandan

 










Phil Factor
Automated Script-generation with Powershell and SMO
 In the first of a series of articles on automating the process of building, modifying and copying SQL Server... Read more...



 View the blog
Using SQL Test Database Unit Testing with TeamCity Continuous Integration
 With database applications, the process of test and integration can be frustratingly slow because so... Read more...

SQL Source Control: The Development Story
 Often, there is a huge difference between software being easy to use, and easy to develop. When your... Read more...

How to Import Data from HTML pages
 It turns out that there are plenty of ways to get data into SQL Server from websites, whether the data... Read more...

SQL Scripts Manager: An Appreciation
 SQL Scripts Manager is Simple-Talk's present to its readers. William Brewer was an enthusiastic... Read more...

Hosted Team Foundation Server 2010 Review
 Team Foundation Server (TFS) has expanded its remit to support the whole software development process,... Read more...

Beginning SQL Server 2005 Reporting Services Part 1
 Steve Joubert begins an in-depth tour of SQL Server 2005 Reporting Services with a step-by-step guide... Read more...

Ten Common Database Design Mistakes
 Database design and implementation is the cornerstone of any data centric project (read 99.9% of... Read more...

Reading and Writing Files in SQL Server using T-SQL
 SQL Server provides several "standard" techniques by which to read and write to files but, just... Read more...

Beginning SQL Server 2005 Reporting Services Part 2
 Continuing his in-depth tour of SQL Server 2005 Reporting Services, Steve Joubert demonstrates the most... Read more...

Creating CSV Files Using BCP and Stored Procedures
 Nigel Rivett demonstrates some core techniques for extracting SQL Server data into CSV files, focussing... Read more...

Over 400,000 Microsoft professionals subscribe to the Simple-Talk technical journal. Join today, it's fast, simple, free and secure.

Join Simple Talk