patternMinor
How does the T-SQL optimizer handle "and false"
Viewed 0 times
thehowhandlesqlfalsedoesoptimizerand
Problem
In SQL SERVER 2008 I'm thinking about a query such as:
Given that
I'm hoping the optimizer is smart enough to see the 'and false' and not waste time with it.
SELECT ...
FROM ...
WHERE ...
AND @a=1
UNION
SELECT ...
FROM ...
WHERE ...
AND @a=2Given that
@a is clearly the same value, and therefore either the first SELECT returns results or the second SELECT does, will the query optimizer identify one of the queries as false and not run it? Would it be better for me to put them in an IF statement? The actual query is a bit more complicated than written of course, so the if would make it like 4 different queries, which would be a pain to maintain. I'm hoping the optimizer is smart enough to see the 'and false' and not waste time with it.
Solution
With respect to your question
will the query optimizer identify one of the queries as false and not
run it?
You'd need to check the execution plans. An example below where it doesn't.
Output
Notice that
Both the Startup Expression and number of executions are shown in the operator tool tips as below.
With regard to the other part of your question
Would it be better for me to put them in an IF statement?
Yes probably despite that. You're then guaranteed that the behaviour that you get is that which you want. Also even though
Better still might be to use an
will the query optimizer identify one of the queries as false and not
run it?
You'd need to check the execution plans. An example below where it doesn't.
DECLARE @P INT =1
SET STATISTICS IO ON;
SELECT name
FROM sys.objects
WHERE type='P' AND @P=1
UNION
SELECT name
FROM master..spt_values
WHERE number >0 AND @P=0Output
Table 'Worktable'. Scan count 0, logical reads 0
Table 'sysschobjs'. Scan count 1, logical reads 5Notice that
master..spt_values was not touched in the query execution. The reason for this is that the seek on this table is under a filter with a start up expression predicate of [@P]=(0). As this condition is not met the seek is never actually executed.Both the Startup Expression and number of executions are shown in the operator tool tips as below.
With regard to the other part of your question
Would it be better for me to put them in an IF statement?
Yes probably despite that. You're then guaranteed that the behaviour that you get is that which you want. Also even though
master..spt_values doesn't have any pages read above it does still have an IS lock taken out against it (which doesn't happen in the IF ... ELSE version)Better still might be to use an
If that calls separate stored procedures for each branch. You haven't shown the rest of your code but one possible issue with these mutually exclusive branches might be parameter sniffing. The batch will be compiled as per the first set of parameters seen. These might be wholly unsuitable for the other branch(es). Splitting into child batches allows each branch to be compiled separately taking into account the parameter values that actually occurred when that branch was executed.Code Snippets
DECLARE @P INT =1
SET STATISTICS IO ON;
SELECT name
FROM sys.objects
WHERE type='P' AND @P=1
UNION
SELECT name
FROM master..spt_values
WHERE number >0 AND @P=0Table 'Worktable'. Scan count 0, logical reads 0
Table 'sysschobjs'. Scan count 1, logical reads 5Context
StackExchange Database Administrators Q#25496, answer score: 4
Revisions (0)
No revisions yet.