I have a simple query that runs very quickly (about 1 second) when I use a string literal in my WHERE
clause, such as:
select *
from table
where theDate >= '6/5/2016'
However, this query (which is not materially different) runs in over 2 minutes:
declare @thisDate as date
set @thisDate = '6/5/2016'
select *
from table
where theDate >= @thisDate
I tried using OPTION(RECOMPILE)
as suggested here but it does nothing to improve the performance. the column theDate
is a datetime, this database was recently migrated from SQL Server 2005.
There is no index on my theDate
column, and the table has just over 1 billion rows. It's a shared resource and I don't want to start indexing without some assurance that it will help.
I find that using logic instead of a variable provides the same performance as a string literal:
select *
from table
where theDate >= dateadd(dd, -23, getdate())
But, if I replace the date integer with a variable integer the performance is again hindered.
How can I include a variable and maintain performance?
EDIT
Actual query included by request:
DECLARE @days INT
Set @days = 7
select c.DEBT_KEY
, c.new_value
, c.CHANGE_DATE
from changes c with (nolock)
where c.C_CODE = 3
and c.old_value = 4
and c.CHANGE_DATE >= dateadd(dd, -@days, getdate())
No joins.
Query Plans
With Variable (xml explain plan):
With string literal (xml explain plan):
So I can see the difference is that the variable invokes a Clustered Index Scan (clustered) while the string literal invokes a Key Lookup (clustered)... I will need to refer to google because I don't know really anything about the performance pros/cons of these.
EDIT EDIT
This worked (xml explain plan):
DECLARE @days INT
Set @days = 7
select c.DEBT_KEY
, c.new_value
, c.CHANGE_DATE
from changes c with (nolock)
where c.CHANGE_CODE = 3
and c.old_value = 4
and c.CHANGE_DATE >= dateadd(dd, -@days, getdate())
OPTION(OPTIMIZE FOR (@days = 7))
... I don't know why. Also I dislike the solution as it negates my purpose of using a variable, which is to put all variables at the top of the proc in order to mitigate the need to poke around in the code during the inevitable maintenance.