Hi SQL Padawan,
I coded up your example to explain the difference between estimated execution plans and actual I/O statistics.
Both of your statements use the idx_field_value in the query plan.
In my example below, I could not get the query analyzer to use the this index due to the amount of data in the table (2 records).
It performs a full table scan (FTS).
Here are some things to note.
1 - The plan with a constant will probably be re-used. This is due to the fact that we know what the value is.
On the other hand, this may lead to parameter sniffing.
2 - The plan with the variable will be recompiled every time. This is due to the fact it might change.
This is even more likely if the input parameter is set to a local variable before executing. And the local variable is used in the where clause.
Please see Grant Fritchey query plan e-book from simple talk.
I usually look at time and I/O when running a query. The below TSQL with turn these counters on in the query window.
-- Show time & i/o
SET STATISTICS TIME ON
SET STATISTICS IO ON
GO
I usually clear the buffers and plan cache in test so that stored plans do not skew the results.
-- Remove clean buffers & clear plan cache
CHECKPOINT
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
GO
My simple execution using two records show that the non-parameter solution is 1 ms quicker than the one with a variable.
Both have the same page scans (logical and physical).
Please redo clearing the buffers and cache and post the results for I/O.
If they are almost the same, there is really not difference between the two constructs other than possibly removing parameter sniffing.
Sincerely
John
PS: I hope this post helps you out!
:w00t:
--
-- Sample code
--
-- Create temp table
create table tempdb.dbo.table7
(
[pk_value] int,
[field_value] varchar(10)
);
-- Create NC index
create nonclustered index idx_field_value on tempdb.dbo.table7 ([field_value]);
-- Insert two rows
insert into tempdb.dbo.table7 values
(1, 'Yes'),
(2, 'No');
-- Update the stats
update statistics tempdb.dbo.table7;
go
-- Show the data
select * from tempdb.dbo.table7
-- Show time & i/o
SET STATISTICS TIME ON
SET STATISTICS IO ON
GO
-- Remove clean buffers & clear plan cache
CHECKPOINT
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
GO
-- Declare local variable
declare @yes varchar(3) = 'Yes'
-- First way
select
[pk_value]
,[field_value]
from tempdb.dbo.table7
where [field_value] = @yes;
/*
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 18 ms.
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.
(1 row(s) affected)
Table 'table7'. Scan count 1, logical reads 1, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 14 ms.
*/
-- Remove clean buffers & clear plan cache
CHECKPOINT
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
GO
-- Second way
select
[pk_value]
,[field_value]
FROM tempdb.dbo.table7
WHERE [field_value] = 'Yes';
/*
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 22 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
(1 row(s) affected)
Table 'table7'. Scan count 1, logical reads 1, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 13 ms.
*/
John Miner
Crafty DBA
www.craftydba.com