I am writing a stored procedure that works with a heavy select statement. The stored procedure takes in about 15 parameters to act as a filter, all of which are NULLable.
There are two things the parameters generally do – check if x is between high and low or check if column value is in y.
My main concern is how I write the where clause.
Example: Dynamic SQL is notoriously slow, so I don’t want to write the where clause and then pass it to exec.
I don’t want to do if High = null then High = max because then I’ll still have a between statement that takes up processing power and has no use.
I don’t want to do an (if High = null or X <= High) because the null check would still be processed for every row and I heard rumors that would mess with indexes.
In short, I’m looking for guidance in the best practice that takes performance into account.
Dynamic SQL used to be slow because execution plans for dynamically generated SQL weren’t cached. This is no longer the case and execution plans for dynamic SQL queries will be cached as long as the query text is identical. This means that you should:
As long as you do this then your query plans should be cached (one for each possible query variation) and dynamic SQL won’t be any slower than any normal query.
Your other suggestions (setting various parameters to NULL) is to be avoided and may in fact perform quite badly – statements can only have one cached query plan, however the optimal query plan will depend on the parameters and may be very different depending on the values supplied.
For example one set of parameters might result in most of the table being returned, in which case a table scan might be optimal. Another set of parameters might result in a single row being returned in which case a row lookup might be optimal. SQL Server must choose to cache one of these two plans (probably the most optimal one based on the parameters supplied the first time the query is run), however whatever plan it chooses the query will probably perform badly in the opposite scenario. (this is an over simplification, however I have seen variations of this happen and it can have a very significant performance impact).
Ultimately this will mean that either:
The other disadvantage of your alternative aproaches is that it will result in a more complex query, which can make it difficult for the query optimiser to optimise the query properly.
For these reasons I’d say that dynamic SQL is definitely the better choice.