That’s when it all gets blown away
At one point or another in everyone’s SQL-querying career, they end up writing a query that goes something like this:
WHERE (@thing1 is NULL or whatever = @thing1)
These are often called optional parameters, and if you spend any time looking at queries, this will make you shudder for many reasons. Poor cardinality estimates, full scans, etc.
One thing that often gets overlooked is that queries constructed like this don’t register missing index requests.
As usual, using the Stack Overflow database for a demo.
With literal values, the optimizer goes into index matching mode, finds nothing helpful, and tells you all about it. The missing index request is pretty predictable, on DisplayName and Reputation. Makes sense so far, right?
What about with NULL variables?
You may blame the NULLs, but it’s not their fault.
What about with a RECOMPILE hint? Someone on the internet told me that if I use RECOMPILE I’ll get an optimal plan.
Someone on the internet was, well, not wrong, but not right either. By most standards, you’ll get an optimal plan. But still no missing index request.
Using a stored procedure doesn’t help with that, either (unless you recompile, but that may not be ideal for other reasons).
If we add an index with the correct definition, all of those queries will use it as written.
CREATE INDEX ix_helper ON dbo.Users (DisplayName, Reputation);
That’s not exactly the problem. Nor is the missing index request being missing a direct affront to anyone who has been tuning queries for more than 30 seconds. It’s obvious what a good enough index would be for this query.
What could be very misleading is if you’re using the DMVs to round up missing index requests, you’re unfamiliar with the overall schema and current index design, or if the optional parameter searches are part of a larger query where the index usage patterns being sub optimal aren’t apparent.
The bottom line on this type of search is that it’s not SARGable. Like using functions and other icky-messies across joins and where clauses, it will prevent missing index requests from popping up. And while missing index requests aren’t perfect, they are a valuable workload analysis tool, especially to beginners.
Thanks for reading!
Brent says: This is such a good example of why you need at least 3 tuning passes for performance tuning: run sp_BlitzIndex looking for obvious index improvements, then run sp_BlitzCache to tune the queries that are still slow, then after tuning them, run sp_BlitzIndex one more time to catch the new missing index requests.