where (@IDCriteria is null or ID=@IDCriteria)
and (@MaxDateCriteria is null or Date<@MaxDateCriteria)
If you write this criteria, then SQL server will not know whether it is better to use the index for IDs or the index for Dates.
For proper optimization, it is far better to write separate queries for each case and use IF to guide you to the correct one.
IF @IDCriteria is not null and @MaxDateCriteria is not null
--query
WHERE ID = @IDCriteria and Date < @MaxDateCriteria
ELSE IF @IDCriteria is not null
--query
WHERE ID = @IDCriteria
ELSE IF @MaxDateCriteria is not null
--query
WHERE Date < @MaxDateCriteria
ELSE
--query
WHERE 1 = 1
If you expect to need different plans out of the optimizer, you need to write different queries to get them!!
Would generating SQL code containing only the needed where clauses be notably faster?
Yes - if you expect the optimizer to choose between different plans.
Edit:
DECLARE @CustomerNumber int, @CustomerName varchar(30)
SET @CustomerNumber = 123
SET @CustomerName = '123'
SELECT * FROM Customers
WHERE (CustomerNumber = @CustomerNumber OR @CustomerNumber is null)
AND (CustomerName = @CustomerName OR @CustomerName is null)
CustomerName and CustomerNumber are indexed. Optimizer says : "Clustered
Index Scan with parallelization". You can't write a worse single table query.
Edit : I've around 20 possible parameters, and each combination of n non-null parameters can happen.
We had a similar "search" functionality in our database. When we looked at the actual queries issued, 99.9% of them used an AccountIdentifier. In your case, I suspect either one column is -always supplied- or one of two columns are always supplied. This would lead to 2 or 3 cases respectively.
It's not important to remove OR's from the whole structure. It is important to remove OR's from the column/s that you expect the optimizer to use to access the indexes.