question

Zach avatar image
Zach asked

Where clause on indexed column using a variable

I thought this might be an easy question to answer but after hours of searching the web, I'm giving up.

I have a SQL 2005 table with a few composite indexes and a few single column indexes. I've narrowed my problem down to this; if I run a query such as the following:

select * from tbl                    
where col = 'test'                    

the execution plan shows that index built on col is used. However if I run the query this way:

declare @var varchar(10)                    
set @var = 'test'                    
                    
select * from tbl                    
where col = @var                    

then the execution plan shows that the index wasn't used.

I would like to know if this is how sql works or is the sql optimizer just recognizing that it doesn't need to use the index.

Thanks in advance for your help, Z

sql-server-2005indexes
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

RickD avatar image
RickD answered

Did you clear the Cache between the first and second execution? This can cause your query to be cached, even though you think you changed it, SQL will pre-compile the code and see it is the same as the cached version it has got as far as it is concerned.

If you want to do a true test, run:

DBCC FREEPROCCACHE            

between the two statements.

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Kristen avatar image
Kristen answered

I can't say I've had a problem with this in Stored Procedures, but I don't know about when using dynamic SQL, or parameterised queries (e.g. using sp_ExecuteSQL).

You might want to Google "Parameter Sniffing" though, which may enable you to force the query optimizer to take note of the actual value in your parameter.

There is also the issue that a Stored Procedure's cached Query Plan will be created the first time the Sproc runes; which may give a "sub-standard" query plan if the parameter is not very selective - e.g. a table scan instead of an index seek.

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Craig avatar image
Craig answered

Does the Col column have a definition of varchar(10)? It may be that SQL compares the column definition to the variable definition and decides that they are so dissimilar that it cannot use the index.

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Peso avatar image
Peso answered

You probably used the clustered index instead, due to the "SELECT *". SQL Server probably did this to avoid a KEY LOOKUP for you.

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Rajib Bahar avatar image
Rajib Bahar answered

have you considered forcing index hint? you can tell the query that you want a particular index always used regardless of what SQL server decides in the background.

WITH INDEX(<INDEX_NAME>) or WTIH INDEX(<INDEX_NO>)            
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.