I have a simple date table (Date, DateID) that contains a list of dates between January 1, 1900 and December 31, 2100.
When choosing from a table using the between operator and hard-coded parameter values, I get the correct query plan with 3 evaluated rows compared to two actual rows:
select v.Date from Dates v where v.Date between '20130128' and '20130129';
However, when replacing hard-coded values with parameters, the query plan changes to a very poor plan, with more than 6,000 evaluated rows and only 2 actual rows:
select v.Date from Dates v where v.Date between @startdate and @enddate;
Query plans are identical in themselves, it’s just the difference in the estimated lines, which leads to the start of a parameterized query about 4 times slower than a programmed query. Is there something that I am missing, why the parameterized version is much slower, and what indexes / hints can I give SQL Server to help it use the correct query plan?
Additional Information:
- The problem does not arise when using simple equality criteria
= , it seems specific to the between operator. - If I add
option(recompile) at the end of a parameterized query, I get a perfect query plan identical to a hard-coded query. - There are only two columns in the date table: Date and DateID with a clustered index in the DateID column of the primary key and a unique non-clustered index in the Date column. All updated statistics.
- The query plan performs automatic parameterization for the hard-coded query, replacing the hard-coded values with @ 1 and @ 2 and displaying the query as uppercase. It does not seem to perform any conversions for the parameterized query.
- Using SQL Server 2008 R2.
I know enough to realize to suspect that this is some kind of problem with sniffing options. Why not add option(recompile) to the request? This is used as part of a much more complex query, and I understand that it is good practice to let SQL Server do its job and reuse query plans from the cache where possible.
Edit and update: thanks for the thoughtful answers. To clarify the question, the query plan uses an excellent index for both of the above queries, but why doesn’t he admit that the date range is only two days for a parameterized query, why does he think that the range is 6000 rows wide? Especially when, looking at the query plan, does SQL Server perform automatic parameterization for a hard-coded query? In the basic query plan, both plans look the same, because both of them are parameterized!